Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_bridge.c
Show First 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | |||||
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 */ | 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_host { | struct ng_bridge_host { | ||||
u_char addr[6]; /* ethernet address */ | u_char addr[6]; /* ethernet address */ | ||||
link_p link; /* link where addr can be found */ | link_p link; /* link where addr can be found */ | ||||
u_int16_t age; /* seconds ago entry was created */ | u_int16_t age; /* seconds ago entry was created */ | ||||
u_int16_t staleness; /* seconds ago host last heard from */ | counter_u64_t staleness; /* seconds ago host last heard from */ | ||||
SLIST_ENTRY(ng_bridge_host) next; /* next entry in bucket */ | SLIST_ENTRY(ng_bridge_host) next; /* next entry in bucket */ | ||||
}; | }; | ||||
/* Hash table bucket declaration */ | /* Hash table bucket declaration */ | ||||
SLIST_HEAD(ng_bridge_bucket, ng_bridge_host); | SLIST_HEAD(ng_bridge_bucket, ng_bridge_host); | ||||
/* Netgraph node methods */ | /* Netgraph node methods */ | ||||
static ng_constructor_t ng_bridge_constructor; | static ng_constructor_t ng_bridge_constructor; | ||||
▲ Show 20 Lines • Show All 432 Lines • ▼ Show 20 Lines | case NGM_BRIDGE_GET_TABLE: | ||||
ary = (struct ng_bridge_host_ary *)resp->data; | ary = (struct ng_bridge_host_ary *)resp->data; | ||||
ary->numHosts = priv->numHosts; | ary->numHosts = priv->numHosts; | ||||
for (bucket = 0; bucket < priv->numBuckets; bucket++) { | for (bucket = 0; bucket < priv->numBuckets; bucket++) { | ||||
SLIST_FOREACH(host, &priv->tab[bucket], next) { | SLIST_FOREACH(host, &priv->tab[bucket], next) { | ||||
memcpy(ary->hosts[i].addr, | memcpy(ary->hosts[i].addr, | ||||
host->addr, | host->addr, | ||||
sizeof(ary->hosts[i].addr)); | sizeof(ary->hosts[i].addr)); | ||||
ary->hosts[i].age = host->age; | ary->hosts[i].age = host->age; | ||||
ary->hosts[i].staleness = host->staleness; | ary->hosts[i].staleness = | ||||
counter_u64_fetch(host->staleness); | |||||
strncpy(ary->hosts[i].hook, | strncpy(ary->hosts[i].hook, | ||||
NG_HOOK_NAME(host->link->hook), | NG_HOOK_NAME(host->link->hook), | ||||
sizeof(ary->hosts[i].hook)); | sizeof(ary->hosts[i].hook)); | ||||
i++; | i++; | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | if (ETHER_EQUAL(eh->ether_dhost, ng_bridge_bcast_addr)) { | ||||
ctx.manycast = 2; | ctx.manycast = 2; | ||||
} else | } else | ||||
counter_u64_add(ctx.incoming->stats.recvMulticasts, 1); | counter_u64_add(ctx.incoming->stats.recvMulticasts, 1); | ||||
} | } | ||||
/* Look up packet's source Ethernet address in hashtable */ | /* Look up packet's source Ethernet address in hashtable */ | ||||
if ((host = ng_bridge_get(priv, eh->ether_shost)) != NULL) { | if ((host = ng_bridge_get(priv, eh->ether_shost)) != NULL) { | ||||
/* Update time since last heard from this host */ | /* Update time since last heard from this host */ | ||||
host->staleness = 0; | counter_u64_zero(host->staleness); | ||||
/* Did host jump to a different link? */ | /* Did host jump to a different link? */ | ||||
if (host->link != ctx.incoming) { | if (host->link != ctx.incoming) { | ||||
/* | /* | ||||
* If the host's old link was recently established | * If the host's old link was recently established | ||||
* on the old link and it's already jumped to a new | * on the old link and it's already jumped to a new | ||||
* link, declare a loopback condition. | * link, declare a loopback condition. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
/* Allocate and initialize new hashtable entry */ | /* Allocate and initialize new hashtable entry */ | ||||
host = malloc(sizeof(*host), M_NETGRAPH_BRIDGE, M_NOWAIT); | host = malloc(sizeof(*host), M_NETGRAPH_BRIDGE, M_NOWAIT); | ||||
if (host == NULL) | if (host == NULL) | ||||
return (0); | return (0); | ||||
bcopy(addr, host->addr, ETHER_ADDR_LEN); | bcopy(addr, host->addr, ETHER_ADDR_LEN); | ||||
host->link = link; | host->link = link; | ||||
host->staleness = 0; | |||||
host->age = 0; | host->age = 0; | ||||
host->staleness = counter_u64_alloc(M_NOWAIT); | |||||
if (host->staleness == NULL) { | |||||
free(host, M_NETGRAPH_BRIDGE); | |||||
return (0); | |||||
} | |||||
/* Add new element to hash bucket */ | /* Add new element to hash bucket */ | ||||
SLIST_INSERT_HEAD(&priv->tab[bucket], host, next); | SLIST_INSERT_HEAD(&priv->tab[bucket], host, next); | ||||
priv->numHosts++; | priv->numHosts++; | ||||
/* Resize table if necessary */ | /* Resize table if necessary */ | ||||
ng_bridge_rehash(priv); | ng_bridge_rehash(priv); | ||||
return (1); | return (1); | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | ng_bridge_remove_hosts(priv_p priv, link_p link) | ||||
for (bucket = 0; bucket < priv->numBuckets; bucket++) { | for (bucket = 0; bucket < priv->numBuckets; bucket++) { | ||||
struct ng_bridge_host **hptr = &SLIST_FIRST(&priv->tab[bucket]); | struct ng_bridge_host **hptr = &SLIST_FIRST(&priv->tab[bucket]); | ||||
while (*hptr != NULL) { | while (*hptr != NULL) { | ||||
struct ng_bridge_host *const host = *hptr; | struct ng_bridge_host *const host = *hptr; | ||||
if (link == NULL || host->link == link) { | if (link == NULL || host->link == link) { | ||||
*hptr = SLIST_NEXT(host, next); | *hptr = SLIST_NEXT(host, next); | ||||
counter_u64_free(host->staleness); | |||||
free(host, M_NETGRAPH_BRIDGE); | free(host, M_NETGRAPH_BRIDGE); | ||||
priv->numHosts--; | priv->numHosts--; | ||||
} else | } else | ||||
hptr = &SLIST_NEXT(host, next); | hptr = &SLIST_NEXT(host, next); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Show All 34 Lines | ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2) | ||||
/* Update host time counters and remove stale entries */ | /* Update host time counters and remove stale entries */ | ||||
for (bucket = 0; bucket < priv->numBuckets; bucket++) { | for (bucket = 0; bucket < priv->numBuckets; bucket++) { | ||||
struct ng_bridge_host **hptr = &SLIST_FIRST(&priv->tab[bucket]); | struct ng_bridge_host **hptr = &SLIST_FIRST(&priv->tab[bucket]); | ||||
while (*hptr != NULL) { | while (*hptr != NULL) { | ||||
struct ng_bridge_host *const host = *hptr; | struct ng_bridge_host *const host = *hptr; | ||||
/* Remove hosts we haven't heard from in a while */ | /* Remove hosts we haven't heard from in a while */ | ||||
if (++host->staleness >= priv->conf.maxStaleness) { | counter_u64_add(host->staleness, 1); | ||||
if (counter_u64_fetch(host->staleness) >= | |||||
priv->conf.maxStaleness) { | |||||
*hptr = SLIST_NEXT(host, next); | *hptr = SLIST_NEXT(host, next); | ||||
counter_u64_free(host->staleness); | |||||
free(host, M_NETGRAPH_BRIDGE); | free(host, M_NETGRAPH_BRIDGE); | ||||
priv->numHosts--; | priv->numHosts--; | ||||
} else { | } else { | ||||
if (host->age < 0xffff) | if (host->age < 0xffff) | ||||
host->age++; | host->age++; | ||||
hptr = &SLIST_NEXT(host, next); | hptr = &SLIST_NEXT(host, next); | ||||
counter++; | counter++; | ||||
} | } | ||||
Show All 32 Lines |