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 (1/2) : gif(4) side



details:   https://anonhg.NetBSD.org/src/rev/c605d19b3437
branches:  trunk
changeset: 346257:c605d19b3437
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Mon Jul 04 04:14:47 2016 +0000

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

To prevent calling softint_schedule() after called softint_disestablish(),
the following modifications are added
    + ioctl (writing configuration) side
      - off IFF_RUNNING flag before changing configuration
      - wait softint handler completion before changing configuration
    + packet processing (reading configuraiotn) side
      - if IFF_RUNNING flag is on, do nothing
    + in whole
      - add gif_list_lock_{enter,exit} to prevent the same configuration is
        set to other gif(4) interfaces

diffstat:

 sys/net/if_gif.c       |  64 ++++++++++++++++++++++++++++++++++++++++++++++---
 sys/netinet/in_gif.c   |   7 +++--
 sys/netinet6/in6_gif.c |   7 +++--
 3 files changed, 68 insertions(+), 10 deletions(-)

diffs (220 lines):

diff -r b1f0bc7cc5d8 -r c605d19b3437 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Mon Jul 04 03:04:25 2016 +0000
+++ b/sys/net/if_gif.c  Mon Jul 04 04:14:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gif.c,v 1.113 2016/06/27 09:06:56 knakahara Exp $   */
+/*     $NetBSD: if_gif.c,v 1.114 2016/07/04 04:14:47 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.113 2016/06/27 09:06:56 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.114 2016/07/04 04:14:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -53,6 +53,7 @@
 #include <sys/intr.h>
 #include <sys/kmem.h>
 #include <sys/sysctl.h>
+#include <sys/xcall.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -107,6 +108,10 @@
 
 static int     gif_encap_attach(struct gif_softc *);
 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);
@@ -226,7 +231,8 @@
        if (sc == NULL)
                return 0;
 
-       if ((sc->gif_if.if_flags & IFF_UP) == 0)
+       if ((sc->gif_if.if_flags & (IFF_UP|IFF_RUNNING))
+           != (IFF_UP|IFF_RUNNING))
                return 0;
 
        /* no physical address */
@@ -329,7 +335,7 @@
        }
 
        m->m_flags &= ~(M_BCAST|M_MCAST);
-       if (!(ifp->if_flags & IFF_UP) ||
+       if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ||
            sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
                m_freem(m);
                error = ENETDOWN;
@@ -776,6 +782,25 @@
        return error;
 }
 
+static void
+gif_encap_pause(struct gif_softc *sc)
+{
+       struct ifnet *ifp = &sc->gif_if;
+       uint64_t where;
+
+       ifp->if_flags &= ~IFF_RUNNING;
+       /* membar_sync() is done in xc_broadcast(). */
+
+       /*
+        * Wait for softint_execute()(ipintr() or ip6intr())
+        * completion done by other CPUs which already run over if_flags
+        * check in in_gif_input() or in6_gif_input().
+        * Furthermore, wait for gif_output() completion too.
+        */
+       where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
+       xc_wait(where);
+}
+
 static int
 gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
 {
@@ -787,6 +812,7 @@
        int error;
 
        s = splsoftnet();
+       gif_list_lock_enter();
 
        LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
                if (sc2 == sc)
@@ -797,6 +823,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();
                        splx(s);
                        return EADDRNOTAVAIL;
                }
@@ -805,15 +832,19 @@
        }
 
        if ((nsrc = sockaddr_dup(src, M_WAITOK)) == NULL) {
+               gif_list_lock_exit();
                splx(s);
                return ENOMEM;
        }
        if ((ndst = sockaddr_dup(dst, M_WAITOK)) == NULL) {
                sockaddr_free(nsrc);
+               gif_list_lock_exit();
                splx(s);
                return ENOMEM;
        }
 
+       gif_encap_pause(sc);
+
        /* Firstly, clear old configurations. */
        /* XXX we can detach from both, but be polite just in case */
        if (sc->gif_psrc)
@@ -858,6 +889,7 @@
        else
                ifp->if_flags &= ~IFF_RUNNING;
 
+       gif_list_lock_exit();
        splx(s);
        return error;
 }
@@ -869,7 +901,9 @@
        int s;
 
        s = splsoftnet();
+       gif_list_lock_enter();
 
+       gif_encap_pause(sc);
        if (sc->gif_psrc) {
                sockaddr_free(sc->gif_psrc);
                sc->gif_psrc = NULL;
@@ -890,5 +924,27 @@
                ifp->if_flags |= IFF_RUNNING;
        else
                ifp->if_flags &= ~IFF_RUNNING;
+
+       gif_list_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 b1f0bc7cc5d8 -r c605d19b3437 sys/netinet/in_gif.c
--- a/sys/netinet/in_gif.c      Mon Jul 04 03:04:25 2016 +0000
+++ b/sys/netinet/in_gif.c      Mon Jul 04 04:14:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_gif.c,v 1.76 2016/06/10 13:31:44 ozaki-r Exp $      */
+/*     $NetBSD: in_gif.c,v 1.77 2016/07/04 04:14:47 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.76 2016/06/10 13:31:44 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.77 2016/07/04 04:14:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -206,7 +206,8 @@
 
        gifp = (struct ifnet *)encap_getarg(m);
 
-       if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
+       if (gifp == NULL || (gifp->if_flags & (IFF_UP|IFF_RUNNING))
+               != (IFF_UP|IFF_RUNNING)) {
                m_freem(m);
                ip_statinc(IP_STAT_NOGIF);
                return;
diff -r b1f0bc7cc5d8 -r c605d19b3437 sys/netinet6/in6_gif.c
--- a/sys/netinet6/in6_gif.c    Mon Jul 04 03:04:25 2016 +0000
+++ b/sys/netinet6/in6_gif.c    Mon Jul 04 04:14:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_gif.c,v 1.75 2016/06/28 02:02:56 ozaki-r Exp $     */
+/*     $NetBSD: in6_gif.c,v 1.76 2016/07/04 04:14:47 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.75 2016/06/28 02:02:56 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.76 2016/07/04 04:14:47 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -215,7 +215,8 @@
 
        gifp = (struct ifnet *)encap_getarg(m);
 
-       if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
+       if (gifp == NULL || (gifp->if_flags & (IFF_UP|IFF_RUNNING))
+               != (IFF_UP|IFF_RUNNING)) {
                m_freem(m);
                IP6_STATINC(IP6_STAT_NOGIF);
                return IPPROTO_DONE;



Home | Main Index | Thread Index | Old Index