Module Name: src Committed By: snj Date: Tue Oct 24 08:47:24 UTC 2017
Modified Files: src/sys/net [netbsd-8]: if_gif.c if_gif.h src/sys/netinet [netbsd-8]: in_gif.c src/sys/netinet6 [netbsd-8]: in6_gif.c Log Message: Pull up following revision(s) (requested by knahakara in ticket #303): sys/net/if_gif.c: 1.129-1.130 sys/net/if_gif.h: 1.26-1.27 sys/netinet/in_gif.c: 1.88 sys/netinet6/in6_gif.c: 1.86 add lock for percpu route like l2tp(4). -- add lock for sclist to exclude ifconfig gifX add/delete and ifconfig gifX tunnel -- update locking notes. To generate a diff of this commit: cvs rdiff -u -r1.126.2.2 -r1.126.2.3 src/sys/net/if_gif.c cvs rdiff -u -r1.25 -r1.25.8.1 src/sys/net/if_gif.h cvs rdiff -u -r1.87 -r1.87.8.1 src/sys/netinet/in_gif.c cvs rdiff -u -r1.85 -r1.85.6.1 src/sys/netinet6/in6_gif.c 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/if_gif.c diff -u src/sys/net/if_gif.c:1.126.2.2 src/sys/net/if_gif.c:1.126.2.3 --- src/sys/net/if_gif.c:1.126.2.2 Wed Aug 9 05:51:50 2017 +++ src/sys/net/if_gif.c Tue Oct 24 08:47:24 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_gif.c,v 1.126.2.2 2017/08/09 05:51:50 snj Exp $ */ +/* $NetBSD: if_gif.c,v 1.126.2.3 2017/10/24 08:47:24 snj Exp $ */ /* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.126.2.2 2017/08/09 05:51:50 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.126.2.3 2017/10/24 08:47:24 snj Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -96,7 +96,14 @@ __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1 /* * gif global variable definitions */ -static LIST_HEAD(, gif_softc) gif_softc_list; +LIST_HEAD(gif_sclist, gif_softc); +static struct { + struct gif_sclist list; + kmutex_t lock; +} gif_softcs __cacheline_aligned; + +static void gif_ro_init_pc(void *, void *, struct cpu_info *); +static void gif_ro_fini_pc(void *, void *, struct cpu_info *); static void gifattach0(struct gif_softc *); static int gif_output(struct ifnet *, struct mbuf *, @@ -205,7 +212,8 @@ static void gifinit(void) { - LIST_INIT(&gif_softc_list); + mutex_init(&gif_softcs.lock, MUTEX_DEFAULT, IPL_NONE); + LIST_INIT(&gif_softcs.list); if_clone_attach(&gif_cloner); gif_sysctl_setup(); @@ -216,8 +224,11 @@ gifdetach(void) { int error = 0; - if (!LIST_EMPTY(&gif_softc_list)) + mutex_enter(&gif_softcs.lock); + if (!LIST_EMPTY(&gif_softcs.list)) { + mutex_exit(&gif_softcs.lock); error = EBUSY; + } if (error == 0) { if_clone_detach(&gif_cloner); @@ -238,8 +249,12 @@ gif_clone_create(struct if_clone *ifc, i gifattach0(sc); - sc->gif_ro_percpu = percpu_alloc(sizeof(struct route)); - LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list); + sc->gif_ro_percpu = percpu_alloc(sizeof(struct gif_ro)); + percpu_foreach(sc->gif_ro_percpu, gif_ro_init_pc, NULL); + + mutex_enter(&gif_softcs.lock); + LIST_INSERT_HEAD(&gif_softcs.list, sc, gif_list); + mutex_exit(&gif_softcs.lock); return (0); } @@ -270,12 +285,30 @@ gifattach0(struct gif_softc *sc) bpf_attach(&sc->gif_if, DLT_NULL, sizeof(u_int)); } +static void +gif_ro_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused) +{ + struct gif_ro *gro = p; + + mutex_init(&gro->gr_lock, MUTEX_DEFAULT, IPL_NONE); +} + +static void +gif_ro_fini_pc(void *p, void *arg __unused, struct cpu_info *ci __unused) +{ + struct gif_ro *gro = p; + + rtcache_free(&gro->gr_ro); + + mutex_destroy(&gro->gr_lock); +} + void gif_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused) { - struct route *ro = p; + struct gif_ro *gro = p; - rtcache_free(ro); + rtcache_free(&gro->gr_ro); } static int @@ -288,8 +321,10 @@ gif_clone_destroy(struct ifnet *ifp) gif_delete_tunnel(&sc->gif_if); bpf_detach(ifp); if_detach(ifp); - percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL); - percpu_free(sc->gif_ro_percpu, sizeof(struct route)); + + percpu_foreach(sc->gif_ro_percpu, gif_ro_fini_pc, NULL); + percpu_free(sc->gif_ro_percpu, sizeof(struct gif_ro)); + kmem_free(sc, sizeof(struct gif_softc)); return (0); @@ -969,7 +1004,8 @@ gif_set_tunnel(struct ifnet *ifp, struct return error; } - LIST_FOREACH(sc2, &gif_softc_list, gif_list) { + mutex_enter(&gif_softcs.lock); + LIST_FOREACH(sc2, &gif_softcs.list, gif_list) { if (sc2 == sc) continue; if (!sc2->gif_pdst || !sc2->gif_psrc) @@ -978,12 +1014,14 @@ gif_set_tunnel(struct ifnet *ifp, struct if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 && sockaddr_cmp(sc2->gif_psrc, src) == 0) { /* continue to use the old configureation. */ + mutex_exit(&gif_softcs.lock); error = EADDRNOTAVAIL; goto out; } /* XXX both end must be valid? (I mean, not 0.0.0.0) */ } + mutex_exit(&gif_softcs.lock); nsrc = sockaddr_dup(src, M_WAITOK); ndst = sockaddr_dup(dst, M_WAITOK); Index: src/sys/net/if_gif.h diff -u src/sys/net/if_gif.h:1.25 src/sys/net/if_gif.h:1.25.8.1 --- src/sys/net/if_gif.h:1.25 Wed Dec 14 11:19:15 2016 +++ src/sys/net/if_gif.h Tue Oct 24 08:47:24 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_gif.h,v 1.25 2016/12/14 11:19:15 knakahara Exp $ */ +/* $NetBSD: if_gif.h,v 1.25.8.1 2017/10/24 08:47:24 snj Exp $ */ /* $KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $ */ /* @@ -49,11 +49,16 @@ struct encaptab; +struct gif_ro { + struct route gr_ro; + kmutex_t gr_lock; +}; + struct gif_softc { struct ifnet gif_if; /* common area - must be at the top */ struct sockaddr *gif_psrc; /* Physical src addr */ struct sockaddr *gif_pdst; /* Physical dst addr */ - percpu_t *gif_ro_percpu; + percpu_t *gif_ro_percpu; /* struct gif_ro */ int gif_flags; const struct encaptab *encap_cookie4; const struct encaptab *encap_cookie6; @@ -76,6 +81,17 @@ int gif_encapcheck(struct mbuf *, int, i /* * Locking notes: - * - All members of struct si_sync are protected by si_lock (an adaptive mutex) + * + gif_softc_list is protected by gif_softcs.lock (an adaptive mutex) + * gif_softc_list is list of all gif_softcs. It is used by ioctl + * context only. + * + Members of struct gif_softc except for gif_ro_percpu are protected by + * - encap_lock for writer + * - stopping processing when writer begin to run + * for reader(Tx and Rx processing) + * + Each CPU's gif_ro.gr_ro of gif_ro_percpu are protected by + * percpu'ed gif_ro.gr_lock. + * + * Locking order: + * - encap_lock => gif_softcs.lock */ #endif /* !_NET_IF_GIF_H_ */ Index: src/sys/netinet/in_gif.c diff -u src/sys/netinet/in_gif.c:1.87 src/sys/netinet/in_gif.c:1.87.8.1 --- src/sys/netinet/in_gif.c:1.87 Fri Jan 6 03:25:13 2017 +++ src/sys/netinet/in_gif.c Tue Oct 24 08:47:24 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in_gif.c,v 1.87 2017/01/06 03:25:13 knakahara Exp $ */ +/* $NetBSD: in_gif.c,v 1.87.8.1 2017/10/24 08:47:24 snj Exp $ */ /* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.87 2017/01/06 03:25:13 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.87.8.1 2017/10/24 08:47:24 snj Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -84,6 +84,7 @@ in_gif_output(struct ifnet *ifp, int fam { struct rtentry *rt; struct route *ro; + struct gif_ro *gro; struct gif_softc *sc = ifp->if_softc; struct sockaddr_in *sin_src = satosin(sc->gif_psrc); struct sockaddr_in *sin_dst = satosin(sc->gif_pdst); @@ -166,8 +167,11 @@ in_gif_output(struct ifnet *ifp, int fam return ENOBUFS; bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); - ro = percpu_getref(sc->gif_ro_percpu); + gro = percpu_getref(sc->gif_ro_percpu); + mutex_enter(&gro->gr_lock); + ro = &gro->gr_ro; if ((rt = rtcache_lookup(ro, sc->gif_pdst)) == NULL) { + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; @@ -177,6 +181,7 @@ in_gif_output(struct ifnet *ifp, int fam if (rt->rt_ifp == ifp) { rtcache_unref(rt, ro); rtcache_free(ro); + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; /*XXX*/ @@ -184,6 +189,7 @@ in_gif_output(struct ifnet *ifp, int fam rtcache_unref(rt, ro); error = ip_output(m, NULL, ro, 0, NULL, NULL); + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); return (error); } Index: src/sys/netinet6/in6_gif.c diff -u src/sys/netinet6/in6_gif.c:1.85 src/sys/netinet6/in6_gif.c:1.85.6.1 --- src/sys/netinet6/in6_gif.c:1.85 Mon Jan 16 15:44:47 2017 +++ src/sys/netinet6/in6_gif.c Tue Oct 24 08:47:24 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_gif.c,v 1.85 2017/01/16 15:44:47 christos Exp $ */ +/* $NetBSD: in6_gif.c,v 1.85.6.1 2017/10/24 08:47:24 snj Exp $ */ /* $KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.85 2017/01/16 15:44:47 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.85.6.1 2017/10/24 08:47:24 snj Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -87,6 +87,7 @@ in6_gif_output(struct ifnet *ifp, int fa { struct rtentry *rt; struct route *ro; + struct gif_ro *gro; struct gif_softc *sc = ifp->if_softc; struct sockaddr_in6 *sin6_src = satosin6(sc->gif_psrc); struct sockaddr_in6 *sin6_dst = satosin6(sc->gif_pdst); @@ -172,9 +173,12 @@ in6_gif_output(struct ifnet *ifp, int fa ip6->ip6_flow &= ~ntohl(0xff00000); ip6->ip6_flow |= htonl((u_int32_t)otos << 20); - ro = percpu_getref(sc->gif_ro_percpu); + gro = percpu_getref(sc->gif_ro_percpu); + mutex_enter(&gro->gr_lock); + ro = &gro->gr_ro; rt = rtcache_lookup(ro, sc->gif_pdst); if (rt == NULL) { + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; @@ -184,6 +188,7 @@ in6_gif_output(struct ifnet *ifp, int fa if (rt->rt_ifp == ifp) { rtcache_unref(rt, ro); rtcache_free(ro); + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; /* XXX */ @@ -200,6 +205,7 @@ in6_gif_output(struct ifnet *ifp, int fa #else error = ip6_output(m, 0, ro, 0, NULL, NULL, NULL); #endif + mutex_exit(&gro->gr_lock); percpu_putref(sc->gif_ro_percpu); return (error); }