Source-Changes-HG archive

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

[src/trunk]: src/sys let gif(4) promise softint(9) contract (2/2) : ip_encap ...



details:   https://anonhg.NetBSD.org/src/rev/eeabdfedf817
branches:  trunk
changeset: 816400:eeabdfedf817
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Jul 04 04:17:25 2016 +0000

description:
let gif(4) promise softint(9) contract (2/2) : ip_encap side

The last commit does not care encaptab. This commit fixes encaptab race which
is used not only gif(4).

diffstat:

 sys/net/if_gif.c          |  41 +++++-----------------
 sys/net/if_stf.c          |  17 ++++++---
 sys/netinet/ip_encap.c    |  84 +++++++++++++++++++++++++++++++++++++++++++++-
 sys/netinet/ip_encap.h    |   5 ++-
 sys/netinet/ip_mroute.c   |   8 +++-
 sys/netipsec/xform_ipip.c |   7 ++-
 6 files changed, 116 insertions(+), 46 deletions(-)

diffs (truncated from 535 to 300 lines):

diff -r b07bdf72d60e -r eeabdfedf817 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Mon Jul 04 04:14:47 2016 +0000
+++ b/sys/net/if_gif.c  Mon Jul 04 04:17:25 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.114 2016/07/04 04:14:47 knakahara Exp $   */
+/*     $NetBSD: if_gif.c,v 1.115 2016/07/04 04:17:25 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.114 2016/07/04 04:14:47 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.115 2016/07/04 04:17:25 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -110,9 +110,6 @@
 static int     gif_encap_detach(struct gif_softc *);
 static void    gif_encap_pause(struct gif_softc *);
 
-static void    gif_list_lock_enter(void);
-static void    gif_list_lock_exit(void);
-
 static struct if_clone gif_cloner =
     IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
 
@@ -812,7 +809,7 @@
        int error;
 
        s = splsoftnet();
-       gif_list_lock_enter();
+       encap_lock_enter();
 
        LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
                if (sc2 == sc)
@@ -823,7 +820,7 @@
                if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 &&
                    sockaddr_cmp(sc2->gif_psrc, src) == 0) {
                        /* continue to use the old configureation. */
-                       gif_list_lock_exit();
+                       encap_lock_exit();
                        splx(s);
                        return EADDRNOTAVAIL;
                }
@@ -832,13 +829,13 @@
        }
 
        if ((nsrc = sockaddr_dup(src, M_WAITOK)) == NULL) {
-               gif_list_lock_exit();
+               encap_lock_exit();
                splx(s);
                return ENOMEM;
        }
        if ((ndst = sockaddr_dup(dst, M_WAITOK)) == NULL) {
                sockaddr_free(nsrc);
-               gif_list_lock_exit();
+               encap_lock_exit();
                splx(s);
                return ENOMEM;
        }
@@ -889,7 +886,7 @@
        else
                ifp->if_flags &= ~IFF_RUNNING;
 
-       gif_list_lock_exit();
+       encap_lock_exit();
        splx(s);
        return error;
 }
@@ -901,7 +898,7 @@
        int s;
 
        s = splsoftnet();
-       gif_list_lock_enter();
+       encap_lock_enter();
 
        gif_encap_pause(sc);
        if (sc->gif_psrc) {
@@ -925,26 +922,6 @@
        else
                ifp->if_flags &= ~IFF_RUNNING;
 
-       gif_list_lock_exit();
+       encap_lock_exit();
        splx(s);
 }
-
-static void
-gif_list_lock_enter(void)
-{
-
-       /* XXX future work
-        * should change interruptable lock.
-        */
-       KERNEL_LOCK(1, NULL);
-}
-
-static void
-gif_list_lock_exit(void)
-{
-
-       /* XXX future work
-        * should change interruptable lock.
-        */
-       KERNEL_UNLOCK_ONE(NULL);
-}
diff -r b07bdf72d60e -r eeabdfedf817 sys/net/if_stf.c
--- a/sys/net/if_stf.c  Mon Jul 04 04:14:47 2016 +0000
+++ b/sys/net/if_stf.c  Mon Jul 04 04:17:25 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_stf.c,v 1.91 2016/06/22 07:48:17 ozaki-r Exp $      */
+/*     $NetBSD: if_stf.c,v 1.92 2016/07/04 04:17:25 knakahara Exp $    */
 /*     $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
 
 /*
@@ -75,7 +75,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.91 2016/06/22 07:48:17 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.92 2016/07/04 04:17:25 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -191,17 +191,20 @@
 {
        struct stf_softc *sc;
 
+       sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO);
+       if_initname(&sc->sc_if, ifc->ifc_name, unit);
+
+       encap_lock_enter();
        if (LIST_FIRST(&stf_softc_list) != NULL) {
                /* Only one stf interface is allowed. */
+               encap_lock_exit();
+               free(sc, M_DEVBUF);
                return (EEXIST);
        }
 
-       sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO);
-
-       if_initname(&sc->sc_if, ifc->ifc_name, unit);
-
        sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
            stf_encapcheck, &in_stf_encapsw, sc);
+       encap_lock_exit();
        if (sc->encap_cookie == NULL) {
                printf("%s: unable to attach encap\n", if_name(&sc->sc_if));
                free(sc, M_DEVBUF);
@@ -226,8 +229,10 @@
 {
        struct stf_softc *sc = (void *) ifp;
 
+       encap_lock_enter();
        LIST_REMOVE(sc, sc_list);
        encap_detach(sc->encap_cookie);
+       encap_lock_exit();
        bpf_detach(ifp);
        if_detach(ifp);
        rtcache_free(&sc->sc_ro);
diff -r b07bdf72d60e -r eeabdfedf817 sys/netinet/ip_encap.c
--- a/sys/netinet/ip_encap.c    Mon Jul 04 04:14:47 2016 +0000
+++ b/sys/netinet/ip_encap.c    Mon Jul 04 04:17:25 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_encap.c,v 1.53 2016/04/26 08:44:44 ozaki-r Exp $    */
+/*     $NetBSD: ip_encap.c,v 1.54 2016/07/04 04:17:25 knakahara Exp $  */
 /*     $KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $       */
 
 /*
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.53 2016/04/26 08:44:44 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.54 2016/07/04 04:17:25 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_mrouting.h"
@@ -82,6 +82,8 @@
 #include <sys/errno.h>
 #include <sys/queue.h>
 #include <sys/kmem.h>
+#include <sys/once.h>
+#include <sys/rwlock.h>
 
 #include <net/if.h>
 
@@ -124,6 +126,12 @@
 
 struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */
 
+static ONCE_DECL(encap_init_control);
+
+static krwlock_t encap_whole_lock __cacheline_aligned;
+
+static int encap_init_once(void);
+
 void
 encap_init(void)
 {
@@ -166,6 +174,7 @@
        struct radix_node *rn;
 
        KASSERT(m->m_len >= sizeof(*ip));
+       KASSERT(rw_read_held(&encap_whole_lock));
 
        ip = mtod(m, struct ip *);
 
@@ -246,6 +255,7 @@
        proto = va_arg(ap, int);
        va_end(ap);
 
+       rw_enter(&encap_whole_lock, RW_READER);
        match = encap4_lookup(m, off, proto, INBOUND);
 
        if (match) {
@@ -253,11 +263,15 @@
                esw = match->esw;
                if (esw && esw->encapsw4.pr_input) {
                        encap_fillarg(m, match);
+                       rw_exit(&encap_whole_lock);
                        (*esw->encapsw4.pr_input)(m, off, proto);
-               } else
+               } else {
+                       rw_exit(&encap_whole_lock);
                        m_freem(m);
+               }
                return;
        }
+       rw_exit(&encap_whole_lock);
 
        /* last resort: inject to raw socket */
        rip_input(m, off, proto);
@@ -276,6 +290,7 @@
        struct radix_node *rn;
 
        KASSERT(m->m_len >= sizeof(*ip6));
+       KASSERT(rw_read_held(&encap_whole_lock));
 
        ip6 = mtod(m, struct ip6_hdr *);
 
@@ -330,6 +345,7 @@
        const struct encapsw *esw;
        struct encaptab *match;
 
+       rw_enter(&encap_whole_lock, RW_READER);
        match = encap6_lookup(m, *offp, proto, INBOUND);
 
        if (match) {
@@ -337,24 +353,33 @@
                esw = match->esw;
                if (esw && esw->encapsw6.pr_input) {
                        encap_fillarg(m, match);
+                       rw_exit(&encap_whole_lock);
                        return (*esw->encapsw6.pr_input)(mp, offp, proto);
                } else {
+                       rw_exit(&encap_whole_lock);
                        m_freem(m);
                        return IPPROTO_DONE;
                }
        }
+       rw_exit(&encap_whole_lock);
 
        /* last resort: inject to raw socket */
        return rip6_input(mp, offp, proto);
 }
 #endif
 
+/*
+ * XXX
+ * The encaptab list and the rnh radix tree must be manipulated atomically.
+ */
 static int
 encap_add(struct encaptab *ep)
 {
        struct radix_node_head *rnh = encap_rnh(ep->af);
        int error = 0;
 
+       KASSERT(rw_write_held(&encap_whole_lock));
+
        LIST_INSERT_HEAD(&encaptab, ep, chain);
        if (!ep->func && rnh) {
                if (!rnh->rnh_addaddr((void *)ep->addrpack,
@@ -370,12 +395,18 @@
        return error;
 }
 
+/*
+ * XXX
+ * The encaptab list and the rnh radix tree must be manipulated atomically.
+ */
 static int
 encap_remove(struct encaptab *ep)
 {
        struct radix_node_head *rnh = encap_rnh(ep->af);
        int error = 0;
 
+       KASSERT(rw_write_held(&encap_whole_lock));



Home | Main Index | Thread Index | Old Index