Date: Sun, 21 Sep 2014 03:56:07 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271918 - in head/sys: net netinet Message-ID: <201409210356.s8L3u7KL016913@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hrs Date: Sun Sep 21 03:56:06 2014 New Revision: 271918 URL: http://svnweb.freebsd.org/changeset/base/271918 Log: - Virtualize interface cloner for gre(4). This fixes a panic when destroying a vnet jail which has a gre(4) interface. - Make net.link.gre.max_nesting vnet-local. Modified: head/sys/net/if_gre.c head/sys/net/if_gre.h head/sys/netinet/ip_gre.c Modified: head/sys/net/if_gre.c ============================================================================== --- head/sys/net/if_gre.c Sun Sep 21 03:55:04 2014 (r271917) +++ head/sys/net/if_gre.c Sun Sep 21 03:56:06 2014 (r271918) @@ -102,15 +102,16 @@ struct mtag_gre_nesting { * gre_mtx protects all global variables in if_gre.c. * XXX: gre_softc data not protected yet. */ -struct mtx gre_mtx; +VNET_DEFINE(struct mtx, gre_mtx); +VNET_DEFINE(struct gre_softc_head, gre_softc_list); + static const char grename[] = "gre"; static MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation"); -struct gre_softc_head gre_softc_list; - static int gre_clone_create(struct if_clone *, int, caddr_t); static void gre_clone_destroy(struct ifnet *); -static struct if_clone *gre_cloner; +static VNET_DEFINE(struct if_clone *, gre_cloner); +#define V_gre_cloner VNET(gre_cloner) static int gre_ioctl(struct ifnet *, u_long, caddr_t); static int gre_output(struct ifnet *, struct mbuf *, @@ -118,8 +119,6 @@ static int gre_output(struct ifnet *, st static int gre_compute_route(struct gre_softc *sc); -static void greattach(void); - #ifdef INET extern struct domain inetdomain; static const struct protosw in_gre_protosw = { @@ -160,26 +159,34 @@ static SYSCTL_NODE(_net_link, IFT_TUNNEL */ #define MAX_GRE_NEST 1 #endif -static int max_gre_nesting = MAX_GRE_NEST; -SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW, - &max_gre_nesting, 0, "Max nested tunnels"); +static VNET_DEFINE(int, max_gre_nesting) = MAX_GRE_NEST; +#define V_max_gre_nesting VNET(max_gre_nesting) +SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET, + &VNET_NAME(max_gre_nesting), 0, "Max nested tunnels"); -/* ARGSUSED */ static void -greattach(void) +vnet_gre_init(const void *unused __unused) { - - mtx_init(&gre_mtx, "gre_mtx", NULL, MTX_DEF); - LIST_INIT(&gre_softc_list); - gre_cloner = if_clone_simple(grename, gre_clone_create, + LIST_INIT(&V_gre_softc_list); + GRE_LIST_LOCK_INIT(); + V_gre_cloner = if_clone_simple(grename, gre_clone_create, gre_clone_destroy, 0); } +VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_gre_init, NULL); + +static void +vnet_gre_uninit(const void *unused __unused) +{ + + if_clone_detach(V_gre_cloner); + GRE_LIST_LOCK_DESTROY(); +} +VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_gre_uninit, NULL); static int -gre_clone_create(ifc, unit, params) - struct if_clone *ifc; - int unit; - caddr_t params; +gre_clone_create(struct if_clone *ifc, int unit, caddr_t params) { struct gre_softc *sc; @@ -210,21 +217,20 @@ gre_clone_create(ifc, unit, params) sc->key = 0; if_attach(GRE2IFP(sc)); bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t)); - mtx_lock(&gre_mtx); - LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list); - mtx_unlock(&gre_mtx); + GRE_LIST_LOCK(); + LIST_INSERT_HEAD(&V_gre_softc_list, sc, sc_list); + GRE_LIST_UNLOCK(); return (0); } static void -gre_clone_destroy(ifp) - struct ifnet *ifp; +gre_clone_destroy(struct ifnet *ifp) { struct gre_softc *sc = ifp->if_softc; - mtx_lock(&gre_mtx); + GRE_LIST_LOCK(); LIST_REMOVE(sc, sc_list); - mtx_unlock(&gre_mtx); + GRE_LIST_UNLOCK(); #ifdef INET if (sc->encap != NULL) @@ -269,7 +275,7 @@ gre_output(struct ifnet *ifp, struct mbu gt = (struct mtag_gre_nesting *)(mtag + 1); gt->count++; - if (gt->count > min(gt->max,max_gre_nesting)) { + if (gt->count > min(gt->max, V_max_gre_nesting)) { printf("%s: hit maximum recursion limit %u on %s\n", __func__, gt->count - 1, ifp->if_xname); m_freem(m); @@ -301,7 +307,7 @@ gre_output(struct ifnet *ifp, struct mbu * Note: the sysctl does not actually check for saneness, so we * limit the maximum numbers of possible recursions here. */ - max = imin(max_gre_nesting, 256); + max = imin(V_max_gre_nesting, 256); /* If someone sets the sysctl <= 0, we want at least 1. */ max = imax(max, 1); len = sizeof(struct mtag_gre_nesting) + @@ -909,16 +915,12 @@ gremodevent(module_t mod, int type, void switch (type) { case MOD_LOAD: - greattach(); - break; case MOD_UNLOAD: - if_clone_detach(gre_cloner); - mtx_destroy(&gre_mtx); break; default: - return EOPNOTSUPP; + return (EOPNOTSUPP); } - return 0; + return (0); } static moduledata_t gre_mod = { Modified: head/sys/net/if_gre.h ============================================================================== --- head/sys/net/if_gre.h Sun Sep 21 03:55:04 2014 (r271917) +++ head/sys/net/if_gre.h Sun Sep 21 03:56:06 2014 (r271918) @@ -176,8 +176,16 @@ struct mobip_h { #ifdef _KERNEL LIST_HEAD(gre_softc_head, gre_softc); -extern struct mtx gre_mtx; -extern struct gre_softc_head gre_softc_list; +VNET_DECLARE(struct gre_softc_head, gre_softc_list); +#define V_gre_softc_list VNET(gre_softc_list) + +VNET_DECLARE(struct mtx, gre_mtx); +#define V_gre_mtx VNET(gre_mtx) +#define GRE_LIST_LOCK_INIT(x) mtx_init(&V_gre_mtx, "gre_mtx", NULL, \ + MTX_DEF) +#define GRE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gre_mtx) +#define GRE_LIST_LOCK(x) mtx_lock(&V_gre_mtx) +#define GRE_LIST_UNLOCK(x) mtx_unlock(&V_gre_mtx) u_int16_t gre_in_cksum(u_int16_t *, u_int); #endif /* _KERNEL */ Modified: head/sys/netinet/ip_gre.c ============================================================================== --- head/sys/netinet/ip_gre.c Sun Sep 21 03:55:04 2014 (r271917) +++ head/sys/netinet/ip_gre.c Sun Sep 21 03:56:06 2014 (r271918) @@ -315,18 +315,18 @@ gre_lookup(struct mbuf *m, u_int8_t prot struct ip *ip = mtod(m, struct ip *); struct gre_softc *sc; - mtx_lock(&gre_mtx); - for (sc = LIST_FIRST(&gre_softc_list); sc != NULL; + GRE_LIST_LOCK(); + for (sc = LIST_FIRST(&V_gre_softc_list); sc != NULL; sc = LIST_NEXT(sc, sc_list)) { if ((sc->g_dst.s_addr == ip->ip_src.s_addr) && (sc->g_src.s_addr == ip->ip_dst.s_addr) && (sc->g_proto == proto) && ((GRE2IFP(sc)->if_flags & IFF_UP) != 0)) { - mtx_unlock(&gre_mtx); + GRE_LIST_UNLOCK(); return (sc); } } - mtx_unlock(&gre_mtx); + GRE_LIST_UNLOCK(); return (NULL); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409210356.s8L3u7KL016913>