Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Sep 2015 08:52:40 +0000 (UTC)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r287594 - stable/10/sys/net
Message-ID:  <201509090852.t898qeJ9087535@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hrs
Date: Wed Sep  9 08:52:39 2015
New Revision: 287594
URL: https://svnweb.freebsd.org/changeset/base/287594

Log:
  MFC r272889 and r287402:
  
  - Virtualize if_epair(4).  An if_xname check for both "a" and "b" interfaces
    is added to return EEXIST when only "b" interface exists---this can happen
    when epair<N>b is moved to a vnet jail and then "ifconfig epair<N> create"
    is invoked there.
  
  - Fix a panic which was reproducible by an infinite loop of
    "ifconfig epair0 create && ifconfig epair0a destroy".
    This was caused by an uninitialized function pointer in
    softc->media.

Modified:
  stable/10/sys/net/if_epair.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/net/if_epair.c
==============================================================================
--- stable/10/sys/net/if_epair.c	Wed Sep  9 08:40:17 2015	(r287593)
+++ stable/10/sys/net/if_epair.c	Wed Sep  9 08:52:39 2015	(r287594)
@@ -100,7 +100,7 @@ static int epair_clone_destroy(struct if
 
 static const char epairname[] = "epair";
 
-/* Netisr realted definitions and sysctl. */
+/* Netisr related definitions and sysctl. */
 static struct netisr_handler epair_nh = {
 	.nh_name	= epairname,
 	.nh_proto	= NETISR_EPAIR,
@@ -171,7 +171,8 @@ STAILQ_HEAD(eid_list, epair_ifp_drain);
 static MALLOC_DEFINE(M_EPAIR, epairname,
     "Pair of virtual cross-over connected Ethernet-like interfaces");
 
-static struct if_clone *epair_cloner;
+static VNET_DEFINE(struct if_clone *, epair_cloner);
+#define	V_epair_cloner	VNET(epair_cloner)
 
 /*
  * DPCPU area and functions.
@@ -759,10 +760,17 @@ epair_clone_create(struct if_clone *ifc,
 		ifc_free_unit(ifc, unit);
 		return (ENOSPC);
 	}
-	*dp = 'a';
+	*dp = 'b';
 	/* Must not change dp so we can replace 'a' by 'b' later. */
 	*(dp+1) = '\0';
 
+	/* Check if 'a' and 'b' interfaces already exist. */ 
+	if (ifunit(name) != NULL)
+		return (EEXIST);
+	*dp = 'a';
+	if (ifunit(name) != NULL)
+		return (EEXIST);
+
 	/* Allocate memory for both [ab] interfaces */
 	sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO);
 	EPAIR_REFCOUNT_INIT(&sca->refcount, 1);
@@ -800,6 +808,14 @@ epair_clone_create(struct if_clone *ifc,
 	    netisr_get_cpuid(sca->ifp->if_index % netisr_get_cpucount());
 	scb->cpuid =
 	    netisr_get_cpuid(scb->ifp->if_index % netisr_get_cpucount());
+
+	/* Initialise pseudo media types. */
+	ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status);
+	ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+	ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T);
+	ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status);
+	ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+	ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T);
 	
 	/* Finish initialization of interface <n>a. */
 	ifp = sca->ifp;
@@ -858,14 +874,6 @@ epair_clone_create(struct if_clone *ifc,
 	strlcpy(name, sca->ifp->if_xname, len);
 	DPRINTF("name='%s/%db' created sca=%p scb=%p\n", name, unit, sca, scb);
 
-	/* Initialise pseudo media types. */
-	ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status);
-	ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL);
-	ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T);
-	ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status);
-	ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL);
-	ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T);
-
 	/* Tell the world, that we are ready to rock. */
 	sca->ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	scb->ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -943,6 +951,25 @@ epair_clone_destroy(struct if_clone *ifc
 	return (0);
 }
 
+static void
+vnet_epair_init(const void *unused __unused)
+{
+
+	V_epair_cloner = if_clone_advanced(epairname, 0,
+	    epair_clone_match, epair_clone_create, epair_clone_destroy);
+}
+VNET_SYSINIT(vnet_epair_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+    vnet_epair_init, NULL);
+
+static void
+vnet_epair_uninit(const void *unused __unused)
+{
+
+	if_clone_detach(V_epair_cloner);
+}
+VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+    vnet_epair_uninit, NULL);
+
 static int
 epair_modevent(module_t mod, int type, void *data)
 {
@@ -956,13 +983,10 @@ epair_modevent(module_t mod, int type, v
 		if (TUNABLE_INT_FETCH("net.link.epair.netisr_maxqlen", &qlimit))
 		    epair_nh.nh_qlimit = qlimit;
 		netisr_register(&epair_nh);
-		epair_cloner = if_clone_advanced(epairname, 0,
-		    epair_clone_match, epair_clone_create, epair_clone_destroy);
 		if (bootverbose)
 			printf("%s initialized.\n", epairname);
 		break;
 	case MOD_UNLOAD:
-		if_clone_detach(epair_cloner);
 		netisr_unregister(&epair_nh);
 		epair_dpcpu_detach();
 		if (bootverbose)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509090852.t898qeJ9087535>