svn commit: r271917 - head/sys/net

Hiroki Sato hrs at FreeBSD.org
Sun Sep 21 03:55:05 UTC 2014


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)


More information about the svn-src-all mailing list