Author: hrs
Date: Sun Sep 21 03:55:04 2014
New Revision: 271917
URL: http://svnweb.freebsd.org/changeset/base/271917

Log:
  Virtualize interface cloner for gif(4).  This fixes a panic when destroying
  a vnet jail which has a gif(4) interface.

Modified:
  head/sys/net/if_gif.c

Modified: head/sys/net/if_gif.c
==============================================================================
--- head/sys/net/if_gif.c       Sun Sep 21 03:48:20 2014        (r271916)
+++ head/sys/net/if_gif.c       Sun Sep 21 03:55:04 2014        (r271917)
@@ -92,13 +92,20 @@
 static const char gifname[] = "gif";
 
 /*
- * gif_mtx protects the global gif_softc_list.
+ * gif_mtx protects a per-vnet gif_softc_list.
  */
-static struct mtx gif_mtx;
+static VNET_DEFINE(struct mtx, gif_mtx);
+#define        V_gif_mtx               VNET(gif_mtx)
 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
 static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
 #define        V_gif_softc_list        VNET(gif_softc_list)
 
+#define        GIF_LIST_LOCK_INIT(x)           mtx_init(&V_gif_mtx, "gif_mtx", 
\
+                                           NULL, MTX_DEF)
+#define        GIF_LIST_LOCK_DESTROY(x)        mtx_destroy(&V_gif_mtx)
+#define        GIF_LIST_LOCK(x)                mtx_lock(&V_gif_mtx)
+#define        GIF_LIST_UNLOCK(x)              mtx_unlock(&V_gif_mtx)
+
 void   (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
 void   (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
 void   (*ng_gif_attach_p)(struct ifnet *ifp);
@@ -107,7 +114,8 @@ void        (*ng_gif_detach_p)(struct ifnet *if
 static void    gif_start(struct ifnet *);
 static int     gif_clone_create(struct if_clone *, int, caddr_t);
 static void    gif_clone_destroy(struct ifnet *);
-static struct if_clone *gif_cloner;
+static VNET_DEFINE(struct if_clone *, gif_cloner);
+#define        V_gif_cloner    VNET(gif_cloner)
 
 static int gifmodevent(module_t, int, void *);
 
@@ -189,9 +197,9 @@ gif_clone_create(struct if_clone *ifc, i
        if (ng_gif_attach_p != NULL)
                (*ng_gif_attach_p)(GIF2IFP(sc));
 
-       mtx_lock(&gif_mtx);
+       GIF_LIST_LOCK();
        LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list);
-       mtx_unlock(&gif_mtx);
+       GIF_LIST_UNLOCK();
 
        return (0);
 }
@@ -204,9 +212,9 @@ gif_clone_destroy(struct ifnet *ifp)
 #endif
        struct gif_softc *sc = ifp->if_softc;
 
-       mtx_lock(&gif_mtx);
+       GIF_LIST_LOCK();
        LIST_REMOVE(sc, gif_list);
-       mtx_unlock(&gif_mtx);
+       GIF_LIST_UNLOCK();
 
        gif_delete_tunnel(ifp);
 #ifdef INET6
@@ -238,9 +246,22 @@ vnet_gif_init(const void *unused __unuse
 {
 
        LIST_INIT(&V_gif_softc_list);
+       GIF_LIST_LOCK_INIT();
+       V_gif_cloner = if_clone_simple(gifname, gif_clone_create,
+           gif_clone_destroy, 0);
+}
+VNET_SYSINIT(vnet_gif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+    vnet_gif_init, NULL);
+
+static void
+vnet_gif_uninit(const void *unused __unused)
+{
+
+       if_clone_detach(V_gif_cloner);
+       GIF_LIST_LOCK_DESTROY();
 }
-VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init,
-    NULL);
+VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+    vnet_gif_uninit, NULL);
 
 static int
 gifmodevent(module_t mod, int type, void *data)
@@ -248,19 +269,12 @@ gifmodevent(module_t mod, int type, void
 
        switch (type) {
        case MOD_LOAD:
-               mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
-               gif_cloner = if_clone_simple(gifname, gif_clone_create,
-                   gif_clone_destroy, 0);
-               break;
-
        case MOD_UNLOAD:
-               if_clone_detach(gif_cloner);
-               mtx_destroy(&gif_mtx);
                break;
        default:
-               return EOPNOTSUPP;
+               return (EOPNOTSUPP);
        }
-       return 0;
+       return (0);
 }
 
 static moduledata_t gif_mod = {
@@ -364,7 +378,7 @@ gif_start(struct ifnet *ifp)
 #endif
 #ifdef INET6
                if (sc->gif_psrc->sa_family == AF_INET6) 
-                   m->m_pkthdr.len -= GIF_HDR_LEN6;
+                       m->m_pkthdr.len -= GIF_HDR_LEN6;
 #endif
 #endif
                /* 
@@ -373,6 +387,7 @@ gif_start(struct ifnet *ifp)
                 */
                af = m->m_pkthdr.csum_data;
                
+               /* override to IPPROTO_ETHERIP for bridged traffic */
                if (ifp->if_bridge)
                        af = AF_LINK;
 
@@ -381,7 +396,6 @@ gif_start(struct ifnet *ifp)
 
 /*              Done by IFQ_HANDOFF */
 /*             if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);*/
-               /* override to IPPROTO_ETHERIP for bridged traffic */
 
                M_SETFIB(m, sc->gif_fibnum);
                /* inner AF-specific encapsulation */
@@ -904,7 +918,7 @@ gif_set_tunnel(struct ifnet *ifp, struct
        struct sockaddr *osrc, *odst, *sa;
        int error = 0; 
 
-       mtx_lock(&gif_mtx);
+       GIF_LIST_LOCK();
        LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) {
                if (sc2 == sc)
                        continue;
@@ -924,13 +938,13 @@ gif_set_tunnel(struct ifnet *ifp, struct
                    bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
                    bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
                        error = EADDRNOTAVAIL;
-                       mtx_unlock(&gif_mtx);
+                       GIF_LIST_UNLOCK();
                        goto bad;
                }
 
                /* XXX both end must be valid? (I mean, not 0.0.0.0) */
        }
-       mtx_unlock(&gif_mtx);
+       GIF_LIST_UNLOCK();
 
        /* XXX we can detach from both, but be polite just in case */
        if (sc->gif_psrc)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to