Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if_epair.c
Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
* epairs on multiple stacks/machines, we may need this. | * epairs on multiple stacks/machines, we may need this. | ||||
* For now let the user handle that case. | * For now let the user handle that case. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/hash.h> | |||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/libkern.h> | #include <sys/libkern.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/refcount.h> | #include <sys/refcount.h> | ||||
Show All 38 Lines | |||||
static int epair_media_change(struct ifnet *); | static int epair_media_change(struct ifnet *); | ||||
static void epair_media_status(struct ifnet *, struct ifmediareq *); | static void epair_media_status(struct ifnet *, struct ifmediareq *); | ||||
static int epair_clone_match(struct if_clone *, const char *); | 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_create(struct if_clone *, char *, size_t, caddr_t); | ||||
static int epair_clone_destroy(struct if_clone *, struct ifnet *); | static int epair_clone_destroy(struct if_clone *, struct ifnet *); | ||||
static const char epairname[] = "epair"; | static const char epairname[] = "epair"; | ||||
static unsigned int next_index = 0; | |||||
/* Netisr related definitions and sysctl. */ | /* Netisr related definitions and sysctl. */ | ||||
static struct netisr_handler epair_nh = { | static struct netisr_handler epair_nh = { | ||||
.nh_name = epairname, | .nh_name = epairname, | ||||
.nh_proto = NETISR_EPAIR, | .nh_proto = NETISR_EPAIR, | ||||
.nh_policy = NETISR_POLICY_CPU, | .nh_policy = NETISR_POLICY_CPU, | ||||
.nh_handler = epair_nh_sintr, | .nh_handler = epair_nh_sintr, | ||||
.nh_m2cpuid = epair_nh_m2cpuid, | .nh_m2cpuid = epair_nh_m2cpuid, | ||||
▲ Show 20 Lines • Show All 597 Lines • ▼ Show 20 Lines | |||||
epair_clone_add(struct if_clone *ifc, struct epair_softc *scb) | epair_clone_add(struct if_clone *ifc, struct epair_softc *scb) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ | uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ | ||||
ifp = scb->ifp; | ifp = scb->ifp; | ||||
/* Copy epairNa etheraddr and change the last byte. */ | /* Copy epairNa etheraddr and change the last byte. */ | ||||
memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); | memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); | ||||
eaddr[5] = 0x0b; | eaddr[5] &= 0xf0; | ||||
eaddr[5] |= 0x0b; | |||||
ether_ifattach(ifp, eaddr); | ether_ifattach(ifp, eaddr); | ||||
if_clone_addif(ifc, ifp); | if_clone_addif(ifc, ifp); | ||||
} | } | ||||
static int | static int | ||||
epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) | epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) | ||||
{ | { | ||||
struct epair_softc *sca, *scb; | struct epair_softc *sca, *scb; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
char *dp; | char *dp; | ||||
int error, unit, wildcard; | int error, unit, wildcard; | ||||
uint64_t hostid; | struct ether_addr eaddr; | ||||
uint32_t key[3]; | |||||
uint32_t hash; | |||||
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ | |||||
/* Try to see if a special unit was requested. */ | /* Try to see if a special unit was requested. */ | ||||
error = ifc_name2unit(name, &unit); | error = ifc_name2unit(name, &unit); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
wildcard = (unit < 0); | wildcard = (unit < 0); | ||||
error = ifc_alloc_unit(ifc, &unit); | error = ifc_alloc_unit(ifc, &unit); | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) | ||||
ifp->if_capabilities = IFCAP_VLAN_MTU; | ifp->if_capabilities = IFCAP_VLAN_MTU; | ||||
ifp->if_capenable = IFCAP_VLAN_MTU; | ifp->if_capenable = IFCAP_VLAN_MTU; | ||||
ifp->if_start = epair_start; | ifp->if_start = epair_start; | ||||
ifp->if_ioctl = epair_ioctl; | ifp->if_ioctl = epair_ioctl; | ||||
ifp->if_init = epair_init; | ifp->if_init = epair_init; | ||||
if_setsendqlen(ifp, ifqmaxlen); | if_setsendqlen(ifp, ifqmaxlen); | ||||
if_setsendqready(ifp); | if_setsendqready(ifp); | ||||
/* | ether_gen_addr(ifp, &eaddr); | ||||
* Calculate the etheraddr hashing the hostid and the | eaddr.octet[5] &= 0xf0; | ||||
* interface index. The result would be hopefully unique. | eaddr.octet[5] |= 0x0a; | ||||
* Note that the "a" component of an epair instance may get moved | ether_ifattach(ifp, eaddr.octet); | ||||
* to a different VNET after creation. In that case its index | |||||
* will be freed and the index can get reused by new epair instance. | |||||
* Make sure we do not create same etheraddr again. | |||||
*/ | |||||
getcredhostid(curthread->td_ucred, (unsigned long *)&hostid); | |||||
if (hostid == 0) | |||||
arc4rand(&hostid, sizeof(hostid), 0); | |||||
if (ifp->if_index > next_index) | |||||
next_index = ifp->if_index; | |||||
else | |||||
next_index++; | |||||
key[0] = (uint32_t)next_index; | |||||
key[1] = (uint32_t)(hostid & 0xffffffff); | |||||
key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff); | |||||
hash = jenkins_hash32(key, 3, 0); | |||||
eaddr[0] = 0x02; | |||||
memcpy(&eaddr[1], &hash, 4); | |||||
eaddr[5] = 0x0a; | |||||
ether_ifattach(ifp, eaddr); | |||||
sca->if_qflush = ifp->if_qflush; | sca->if_qflush = ifp->if_qflush; | ||||
ifp->if_qflush = epair_qflush; | ifp->if_qflush = epair_qflush; | ||||
ifp->if_transmit = epair_transmit; | ifp->if_transmit = epair_transmit; | ||||
ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ | ifp->if_baudrate = IF_Gbps(10); /* arbitrary maximum */ | ||||
/* Swap the name and finish initialization of interface <n>b. */ | /* Swap the name and finish initialization of interface <n>b. */ | ||||
*dp = 'b'; | *dp = 'b'; | ||||
▲ Show 20 Lines • Show All 178 Lines • Show Last 20 Lines |