summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/if_epair.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/if_epair.c')
-rw-r--r--freebsd/sys/net/if_epair.c125
1 files changed, 78 insertions, 47 deletions
diff --git a/freebsd/sys/net/if_epair.c b/freebsd/sys/net/if_epair.c
index 755e608a..b4f73d68 100644
--- a/freebsd/sys/net/if_epair.c
+++ b/freebsd/sys/net/if_epair.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/refcount.h>
@@ -67,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_clone.h>
#include <net/if_media.h>
#include <net/if_var.h>
@@ -74,8 +76,6 @@ __FBSDID("$FreeBSD$");
#include <net/netisr.h>
#include <net/vnet.h>
-#define EPAIRNAME "epair"
-
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, OID_AUTO, epair, CTLFLAG_RW, 0, "epair sysctl");
@@ -102,9 +102,11 @@ static int epair_clone_match(struct if_clone *, const char *);
static int epair_clone_create(struct if_clone *, char *, size_t, caddr_t);
static int epair_clone_destroy(struct if_clone *, struct ifnet *);
-/* Netisr realted definitions and sysctl. */
+static const char epairname[] = "epair";
+
+/* Netisr related definitions and sysctl. */
static struct netisr_handler epair_nh = {
- .nh_name = EPAIRNAME,
+ .nh_name = epairname,
.nh_proto = NETISR_EPAIR,
.nh_policy = NETISR_POLICY_CPU,
.nh_handler = epair_nh_sintr,
@@ -170,12 +172,11 @@ STAILQ_HEAD(eid_list, epair_ifp_drain);
#define EPAIR_REFCOUNT_ASSERT(a, p)
#endif
-static MALLOC_DEFINE(M_EPAIR, EPAIRNAME,
+static MALLOC_DEFINE(M_EPAIR, epairname,
"Pair of virtual cross-over connected Ethernet-like interfaces");
-static struct if_clone epair_cloner = IFC_CLONE_INITIALIZER(
- EPAIRNAME, NULL, IF_MAXUNIT,
- NULL, epair_clone_match, epair_clone_create, epair_clone_destroy);
+static VNET_DEFINE(struct if_clone *, epair_cloner);
+#define V_epair_cloner VNET(epair_cloner)
/*
* DPCPU area and functions.
@@ -421,7 +422,7 @@ epair_start_locked(struct ifnet *ifp)
*/
if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(oifp->if_flags & IFF_UP) ==0) {
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
m_freem(m);
continue;
}
@@ -437,15 +438,15 @@ epair_start_locked(struct ifnet *ifp)
error = netisr_queue(NETISR_EPAIR, m);
CURVNET_RESTORE();
if (!error) {
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
/* Someone else received the packet. */
- oifp->if_ipackets++;
+ if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1);
} else {
/* The packet was freed already. */
epair_dpcpu->epair_drv_flags |= IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
(void) epair_add_ifp_for_draining(ifp);
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
EPAIR_REFCOUNT_RELEASE(&sc->refcount);
EPAIR_REFCOUNT_ASSERT((int)sc->refcount >= 1,
("%s: ifp=%p sc->refcount not >= 1: %d",
@@ -506,7 +507,7 @@ epair_transmit_locked(struct ifnet *ifp, struct mbuf *m)
oifp = sc->oifp;
if ((oifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(oifp->if_flags & IFF_UP) ==0) {
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
m_freem(m);
return (0);
}
@@ -515,17 +516,17 @@ epair_transmit_locked(struct ifnet *ifp, struct mbuf *m)
DPRINTF("packet %s -> %s\n", ifp->if_xname, oifp->if_xname);
#ifdef ALTQ
- /* Support ALTQ via the clasic if_start() path. */
+ /* Support ALTQ via the classic if_start() path. */
IF_LOCK(&ifp->if_snd);
if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
ALTQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
if (error)
- ifp->if_snd.ifq_drops++;
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
IF_UNLOCK(&ifp->if_snd);
if (!error) {
- ifp->if_obytes += len;
+ if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
if (mflags & (M_BCAST|M_MCAST))
- ifp->if_omcasts++;
+ if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
epair_start_locked(ifp);
@@ -559,22 +560,22 @@ epair_transmit_locked(struct ifnet *ifp, struct mbuf *m)
error = netisr_queue(NETISR_EPAIR, m);
CURVNET_RESTORE();
if (!error) {
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
/*
* IFQ_HANDOFF_ADJ/ip_handoff() update statistics,
* but as we bypass all this we have to duplicate
* the logic another time.
*/
- ifp->if_obytes += len;
+ if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
if (mflags & (M_BCAST|M_MCAST))
- ifp->if_omcasts++;
+ if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
/* Someone else received the packet. */
- oifp->if_ipackets++;
+ if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1);
} else {
/* The packet was freed already. */
epair_dpcpu->epair_drv_flags |= IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
EPAIR_REFCOUNT_RELEASE(&sc->refcount);
EPAIR_REFCOUNT_ASSERT((int)sc->refcount >= 1,
("%s: ifp=%p sc->refcount not >= 1: %d",
@@ -694,10 +695,10 @@ epair_clone_match(struct if_clone *ifc, const char *name)
* - epair<n>
* but not the epair<n>[ab] versions.
*/
- if (strncmp(EPAIRNAME, name, sizeof(EPAIRNAME)-1) != 0)
+ if (strncmp(epairname, name, sizeof(epairname)-1) != 0)
return (0);
- for (cp = name + sizeof(EPAIRNAME) - 1; *cp != '\0'; cp++) {
+ for (cp = name + sizeof(epairname) - 1; *cp != '\0'; cp++) {
if (*cp < '0' || *cp > '9')
return (0);
}
@@ -716,7 +717,7 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
/*
* We are abusing params to create our second interface.
- * Actually we already created it and called if_clone_createif()
+ * Actually we already created it and called if_clone_create()
* for it to do the official insertion procedure the moment we knew
* it cannot fail anymore. So just do attach it here.
*/
@@ -763,10 +764,17 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
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);
@@ -801,15 +809,23 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
* cache locality but we can at least allow parallelism.
*/
sca->cpuid =
- netisr_get_cpuid(sca->ifp->if_index % netisr_get_cpucount());
+ netisr_get_cpuid(sca->ifp->if_index);
scb->cpuid =
- netisr_get_cpuid(scb->ifp->if_index % netisr_get_cpucount());
+ netisr_get_cpuid(scb->ifp->if_index);
+
+ /* 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;
ifp->if_softc = sca;
strlcpy(ifp->if_xname, name, IFNAMSIZ);
- ifp->if_dname = ifc->ifc_name;
+ ifp->if_dname = epairname;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_capabilities = IFCAP_VLAN_MTU;
@@ -827,7 +843,7 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
sca->if_qflush = ifp->if_qflush;
ifp->if_qflush = epair_qflush;
ifp->if_transmit = epair_transmit;
- ifp->if_baudrate = IF_Gbps(10UL); /* arbitrary maximum */
+ ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */
/* Swap the name and finish initialization of interface <n>b. */
*dp = 'b';
@@ -835,7 +851,7 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp = scb->ifp;
ifp->if_softc = scb;
strlcpy(ifp->if_xname, name, IFNAMSIZ);
- ifp->if_dname = ifc->ifc_name;
+ ifp->if_dname = epairname;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_capabilities = IFCAP_VLAN_MTU;
@@ -845,15 +861,15 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_init = epair_init;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
/* We need to play some tricks here for the second interface. */
- strlcpy(name, EPAIRNAME, len);
+ strlcpy(name, epairname, len);
error = if_clone_create(name, len, (caddr_t)scb);
if (error)
- panic("%s: if_clone_createif() for our 2nd iface failed: %d",
+ panic("%s: if_clone_create() for our 2nd iface failed: %d",
__func__, error);
scb->if_qflush = ifp->if_qflush;
ifp->if_qflush = epair_qflush;
ifp->if_transmit = epair_transmit;
- ifp->if_baudrate = IF_Gbps(10UL); /* arbitrary maximum */
+ ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */
/*
* Restore name to <n>a as the ifp for this will go into the
@@ -862,14 +878,6 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
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;
@@ -947,6 +955,31 @@ epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
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);
+#ifdef VIMAGE
+ netisr_register_vnet(&epair_nh);
+#endif
+}
+VNET_SYSINIT(vnet_epair_init, SI_SUB_PSEUDO, SI_ORDER_ANY,
+ vnet_epair_init, NULL);
+
+static void
+vnet_epair_uninit(const void *unused __unused)
+{
+
+#ifdef VIMAGE
+ netisr_unregister_vnet(&epair_nh);
+#endif
+ if_clone_detach(V_epair_cloner);
+}
+VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY,
+ vnet_epair_uninit, NULL);
+
static int
epair_modevent(module_t mod, int type, void *data)
{
@@ -962,16 +995,14 @@ epair_modevent(module_t mod, int type, void *data)
epair_nh.nh_qlimit = qlimit;
#endif /* __rtems__ */
netisr_register(&epair_nh);
- if_clone_attach(&epair_cloner);
if (bootverbose)
- printf("%s initialized.\n", EPAIRNAME);
+ printf("%s initialized.\n", epairname);
break;
case MOD_UNLOAD:
- if_clone_detach(&epair_cloner);
netisr_unregister(&epair_nh);
epair_dpcpu_detach();
if (bootverbose)
- printf("%s unloaded.\n", EPAIRNAME);
+ printf("%s unloaded.\n", epairname);
break;
default:
return (EOPNOTSUPP);
@@ -985,5 +1016,5 @@ static moduledata_t epair_mod = {
0
};
-DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+DECLARE_MODULE(if_epair, epair_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
MODULE_VERSION(if_epair, 1);