Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_bridge.c
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
/* Per-link private data */ | /* Per-link private data */ | ||||
struct ng_bridge_link { | struct ng_bridge_link { | ||||
hook_p hook; /* netgraph hook */ | hook_p hook; /* netgraph hook */ | ||||
u_int16_t loopCount; /* loop ignore timer */ | u_int16_t loopCount; /* loop ignore timer */ | ||||
unsigned int learnMac : 1, /* autolearn macs */ | unsigned int learnMac : 1, /* autolearn macs */ | ||||
sendUnknown : 1;/* send unknown macs out */ | sendUnknown : 1;/* send unknown macs out */ | ||||
struct ng_bridge_link_kernel_stats stats; /* link stats */ | struct ng_bridge_link_kernel_stats stats; /* link stats */ | ||||
}; | }; | ||||
typedef struct ng_bridge_link const *link_cp; /* read only access */ | |||||
/* Per-node private data */ | /* Per-node private data */ | ||||
struct ng_bridge_private { | struct ng_bridge_private { | ||||
struct ng_bridge_bucket *tab; /* hash table bucket array */ | struct ng_bridge_bucket *tab; /* hash table bucket array */ | ||||
struct ng_bridge_config conf; /* node configuration */ | struct ng_bridge_config conf; /* node configuration */ | ||||
node_p node; /* netgraph node */ | node_p node; /* netgraph node */ | ||||
u_int numHosts; /* num entries in table */ | u_int numHosts; /* num entries in table */ | ||||
u_int numBuckets; /* num buckets in table */ | u_int numBuckets; /* num buckets in table */ | ||||
u_int hashMask; /* numBuckets - 1 */ | u_int hashMask; /* numBuckets - 1 */ | ||||
int numLinks; /* num connected links */ | int numLinks; /* num connected links */ | ||||
unsigned int persistent : 1, /* can exist w/o hooks */ | unsigned int persistent : 1, /* can exist w/o hooks */ | ||||
sendUnknown : 1;/* links receive unknowns by default */ | sendUnknown : 1;/* links receive unknowns by default */ | ||||
struct callout timer; /* one second periodic timer */ | struct callout timer; /* one second periodic timer */ | ||||
}; | }; | ||||
typedef struct ng_bridge_private *priv_p; | typedef struct ng_bridge_private *priv_p; | ||||
typedef struct ng_bridge_private const *priv_cp; /* read only access */ | |||||
/* Information about a host, stored in a hash table entry */ | /* Information about a host, stored in a hash table entry */ | ||||
struct ng_bridge_hent { | struct ng_bridge_hent { | ||||
struct ng_bridge_host host; /* actual host info */ | struct ng_bridge_host host; /* actual host info */ | ||||
SLIST_ENTRY(ng_bridge_hent) next; /* next entry in bucket */ | SLIST_ENTRY(ng_bridge_hent) next; /* next entry in bucket */ | ||||
}; | }; | ||||
/* Hash table bucket declaration */ | /* Hash table bucket declaration */ | ||||
SLIST_HEAD(ng_bridge_bucket, ng_bridge_hent); | SLIST_HEAD(ng_bridge_bucket, ng_bridge_hent); | ||||
/* Netgraph node methods */ | /* Netgraph node methods */ | ||||
static ng_constructor_t ng_bridge_constructor; | static ng_constructor_t ng_bridge_constructor; | ||||
static ng_rcvmsg_t ng_bridge_rcvmsg; | static ng_rcvmsg_t ng_bridge_rcvmsg; | ||||
static ng_shutdown_t ng_bridge_shutdown; | static ng_shutdown_t ng_bridge_shutdown; | ||||
static ng_newhook_t ng_bridge_newhook; | static ng_newhook_t ng_bridge_newhook; | ||||
static ng_rcvdata_t ng_bridge_rcvdata; | static ng_rcvdata_t ng_bridge_rcvdata; | ||||
static ng_disconnect_t ng_bridge_disconnect; | static ng_disconnect_t ng_bridge_disconnect; | ||||
/* Other internal functions */ | /* Other internal functions */ | ||||
static struct ng_bridge_host *ng_bridge_get(priv_p priv, const u_char *addr); | static struct ng_bridge_host *ng_bridge_get(priv_cp priv, const u_char *addr); | ||||
static int ng_bridge_put(priv_p priv, const u_char *addr, link_p link); | static int ng_bridge_put(priv_p priv, const u_char *addr, link_p link); | ||||
static void ng_bridge_rehash(priv_p priv); | static void ng_bridge_rehash(priv_p priv); | ||||
static void ng_bridge_remove_hosts(priv_p priv, link_p link); | static void ng_bridge_remove_hosts(priv_p priv, link_p link); | ||||
static void ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2); | static void ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2); | ||||
static const char *ng_bridge_nodename(node_p node); | static const char *ng_bridge_nodename(node_cp node); | ||||
/* Ethernet broadcast */ | /* Ethernet broadcast */ | ||||
static const u_char ng_bridge_bcast_addr[ETHER_ADDR_LEN] = | static const u_char ng_bridge_bcast_addr[ETHER_ADDR_LEN] = | ||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||||
/* Compare Ethernet addresses using 32 and 16 bit words instead of bytewise */ | /* Compare Ethernet addresses using 32 and 16 bit words instead of bytewise */ | ||||
#define ETHER_EQUAL(a,b) (((const u_int32_t *)(a))[0] \ | #define ETHER_EQUAL(a,b) (((const u_int32_t *)(a))[0] \ | ||||
== ((const u_int32_t *)(b))[0] \ | == ((const u_int32_t *)(b))[0] \ | ||||
▲ Show 20 Lines • Show All 749 Lines • ▼ Show 20 Lines | |||||
#define HASH(addr,mask) ( (((const u_int16_t *)(addr))[0] \ | #define HASH(addr,mask) ( (((const u_int16_t *)(addr))[0] \ | ||||
^ ((const u_int16_t *)(addr))[1] \ | ^ ((const u_int16_t *)(addr))[1] \ | ||||
^ ((const u_int16_t *)(addr))[2]) & (mask) ) | ^ ((const u_int16_t *)(addr))[2]) & (mask) ) | ||||
/* | /* | ||||
* Find a host entry in the table. | * Find a host entry in the table. | ||||
*/ | */ | ||||
static struct ng_bridge_host * | static struct ng_bridge_host * | ||||
ng_bridge_get(priv_p priv, const u_char *addr) | ng_bridge_get(priv_cp priv, const u_char *addr) | ||||
{ | { | ||||
const int bucket = HASH(addr, priv->hashMask); | const int bucket = HASH(addr, priv->hashMask); | ||||
struct ng_bridge_hent *hent; | struct ng_bridge_hent *hent; | ||||
SLIST_FOREACH(hent, &priv->tab[bucket], next) { | SLIST_FOREACH(hent, &priv->tab[bucket], next) { | ||||
if (ETHER_EQUAL(hent->host.addr, addr)) | if (ETHER_EQUAL(hent->host.addr, addr)) | ||||
return (&hent->host); | return (&hent->host); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2) | ||||
/* Register a new timeout, keeping the existing node reference */ | /* Register a new timeout, keeping the existing node reference */ | ||||
ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); | ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); | ||||
} | } | ||||
/* | /* | ||||
* Return node's "name", even if it doesn't have one. | * Return node's "name", even if it doesn't have one. | ||||
*/ | */ | ||||
static const char * | static const char * | ||||
ng_bridge_nodename(node_p node) | ng_bridge_nodename(node_cp node) | ||||
{ | { | ||||
static char name[NG_NODESIZ]; | static char name[NG_NODESIZ]; | ||||
if (NG_NODE_HAS_NAME(node)) | if (NG_NODE_HAS_NAME(node)) | ||||
snprintf(name, sizeof(name), "%s", NG_NODE_NAME(node)); | snprintf(name, sizeof(name), "%s", NG_NODE_NAME(node)); | ||||
else | else | ||||
snprintf(name, sizeof(name), "[%x]", ng_node2ID(node)); | snprintf(name, sizeof(name), "[%x]", ng_node2ID(node)); | ||||
return name; | return name; | ||||
} | } |