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-head
mailing list