Module Name: src Committed By: ozaki-r Date: Thu Sep 21 07:15:35 UTC 2017
Modified Files: src/sys/net: route.c route.h src/sys/netatalk: at_proto.c src/sys/netinet: in_proto.c src/sys/netinet6: in6_proto.c src/sys/netmpls: mpls_proto.c src/sys/netnatm: natm_proto.c src/sys/rump/net/lib/libsockin: sockin.c src/sys/sys: domain.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.198 -r1.199 src/sys/net/route.c cvs rdiff -u -r1.113 -r1.114 src/sys/net/route.h cvs rdiff -u -r1.21 -r1.22 src/sys/netatalk/at_proto.c cvs rdiff -u -r1.123 -r1.124 src/sys/netinet/in_proto.c cvs rdiff -u -r1.117 -r1.118 src/sys/netinet6/in6_proto.c cvs rdiff -u -r1.30 -r1.31 src/sys/netmpls/mpls_proto.c cvs rdiff -u -r1.17 -r1.18 src/sys/netnatm/natm_proto.c cvs rdiff -u -r1.64 -r1.65 src/sys/rump/net/lib/libsockin/sockin.c cvs rdiff -u -r1.32 -r1.33 src/sys/sys/domain.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/route.c diff -u src/sys/net/route.c:1.198 src/sys/net/route.c:1.199 --- src/sys/net/route.c:1.198 Thu Sep 21 04:44:32 2017 +++ src/sys/net/route.c Thu Sep 21 07:15:34 2017 @@ -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 @@ static void rt_timer_timer(void *); * - 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 @@ static krwlock_t rtcache_lock __cacheli #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 int _rtcache_debug = 0; 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 @@ rt_init(void) } 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 @@ rtrequest1(int req, struct rt_addrinfo * 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 @@ rtrequest1(int req, struct rt_addrinfo * } RT_UNLOCK(); need_unlock = false; - rtflushall(dst->sa_family); + rtcache_invalidate(); break; case RTM_GET: if (netmask != NULL) { @@ -1893,14 +1876,13 @@ _rtcache_init(struct route *ro, int flag 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 @@ rtcache_update(struct route *ro, int clo { 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 @@ rtcache_copy(struct route *new_ro, struc 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 @@ out: 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 @@ retry: 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 @@ rtcache_validate(struct route *ro) 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 @@ rtcache_lookup2(struct route *ro, const if (rt == NULL) { RTCACHE_UNLOCK(); RTCACHE_WLOCK(); - rtcache_clear(ro); + ro->_ro_rt = NULL; goto miss; } @@ -2167,7 +2096,8 @@ rtcache_free_locked(struct route *ro) { 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_setdst_locked(struct route *ro, 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; Index: src/sys/net/route.h diff -u src/sys/net/route.h:1.113 src/sys/net/route.h:1.114 --- src/sys/net/route.h:1.113 Fri Jun 16 02:24:54 2017 +++ src/sys/net/route.h Thu Sep 21 07:15:34 2017 @@ -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 @@ struct rtentry * 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 * Index: src/sys/netatalk/at_proto.c diff -u src/sys/netatalk/at_proto.c:1.21 src/sys/netatalk/at_proto.c:1.22 --- src/sys/netatalk/at_proto.c:1.21 Thu Jan 21 15:41:30 2016 +++ src/sys/netatalk/at_proto.c Thu Sep 21 07:15:34 2017 @@ -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 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: at_proto.c,v 1.21 2016/01/21 15:41:30 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: at_proto.c,v 1.22 2017/09/21 07:15:34 ozaki-r Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -78,7 +78,6 @@ struct domain atalkdomain = { .dom_mowner = MOWNER_INIT("",""), .dom_sa_cmpofs = offsetof(struct sockaddr_at, sat_addr), .dom_sa_cmplen = sizeof(struct at_addr), - .dom_rtcache = LIST_HEAD_INITIALIZER(atalkdomain.dom_rtcache) }; int Index: src/sys/netinet/in_proto.c diff -u src/sys/netinet/in_proto.c:1.123 src/sys/netinet/in_proto.c:1.124 --- src/sys/netinet/in_proto.c:1.123 Fri Apr 14 02:43:27 2017 +++ src/sys/netinet/in_proto.c Thu Sep 21 07:15:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in_proto.c,v 1.123 2017/04/14 02:43:27 ozaki-r Exp $ */ +/* $NetBSD: in_proto.c,v 1.124 2017/09/21 07:15:34 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.123 2017/04/14 02:43:27 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.124 2017/09/21 07:15:34 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_mrouting.h" @@ -489,7 +489,6 @@ struct domain inetdomain = { .dom_sa_any = (const struct sockaddr *)&in_any, .dom_sockaddr_const_addr = sockaddr_in_const_addr, .dom_sockaddr_addr = sockaddr_in_addr, - .dom_rtcache = LIST_HEAD_INITIALIZER(inetdomain.dom_rtcache) }; u_char ip_protox[IPPROTO_MAX]; Index: src/sys/netinet6/in6_proto.c diff -u src/sys/netinet6/in6_proto.c:1.117 src/sys/netinet6/in6_proto.c:1.118 --- src/sys/netinet6/in6_proto.c:1.117 Fri Apr 14 02:43:28 2017 +++ src/sys/netinet6/in6_proto.c Thu Sep 21 07:15:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_proto.c,v 1.117 2017/04/14 02:43:28 ozaki-r Exp $ */ +/* $NetBSD: in6_proto.c,v 1.118 2017/09/21 07:15:35 ozaki-r Exp $ */ /* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.117 2017/04/14 02:43:28 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_proto.c,v 1.118 2017/09/21 07:15:35 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_gateway.h" @@ -490,7 +490,6 @@ struct domain inet6domain = { .dom_sa_cmplen = sizeof(struct in6_addr), .dom_sa_any = (const struct sockaddr *)&in6_any, .dom_sockaddr_externalize = sockaddr_in6_externalize, - .dom_rtcache = LIST_HEAD_INITIALIZER(inet6domain.dom_rtcache) }; #if 0 Index: src/sys/netmpls/mpls_proto.c diff -u src/sys/netmpls/mpls_proto.c:1.30 src/sys/netmpls/mpls_proto.c:1.31 --- src/sys/netmpls/mpls_proto.c:1.30 Mon Oct 3 11:06:06 2016 +++ src/sys/netmpls/mpls_proto.c Thu Sep 21 07:15:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mpls_proto.c,v 1.30 2016/10/03 11:06:06 ozaki-r Exp $ */ +/* $NetBSD: mpls_proto.c,v 1.31 2017/09/21 07:15:35 ozaki-r Exp $ */ /* * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mpls_proto.c,v 1.30 2016/10/03 11:06:06 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mpls_proto.c,v 1.31 2017/09/21 07:15:35 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -391,5 +391,4 @@ struct domain mplsdomain = { .dom_mowner = MOWNER_INIT("MPLS", ""), .dom_sa_cmpofs = offsetof(struct sockaddr_mpls, smpls_addr), .dom_sa_cmplen = sizeof(union mpls_shim), - .dom_rtcache = LIST_HEAD_INITIALIZER(mplsdomain.dom_rtcache) }; Index: src/sys/netnatm/natm_proto.c diff -u src/sys/netnatm/natm_proto.c:1.17 src/sys/netnatm/natm_proto.c:1.18 --- src/sys/netnatm/natm_proto.c:1.17 Mon Oct 3 11:06:06 2016 +++ src/sys/netnatm/natm_proto.c Thu Sep 21 07:15:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: natm_proto.c,v 1.17 2016/10/03 11:06:06 ozaki-r Exp $ */ +/* $NetBSD: natm_proto.c,v 1.18 2017/09/21 07:15:35 ozaki-r Exp $ */ /* * Copyright (c) 1996 Charles D. Cranor and Washington University. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: natm_proto.c,v 1.17 2016/10/03 11:06:06 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: natm_proto.c,v 1.18 2017/09/21 07:15:35 ozaki-r Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -105,7 +105,6 @@ struct domain natmdomain = { .dom_protosw = natmsw, .dom_protoswNPROTOSW = &natmsw[sizeof(natmsw)/sizeof(natmsw[0])], .dom_ifqueues = { &natmintrq, NULL }, - .dom_rtcache = LIST_HEAD_INITIALIZER(natmdomain.dom_rtcache) }; #ifdef NATM_STAT u_int natm_sodropcnt = 0; /* # mbufs dropped due to full sb */ Index: src/sys/rump/net/lib/libsockin/sockin.c diff -u src/sys/rump/net/lib/libsockin/sockin.c:1.64 src/sys/rump/net/lib/libsockin/sockin.c:1.65 --- src/sys/rump/net/lib/libsockin/sockin.c:1.64 Tue Nov 15 09:04:30 2016 +++ src/sys/rump/net/lib/libsockin/sockin.c Thu Sep 21 07:15:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sockin.c,v 1.64 2016/11/15 09:04:30 ozaki-r Exp $ */ +/* $NetBSD: sockin.c,v 1.65 2017/09/21 07:15:35 ozaki-r Exp $ */ /* * Copyright (c) 2008, 2009 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sockin.c,v 1.64 2016/11/15 09:04:30 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sockin.c,v 1.65 2017/09/21 07:15:35 ozaki-r Exp $"); #include <sys/param.h> #include <sys/condvar.h> @@ -162,7 +162,6 @@ struct domain sockindomain = { .dom_ifqueues = { NULL }, .dom_link = { NULL }, .dom_mowner = MOWNER_INIT("",""), - .dom_rtcache = { NULL }, .dom_sockaddr_cmp = NULL }; struct domain sockin6domain = { @@ -181,7 +180,6 @@ struct domain sockin6domain = { .dom_ifqueues = { NULL }, .dom_link = { NULL }, .dom_mowner = MOWNER_INIT("",""), - .dom_rtcache = { NULL }, .dom_sockaddr_cmp = NULL }; Index: src/sys/sys/domain.h diff -u src/sys/sys/domain.h:1.32 src/sys/sys/domain.h:1.33 --- src/sys/sys/domain.h:1.32 Wed Apr 22 19:46:08 2015 +++ src/sys/sys/domain.h Thu Sep 21 07:15:35 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: domain.h,v 1.32 2015/04/22 19:46:08 roy Exp $ */ +/* $NetBSD: domain.h,v 1.33 2017/09/21 07:15:35 ozaki-r Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -90,7 +90,6 @@ struct domain { struct mowner dom_mowner; uint_fast8_t dom_sa_cmpofs; uint_fast8_t dom_sa_cmplen; - struct dom_rtlist dom_rtcache; }; STAILQ_HEAD(domainhead,domain);