Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Invalidate rtcache based on a global generation counter



details:   https://anonhg.NetBSD.org/src/rev/754f3530f76d
branches:  trunk
changeset: 826661:754f3530f76d
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu Sep 21 07:15:34 2017 +0000

description:
Invalidate rtcache based on a global generation counter

The change introduces a global generation counter that is incremented when any
routes have been added or deleted. When a rtcache caches a rtentry into itself,
it also stores a snapshot of the generation counter. If the snapshot equals to
the global counter, the cache is still valid, otherwise invalidated.

One drawback of the change is that all rtcaches of all protocol families are
invalidated when any routes of any protocol families are added or deleted.
If that matters, we should have separate generation counters based on
protocol families.

This change removes LIST_ENTRY from struct route, which fixes a part of
PR kern/52515.

diffstat:

 sys/net/route.c                     |  122 +++++++----------------------------
 sys/net/route.h                     |    7 +-
 sys/netatalk/at_proto.c             |    5 +-
 sys/netinet/in_proto.c              |    5 +-
 sys/netinet6/in6_proto.c            |    5 +-
 sys/netmpls/mpls_proto.c            |    5 +-
 sys/netnatm/natm_proto.c            |    5 +-
 sys/rump/net/lib/libsockin/sockin.c |    6 +-
 sys/sys/domain.h                    |    3 +-
 9 files changed, 42 insertions(+), 121 deletions(-)

diffs (truncated from 468 to 300 lines):

diff -r 9ee78bca4a96 -r 754f3530f76d sys/net/route.c
--- a/sys/net/route.c   Thu Sep 21 07:07:28 2017 +0000
+++ b/sys/net/route.c   Thu Sep 21 07:15:34 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: route.c,v 1.198 2017/09/21 04:44:32 ozaki-r Exp $      */
+/*     $NetBSD: route.c,v 1.199 2017/09/21 07:15:34 ozaki-r Exp $      */
 
 /*-
  * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.198 2017/09/21 04:44:32 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.199 2017/09/21 07:15:34 ozaki-r Exp $");
 
 #include <sys/param.h>
 #ifdef RTFLUSH_DEBUG
@@ -203,6 +203,13 @@
  *     - if the caller runs in softint, the caller fails to fetch
  *     - otherwise, the caller waits for the update completed and retries
  *       to fetch (probably succeed to fetch for the second time)
+ * - rtcache invalidation
+ *   - There is a global generation counter that is incremented when
+ *     any routes have been added or deleted
+ *   - When a rtcache caches a rtentry into itself, it also stores
+ *     a snapshot of the generation counter
+ *   - If the snapshot equals to the global counter, the cache is valid,
+ *     otherwise the cache is invalidated
  */
 
 /*
@@ -239,6 +246,8 @@
 #define        RTCACHE_WLOCKED()       false
 #endif
 
+static uint64_t rtcache_generation;
+
 /*
  * mutex and cv that are used to wait for references to a rtentry left
  * before updating the rtentry.
@@ -271,14 +280,11 @@
 static kauth_listener_t route_listener;
 
 static int rtdeletemsg(struct rtentry *);
-static void rtflushall(int);
 
 static void rt_maskedcopy(const struct sockaddr *,
     struct sockaddr *, const struct sockaddr *);
 
-static void rtcache_clear(struct route *);
-static void rtcache_clear_rtentry(int, struct rtentry *);
-static void rtcache_invalidate(struct dom_rtlist *);
+static void rtcache_invalidate(void);
 
 static void rt_ref(struct rtentry *);
 
@@ -491,40 +497,17 @@
 }
 
 static void
-rtflushall(int family)
+rtcache_invalidate(void)
 {
-       struct domain *dom;
 
        if (rtcache_debug())
                printf("%s: enter\n", __func__);
 
-       if ((dom = pffinddomain(family)) == NULL)
-               return;
-
        RTCACHE_WLOCK();
-       rtcache_invalidate(&dom->dom_rtcache);
+       rtcache_generation++;
        RTCACHE_UNLOCK();
 }
 
-static void
-rtcache(struct route *ro)
-{
-       struct domain *dom;
-
-       RTCACHE_ASSERT_WLOCK();
-
-       rtcache_invariants(ro);
-       KASSERT(ro->_ro_rt != NULL);
-       KASSERT(ro->ro_invalid == false);
-       KASSERT(rtcache_getdst(ro) != NULL);
-
-       if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) == NULL)
-               return;
-
-       LIST_INSERT_HEAD(&dom->dom_rtcache, ro, ro_rtcache_next);
-       rtcache_invariants(ro);
-}
-
 #ifdef RT_DEBUG
 static void
 dump_rt(const struct rtentry *rt)
@@ -1251,7 +1234,7 @@
                RT_UNLOCK();
                need_unlock = false;
                rt_timer_remove_all(rt);
-               rtcache_clear_rtentry(dst->sa_family, rt);
+               rtcache_invalidate();
 #if defined(INET) || defined(INET6)
                if (netmask != NULL)
                        lltable_prefix_free(dst->sa_family, dst, netmask, 0);
@@ -1346,7 +1329,7 @@
                }
                RT_UNLOCK();
                need_unlock = false;
-               rtflushall(dst->sa_family);
+               rtcache_invalidate();
                break;
        case RTM_GET:
                if (netmask != NULL) {
@@ -1893,14 +1876,13 @@
 
        if (rtcache_getdst(ro) == NULL)
                return NULL;
-       ro->ro_invalid = false;
        rt = rtalloc1(rtcache_getdst(ro), flag);
        if (rt != NULL && ISSET(rt->rt_flags, RTF_UP)) {
                ro->_ro_rt = rt;
+               ro->ro_rtcache_generation = rtcache_generation;
                KASSERT(!ISSET(rt->rt_flags, RTF_UPDATING));
                rtcache_ref(rt, ro);
                rt_unref(rt);
-               rtcache(ro);
        } else if (rt != NULL)
                rt_unref(rt);
 
@@ -1933,7 +1915,7 @@
 {
        struct rtentry *rt;
        RTCACHE_WLOCK();
-       rtcache_clear(ro);
+       ro->_ro_rt = NULL;
        rt = _rtcache_init(ro, clone);
        RTCACHE_UNLOCK();
        return rt;
@@ -1958,9 +1940,8 @@
                goto out;
 
        RTCACHE_WLOCK();
-       new_ro->ro_invalid = false;
-       if ((new_ro->_ro_rt = rt) != NULL)
-               rtcache(new_ro);
+       new_ro->_ro_rt = rt;
+       new_ro->ro_rtcache_generation = rtcache_generation;
        rtcache_invariants(new_ro);
        RTCACHE_UNLOCK();
 out:
@@ -1968,8 +1949,6 @@
        return;
 }
 
-static struct dom_rtlist invalid_routes = LIST_HEAD_INITIALIZER(dom_rtlist);
-
 #if defined(RT_DEBUG) && defined(NET_MPSAFE)
 static void
 rtcache_trace(const char *func, struct rtentry *rt, struct route *ro)
@@ -2023,7 +2002,8 @@
        rt = ro->_ro_rt;
        rtcache_invariants(ro);
 
-       if (ro->ro_invalid) {
+       if (ro->ro_rtcache_generation != rtcache_generation) {
+               /* The cache is invalidated */
                rt = NULL;
                goto out;
        }
@@ -2063,57 +2043,6 @@
        return rt;
 }
 
-static void
-rtcache_invalidate(struct dom_rtlist *rtlist)
-{
-       struct route *ro;
-
-       RTCACHE_ASSERT_WLOCK();
-
-       while ((ro = LIST_FIRST(rtlist)) != NULL) {
-               rtcache_invariants(ro);
-               KASSERT(ro->_ro_rt != NULL);
-               ro->ro_invalid = true;
-               LIST_REMOVE(ro, ro_rtcache_next);
-               LIST_INSERT_HEAD(&invalid_routes, ro, ro_rtcache_next);
-               rtcache_invariants(ro);
-       }
-}
-
-static void
-rtcache_clear_rtentry(int family, struct rtentry *rt)
-{
-       struct domain *dom;
-       struct route *ro, *nro;
-
-       if ((dom = pffinddomain(family)) == NULL)
-               return;
-
-       RTCACHE_WLOCK();
-       LIST_FOREACH_SAFE(ro, &dom->dom_rtcache, ro_rtcache_next, nro) {
-               if (ro->_ro_rt == rt)
-                       rtcache_clear(ro);
-       }
-       RTCACHE_UNLOCK();
-}
-
-static void
-rtcache_clear(struct route *ro)
-{
-
-       RTCACHE_ASSERT_WLOCK();
-
-       rtcache_invariants(ro);
-       if (ro->_ro_rt == NULL)
-               return;
-
-       LIST_REMOVE(ro, ro_rtcache_next);
-
-       ro->_ro_rt = NULL;
-       ro->ro_invalid = false;
-       rtcache_invariants(ro);
-}
-
 struct rtentry *
 rtcache_lookup2(struct route *ro, const struct sockaddr *dst,
     int clone, int *hitp)
@@ -2140,7 +2069,7 @@
        if (rt == NULL) {
                RTCACHE_UNLOCK();
                RTCACHE_WLOCK();
-               rtcache_clear(ro);
+               ro->_ro_rt = NULL;
                goto miss;
        }
 
@@ -2167,7 +2096,8 @@
 {
 
        RTCACHE_ASSERT_WLOCK();
-       rtcache_clear(ro);
+
+       ro->_ro_rt = NULL;
        if (ro->ro_sa != NULL) {
                sockaddr_free(ro->ro_sa);
                ro->ro_sa = NULL;
@@ -2194,7 +2124,7 @@
        rtcache_invariants(ro);
        if (ro->ro_sa != NULL) {
                if (ro->ro_sa->sa_family == sa->sa_family) {
-                       rtcache_clear(ro);
+                       ro->_ro_rt = NULL;
                        sockaddr_copy(ro->ro_sa, ro->ro_sa->sa_len, sa);
                        rtcache_invariants(ro);
                        return 0;
diff -r 9ee78bca4a96 -r 754f3530f76d sys/net/route.h
--- a/sys/net/route.h   Thu Sep 21 07:07:28 2017 +0000
+++ b/sys/net/route.h   Thu Sep 21 07:15:34 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: route.h,v 1.113 2017/06/16 02:24:54 ozaki-r Exp $      */
+/*     $NetBSD: route.h,v 1.114 2017/09/21 07:15:34 ozaki-r Exp $      */
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -64,8 +64,7 @@
 struct route {
        struct  rtentry         *_ro_rt;
        struct  sockaddr        *ro_sa;
-       LIST_ENTRY(route)       ro_rtcache_next;
-       bool                    ro_invalid;
+       uint64_t                ro_rtcache_generation;
        struct  psref           ro_psref;
        int                     ro_bound;
 };
@@ -458,8 +457,8 @@
 static inline void
 rtcache_invariants(const struct route *ro)
 {
+
        KASSERT(ro->ro_sa != NULL || ro->_ro_rt == NULL);
-       KASSERT(!ro->ro_invalid || ro->_ro_rt != NULL);
 }
 
 static inline struct rtentry *
diff -r 9ee78bca4a96 -r 754f3530f76d sys/netatalk/at_proto.c
--- a/sys/netatalk/at_proto.c   Thu Sep 21 07:07:28 2017 +0000
+++ b/sys/netatalk/at_proto.c   Thu Sep 21 07:15:34 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: at_proto.c,v 1.21 2016/01/21 15:41:30 riastradh Exp $  */
+/*     $NetBSD: at_proto.c,v 1.22 2017/09/21 07:15:34 ozaki-r Exp $    */
 
 /*
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -27,7 +27,7 @@
  */



Home | Main Index | Thread Index | Old Index