Changeset View
Changeset View
Standalone View
Standalone View
head/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/kernel.h> | #include <sys/kernel.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/refcount.h> | #include <sys/refcount.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/sockio.h> | #include <sys/sockio.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
▲ Show 20 Lines • Show All 640 Lines • ▼ Show 20 Lines | |||||
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; | |||||
uint32_t key[3]; | |||||
uint32_t hash; | |||||
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ | uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ | ||||
/* | /* | ||||
* We are abusing params to create our second interface. | * We are abusing params to create our second interface. | ||||
* Actually we already created it and called if_clone_create() | * Actually we already created it and called if_clone_create() | ||||
* for it to do the official insertion procedure the moment we knew | * for it to do the official insertion procedure the moment we knew | ||||
* it cannot fail anymore. So just do attach it here. | * it cannot fail anymore. So just do attach it here. | ||||
*/ | */ | ||||
if (params) { | if (params) { | ||||
scb = (struct epair_softc *)params; | scb = (struct epair_softc *)params; | ||||
ifp = scb->ifp; | ifp = scb->ifp; | ||||
/* Assign a hopefully unique, locally administered etheraddr. */ | /* Copy epairNa etheraddr and change the last byte. */ | ||||
eaddr[0] = 0x02; | memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN); | ||||
eaddr[3] = (ifp->if_index >> 8) & 0xff; | |||||
eaddr[4] = ifp->if_index & 0xff; | |||||
eaddr[5] = 0x0b; | eaddr[5] = 0x0b; | ||||
ether_ifattach(ifp, eaddr); | ether_ifattach(ifp, eaddr); | ||||
/* Correctly set the name for the cloner list. */ | /* Correctly set the name for the cloner list. */ | ||||
strlcpy(name, scb->ifp->if_xname, len); | strlcpy(name, ifp->if_xname, len); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* 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); | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | ||||
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); | ||||
/* Assign a hopefully unique, locally administered etheraddr. */ | |||||
/* | |||||
* Calculate the etheraddr hashing the hostid and the | |||||
* interface index. The result would be hopefully unique | |||||
*/ | |||||
getcredhostid(curthread->td_ucred, (unsigned long *)&hostid); | |||||
if (hostid == 0) | |||||
arc4rand(&hostid, sizeof(hostid), 0); | |||||
key[0] = (uint32_t)ifp->if_index; | |||||
key[1] = (uint32_t)(hostid & 0xffffffff); | |||||
key[2] = (uint32_t)((hostid >> 32) & 0xfffffffff); | |||||
hash = jenkins_hash32(key, 3, 0); | |||||
eaddr[0] = 0x02; | eaddr[0] = 0x02; | ||||
eaddr[3] = (ifp->if_index >> 8) & 0xff; | memcpy(&eaddr[1], &hash, 4); | ||||
eaddr[4] = ifp->if_index & 0xff; | |||||
eaddr[5] = 0x0a; | eaddr[5] = 0x0a; | ||||
ether_ifattach(ifp, eaddr); | 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. */ | ||||
▲ Show 20 Lines • Show All 179 Lines • Show Last 20 Lines |