diff options
Diffstat (limited to 'freebsd/sys/net/if_epair.c')
-rw-r--r-- | freebsd/sys/net/if_epair.c | 125 |
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); |