Module Name: src Committed By: knakahara Date: Wed Dec 14 11:19:15 UTC 2016
Modified Files: src/sys/net: if_etherip.h if_gif.c if_gif.h src/sys/netinet: in_gif.c src/sys/netinet6: in6_gif.c Log Message: fix race of gif_softc->gif_ro when we send multiple flows over gif on NET_MPSAFE enabled kernel. make gif_softc->gif_ro percpu as well as ipforward_rt to resolve this race. and add future TODO comment for etherip(4). To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/sys/net/if_etherip.h cvs rdiff -u -r1.123 -r1.124 src/sys/net/if_gif.c cvs rdiff -u -r1.24 -r1.25 src/sys/net/if_gif.h cvs rdiff -u -r1.85 -r1.86 src/sys/netinet/in_gif.c cvs rdiff -u -r1.81 -r1.82 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_etherip.h diff -u src/sys/net/if_etherip.h:1.11 src/sys/net/if_etherip.h:1.12 --- src/sys/net/if_etherip.h:1.11 Sat Jul 28 00:43:24 2012 +++ src/sys/net/if_etherip.h Wed Dec 14 11:19:15 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_etherip.h,v 1.11 2012/07/28 00:43:24 matt Exp $ */ +/* $NetBSD: if_etherip.h,v 1.12 2016/12/14 11:19:15 knakahara Exp $ */ /* * Copyright (c) 2006, Hans Rosenfeld <rosenf...@grumpf.hope-2000.org> @@ -46,7 +46,11 @@ struct etherip_softc { struct ethercom sc_ec; struct sockaddr *sc_src; /* tunnel source address */ struct sockaddr *sc_dst; /* tunnel destination address */ - struct route sc_ro; /* cached inet route */ + struct route sc_ro; /* + * cached inet route + * TODO: + * we must make percpu when MP-ify + */ void *sc_si; /* softintr handle */ LIST_ENTRY(etherip_softc) etherip_list; /* list of etherip tunnels */ }; Index: src/sys/net/if_gif.c diff -u src/sys/net/if_gif.c:1.123 src/sys/net/if_gif.c:1.124 --- src/sys/net/if_gif.c:1.123 Thu Sep 15 06:59:32 2016 +++ src/sys/net/if_gif.c Wed Dec 14 11:19:15 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_gif.c,v 1.123 2016/09/15 06:59:32 knakahara Exp $ */ +/* $NetBSD: if_gif.c,v 1.124 2016/12/14 11:19:15 knakahara 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.123 2016/09/15 06:59:32 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.124 2016/12/14 11:19:15 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -240,6 +240,9 @@ gif_clone_create(struct if_clone *ifc, i gifattach0(sc); + sc->gif_ro_percpu = percpu_alloc(sizeof(struct route)); + KASSERTMSG(sc->gif_ro_percpu != NULL, + "failed to allocate sc->gif_ro_percpu"); LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list); return (0); } @@ -271,6 +274,14 @@ gifattach0(struct gif_softc *sc) bpf_attach(&sc->gif_if, DLT_NULL, sizeof(u_int)); } +void +gif_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused) +{ + struct route *ro = p; + + rtcache_free(ro); +} + static int gif_clone_destroy(struct ifnet *ifp) { @@ -281,8 +292,8 @@ gif_clone_destroy(struct ifnet *ifp) gif_delete_tunnel(&sc->gif_if); bpf_detach(ifp); if_detach(ifp); - rtcache_free(&sc->gif_ro); - + percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL); + percpu_free(sc->gif_ro_percpu, sizeof(struct route)); kmem_free(sc, sizeof(struct gif_softc)); return (0); Index: src/sys/net/if_gif.h diff -u src/sys/net/if_gif.h:1.24 src/sys/net/if_gif.h:1.25 --- src/sys/net/if_gif.h:1.24 Fri Jun 24 04:38:12 2016 +++ src/sys/net/if_gif.h Wed Dec 14 11:19:15 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_gif.h,v 1.24 2016/06/24 04:38:12 knakahara Exp $ */ +/* $NetBSD: if_gif.h,v 1.25 2016/12/14 11:19:15 knakahara Exp $ */ /* $KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $ */ /* @@ -38,6 +38,7 @@ #define _NET_IF_GIF_H_ #include <sys/queue.h> +#include <sys/percpu.h> #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -52,9 +53,7 @@ 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 */ - union { - struct route gifscr_ro; /* xxx */ - } gifsc_gifscr; + percpu_t *gif_ro_percpu; int gif_flags; const struct encaptab *encap_cookie4; const struct encaptab *encap_cookie6; @@ -62,8 +61,6 @@ struct gif_softc { }; #define GIF_ROUTE_TTL 10 -#define gif_ro gifsc_gifscr.gifscr_ro - #define GIF_MTU (1280) /* Default MTU */ #define GIF_MTU_MIN (1280) /* Minimum MTU */ #define GIF_MTU_MAX (8192) /* Maximum MTU */ @@ -71,6 +68,8 @@ struct gif_softc { /* Prototypes */ void gif_input(struct mbuf *, int, struct ifnet *); +void gif_rtcache_free_pc(void *, void *, struct cpu_info *); + #ifdef GIF_ENCAPCHECK int gif_encapcheck(struct mbuf *, int, int, void *); #endif Index: src/sys/netinet/in_gif.c diff -u src/sys/netinet/in_gif.c:1.85 src/sys/netinet/in_gif.c:1.86 --- src/sys/netinet/in_gif.c:1.85 Mon Dec 12 03:55:57 2016 +++ src/sys/netinet/in_gif.c Wed Dec 14 11:19:15 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: in_gif.c,v 1.85 2016/12/12 03:55:57 ozaki-r Exp $ */ +/* $NetBSD: in_gif.c,v 1.86 2016/12/14 11:19:15 knakahara 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.85 2016/12/12 03:55:57 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.86 2016/12/14 11:19:15 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -83,6 +83,7 @@ int in_gif_output(struct ifnet *ifp, int family, struct mbuf *m) { struct rtentry *rt; + struct route *ro; 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); @@ -170,21 +171,26 @@ in_gif_output(struct ifnet *ifp, int fam bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); sockaddr_in_init(&u.dst4, &sin_dst->sin_addr, 0); - if ((rt = rtcache_lookup(&sc->gif_ro, &u.dst)) == NULL) { + + ro = percpu_getref(sc->gif_ro_percpu); + if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) { + percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; } /* If the route constitutes infinite encapsulation, punt. */ if (rt->rt_ifp == ifp) { - rtcache_unref(rt, &sc->gif_ro); - rtcache_free(&sc->gif_ro); + rtcache_unref(rt, ro); + rtcache_free(ro); + percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; /*XXX*/ } - rtcache_unref(rt, &sc->gif_ro); + rtcache_unref(rt, ro); - error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL); + error = ip_output(m, NULL, ro, 0, NULL, NULL); + percpu_putref(sc->gif_ro_percpu); return (error); } @@ -399,7 +405,7 @@ in_gif_detach(struct gif_softc *sc) error = in_gif_pause(sc); - rtcache_free(&sc->gif_ro); + percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL); return error; } Index: src/sys/netinet6/in6_gif.c diff -u src/sys/netinet6/in6_gif.c:1.81 src/sys/netinet6/in6_gif.c:1.82 --- src/sys/netinet6/in6_gif.c:1.81 Mon Dec 12 03:55:57 2016 +++ src/sys/netinet6/in6_gif.c Wed Dec 14 11:19:15 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_gif.c,v 1.81 2016/12/12 03:55:57 ozaki-r Exp $ */ +/* $NetBSD: in6_gif.c,v 1.82 2016/12/14 11:19:15 knakahara 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.81 2016/12/12 03:55:57 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.82 2016/12/14 11:19:15 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -86,6 +86,7 @@ int in6_gif_output(struct ifnet *ifp, int family, struct mbuf *m) { struct rtentry *rt; + struct route *ro; 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); @@ -176,20 +177,23 @@ in6_gif_output(struct ifnet *ifp, int fa ip6->ip6_flow |= htonl((u_int32_t)otos << 20); sockaddr_in6_init(&u.dst6, &sin6_dst->sin6_addr, 0, 0, 0); - rt = rtcache_lookup(&sc->gif_ro, &u.dst); + ro = percpu_getref(sc->gif_ro_percpu); + rt = rtcache_lookup(ro, &u.dst); if (rt == NULL) { + percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; } /* If the route constitutes infinite encapsulation, punt. */ if (rt->rt_ifp == ifp) { - rtcache_unref(rt, &sc->gif_ro); - rtcache_free(&sc->gif_ro); + rtcache_unref(rt, ro); + rtcache_free(ro); + percpu_putref(sc->gif_ro_percpu); m_freem(m); return ENETUNREACH; /* XXX */ } - rtcache_unref(rt, &sc->gif_ro); + rtcache_unref(rt, ro); #ifdef IPV6_MINMTU /* @@ -197,11 +201,11 @@ in6_gif_output(struct ifnet *ifp, int fa * it is too painful to ask for resend of inner packet, to achieve * path MTU discovery for encapsulated packets. */ - error = ip6_output(m, 0, &sc->gif_ro, IPV6_MINMTU, NULL, NULL, NULL); + error = ip6_output(m, 0, ro, IPV6_MINMTU, NULL, NULL, NULL); #else - error = ip6_output(m, 0, &sc->gif_ro, 0, NULL, NULL, NULL); + error = ip6_output(m, 0, ro, 0, NULL, NULL, NULL); #endif - + percpu_putref(sc->gif_ro_percpu); return (error); } @@ -402,7 +406,7 @@ in6_gif_detach(struct gif_softc *sc) error = in6_gif_pause(sc); - rtcache_free(&sc->gif_ro); + percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL); return error; } @@ -426,6 +430,7 @@ in6_gif_ctlinput(int cmd, const struct s struct ip6ctlparam *ip6cp = NULL; struct ip6_hdr *ip6; const struct sockaddr_in6 *dst6; + struct route *ro; if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) @@ -454,13 +459,15 @@ in6_gif_ctlinput(int cmd, const struct s if (sc->gif_psrc->sa_family != AF_INET6) return NULL; - dst6 = satocsin6(rtcache_getdst(&sc->gif_ro)); + ro = percpu_getref(sc->gif_ro_percpu); + dst6 = satocsin6(rtcache_getdst(ro)); /* XXX scope */ if (dst6 == NULL) ; else if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr)) - rtcache_free(&sc->gif_ro); + rtcache_free(ro); + percpu_putref(sc->gif_ro_percpu); return NULL; }