Author: hrs
Date: Fri Oct 10 06:45:13 2014
New Revision: 272889
URL: https://svnweb.freebsd.org/changeset/base/272889

Log:
  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.

Modified:
  head/sys/net/if_epair.c

Modified: head/sys/net/if_epair.c
==============================================================================
--- head/sys/net/if_epair.c     Fri Oct 10 06:24:09 2014        (r272888)
+++ head/sys/net/if_epair.c     Fri Oct 10 06:45:13 2014        (r272889)
@@ -101,7 +101,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,
@@ -172,7 +172,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.
@@ -760,10 +761,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);
@@ -944,6 +952,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)
 {
@@ -957,13 +984,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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to