summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2014-12-22 17:54:26 +0000
committerae <ae@FreeBSD.org>2014-12-22 17:54:26 +0000
commit9a4e55b14723d5cd0147c18c4a4fde418c5086f8 (patch)
tree34369d45d9c079a476bbf94dc3bf9cb36a56d829 /sys/net
parent3449c92ea5dd1f192ef973f37b9e0e00ab0d30cd (diff)
downloadFreeBSD-src-9a4e55b14723d5cd0147c18c4a4fde418c5086f8.zip
FreeBSD-src-9a4e55b14723d5cd0147c18c4a4fde418c5086f8.tar.gz
MFC r271917 by hrs:
Virtualize interface cloner for gif(4). This fixes a panic when destroying a vnet jail which has a gif(4) interface.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_gif.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 7d4444e..4bec9b6 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -91,13 +91,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);
@@ -106,7 +113,8 @@ void (*ng_gif_detach_p)(struct ifnet *ifp);
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 *);
@@ -188,9 +196,9 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
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);
}
@@ -203,9 +211,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
@@ -237,9 +245,22 @@ vnet_gif_init(const void *unused __unused)
{
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)
@@ -247,19 +268,12 @@ gifmodevent(module_t mod, int type, void *data)
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 = {
@@ -363,7 +377,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
/*
@@ -372,6 +386,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;
@@ -380,7 +395,6 @@ gif_start(struct ifnet *ifp)
/* Done by IFQ_HANDOFF */
/* ifp->if_obytes += m->m_pkthdr.len;*/
- /* override to IPPROTO_ETHERIP for bridged traffic */
M_SETFIB(m, sc->gif_fibnum);
/* inner AF-specific encapsulation */
@@ -939,7 +953,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
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;
@@ -959,13 +973,13 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
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)
OpenPOWER on IntegriCloud