Source-Changes-HG archive

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

[src/trunk]: src/sys fix race of gif_softc->gif_ro when we send multiple flow...



details:   https://anonhg.NetBSD.org/src/rev/9c4a387c6772
branches:  trunk
changeset: 349551:9c4a387c6772
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Wed Dec 14 11:19:15 2016 +0000

description:
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).

diffstat:

 sys/net/if_etherip.h   |   8 ++++++--
 sys/net/if_gif.c       |  19 +++++++++++++++----
 sys/net/if_gif.h       |  11 +++++------
 sys/netinet/in_gif.c   |  22 ++++++++++++++--------
 sys/netinet6/in6_gif.c |  31 +++++++++++++++++++------------
 5 files changed, 59 insertions(+), 32 deletions(-)

diffs (293 lines):

diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_etherip.h
--- a/sys/net/if_etherip.h      Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_etherip.h      Wed Dec 14 11:19:15 2016 +0000
@@ -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 <rosenfeld%grumpf.hope-2000.org@localhost>
@@ -46,7 +46,11 @@
        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    */
 };
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_gif.c  Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
 
        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 @@
        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_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);
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/net/if_gif.h
--- a/sys/net/if_gif.h  Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/net/if_gif.h  Wed Dec 14 11:19:15 2016 +0000
@@ -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 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 @@
 };
 #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 @@
 /* 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
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/netinet/in_gif.c
--- a/sys/netinet/in_gif.c      Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/netinet/in_gif.c      Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
 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 @@
        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 @@
 
        error = in_gif_pause(sc);
 
-       rtcache_free(&sc->gif_ro);
+       percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);
 
        return error;
 }
diff -r 175bbdc5b2e1 -r 9c4a387c6772 sys/netinet6/in6_gif.c
--- a/sys/netinet6/in6_gif.c    Wed Dec 14 10:46:12 2016 +0000
+++ b/sys/netinet6/in6_gif.c    Wed Dec 14 11:19:15 2016 +0000
@@ -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 @@
 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 @@
        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 @@
         * 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 @@
 
        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 @@
        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 @@
        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;
 }
 



Home | Main Index | Thread Index | Old Index