Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_bridge.c
Show First 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | struct ng_bridge_link_kernel_stats { | ||||
counter_u64_t loopDrops; /* pkts dropped due to loopback */ | counter_u64_t loopDrops; /* pkts dropped due to loopback */ | ||||
counter_u64_t loopDetects; /* number of loop detections */ | counter_u64_t loopDetects; /* number of loop detections */ | ||||
counter_u64_t memoryFailures; /* times couldn't get mem or mbuf */ | counter_u64_t memoryFailures; /* times couldn't get mem or mbuf */ | ||||
}; | }; | ||||
/* 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 */ | counter_u64_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 */ | 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 { | ||||
▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Lines | ng_bridge_newhook(node_p node, hook_p hook, const char *name) | ||||
if(NG_PEER_NODE(hook) == node) | if(NG_PEER_NODE(hook) == node) | ||||
return (ELOOP); | return (ELOOP); | ||||
link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_ZERO); | link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_ZERO); | ||||
if (link == NULL) | if (link == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
link->loopCount = counter_u64_alloc(M_WAITOK); | |||||
link->stats.recvOctets = counter_u64_alloc(M_WAITOK); | link->stats.recvOctets = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvPackets = counter_u64_alloc(M_WAITOK); | link->stats.recvPackets = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvMulticasts = counter_u64_alloc(M_WAITOK); | link->stats.recvMulticasts = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvBroadcasts = counter_u64_alloc(M_WAITOK); | link->stats.recvBroadcasts = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvUnknown = counter_u64_alloc(M_WAITOK); | link->stats.recvUnknown = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvRunts = counter_u64_alloc(M_WAITOK); | link->stats.recvRunts = counter_u64_alloc(M_WAITOK); | ||||
link->stats.recvInvalid = counter_u64_alloc(M_WAITOK); | link->stats.recvInvalid = counter_u64_alloc(M_WAITOK); | ||||
link->stats.xmitOctets = counter_u64_alloc(M_WAITOK); | link->stats.xmitOctets = counter_u64_alloc(M_WAITOK); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | static void ng_bridge_clear_link_stats(struct ng_bridge_link_kernel_stats * p) | ||||
counter_u64_zero(p->memoryFailures); | counter_u64_zero(p->memoryFailures); | ||||
}; | }; | ||||
static int | static int | ||||
ng_bridge_reset_link(hook_p hook, void *arg __unused) | ng_bridge_reset_link(hook_p hook, void *arg __unused) | ||||
{ | { | ||||
link_p priv = NG_HOOK_PRIVATE(hook); | link_p priv = NG_HOOK_PRIVATE(hook); | ||||
priv->loopCount = 0; | counter_u64_zero(priv->loopCount); | ||||
ng_bridge_clear_link_stats(&priv->stats); | ng_bridge_clear_link_stats(&priv->stats); | ||||
return (1); | return (1); | ||||
} | } | ||||
static int | static int | ||||
ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook) | ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook) | ||||
{ | { | ||||
const priv_p priv = NG_NODE_PRIVATE(node); | const priv_p priv = NG_NODE_PRIVATE(node); | ||||
▲ Show 20 Lines • Show All 251 Lines • ▼ Show 20 Lines | ng_bridge_rcvdata(hook_p hook, item_p item) | ||||
if ((eh->ether_shost[0] & 1) != 0) { | if ((eh->ether_shost[0] & 1) != 0) { | ||||
counter_u64_add(ctx.incoming->stats.recvInvalid, 1); | counter_u64_add(ctx.incoming->stats.recvInvalid, 1); | ||||
NG_FREE_ITEM(item); | NG_FREE_ITEM(item); | ||||
NG_FREE_M(ctx.m); | NG_FREE_M(ctx.m); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Is link disabled due to a loopback condition? */ | /* Is link disabled due to a loopback condition? */ | ||||
if (ctx.incoming->loopCount != 0) { | if (counter_u64_fetch(ctx.incoming->loopCount) != 0) { | ||||
counter_u64_add(ctx.incoming->stats.loopDrops, 1); | counter_u64_add(ctx.incoming->stats.loopDrops, 1); | ||||
NG_FREE_ITEM(item); | NG_FREE_ITEM(item); | ||||
NG_FREE_M(ctx.m); | NG_FREE_M(ctx.m); | ||||
return (ELOOP); /* XXX is this an appropriate error? */ | return (ELOOP); /* XXX is this an appropriate error? */ | ||||
} | } | ||||
/* Update stats */ | /* Update stats */ | ||||
counter_u64_add(ctx.incoming->stats.recvPackets, 1); | counter_u64_add(ctx.incoming->stats.recvPackets, 1); | ||||
Show All 34 Lines | if (host->link != ctx.incoming) { | ||||
*suffix = '\0'; | *suffix = '\0'; | ||||
log(LOG_WARNING, "ng_bridge: %s:" | log(LOG_WARNING, "ng_bridge: %s:" | ||||
" loopback detected on %s%s\n", | " loopback detected on %s%s\n", | ||||
ng_bridge_nodename(node), | ng_bridge_nodename(node), | ||||
NG_HOOK_NAME(hook), suffix); | NG_HOOK_NAME(hook), suffix); | ||||
} | } | ||||
/* Mark link as linka non grata */ | /* Mark link as linka non grata */ | ||||
ctx.incoming->loopCount = priv->conf.loopTimeout; | counter_u64_add(ctx.incoming->loopCount, | ||||
priv->conf.loopTimeout); | |||||
counter_u64_add(ctx.incoming->stats.loopDetects, 1); | counter_u64_add(ctx.incoming->stats.loopDetects, 1); | ||||
/* Forget all hosts on this link */ | /* Forget all hosts on this link */ | ||||
ng_bridge_remove_hosts(priv, ctx.incoming); | ng_bridge_remove_hosts(priv, ctx.incoming); | ||||
/* Drop packet */ | /* Drop packet */ | ||||
counter_u64_add(ctx.incoming->stats.loopDrops, 1); | counter_u64_add(ctx.incoming->stats.loopDrops, 1); | ||||
NG_FREE_ITEM(item); | NG_FREE_ITEM(item); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); | const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); | ||||
link_p link = NG_HOOK_PRIVATE(hook); | link_p link = NG_HOOK_PRIVATE(hook); | ||||
/* Remove all hosts associated with this link */ | /* Remove all hosts associated with this link */ | ||||
ng_bridge_remove_hosts(priv, link); | ng_bridge_remove_hosts(priv, link); | ||||
/* Free associated link information */ | /* Free associated link information */ | ||||
counter_u64_free(link->loopCount); | |||||
counter_u64_free(link->stats.recvOctets); | counter_u64_free(link->stats.recvOctets); | ||||
counter_u64_free(link->stats.recvPackets); | counter_u64_free(link->stats.recvPackets); | ||||
counter_u64_free(link->stats.recvMulticasts); | counter_u64_free(link->stats.recvMulticasts); | ||||
counter_u64_free(link->stats.recvBroadcasts); | counter_u64_free(link->stats.recvBroadcasts); | ||||
counter_u64_free(link->stats.recvUnknown); | counter_u64_free(link->stats.recvUnknown); | ||||
counter_u64_free(link->stats.recvRunts); | counter_u64_free(link->stats.recvRunts); | ||||
counter_u64_free(link->stats.recvInvalid); | counter_u64_free(link->stats.recvInvalid); | ||||
counter_u64_free(link->stats.xmitOctets); | counter_u64_free(link->stats.xmitOctets); | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
ng_bridge_unmute(hook_p hook, void *arg) | ng_bridge_unmute(hook_p hook, void *arg) | ||||
{ | { | ||||
link_p link = NG_HOOK_PRIVATE(hook); | link_p link = NG_HOOK_PRIVATE(hook); | ||||
node_p node = NG_HOOK_NODE(hook); | node_p node = NG_HOOK_NODE(hook); | ||||
priv_p priv = NG_NODE_PRIVATE(node); | priv_p priv = NG_NODE_PRIVATE(node); | ||||
int *counter = arg; | int *counter = arg; | ||||
uint64_t loopCount = counter_u64_fetch(link->loopCount); | |||||
if (link->loopCount != 0) { | if (loopCount != 0) { | ||||
link->loopCount--; | if (loopCount > priv->conf.loopTimeout) { | ||||
if (link->loopCount == 0 && priv->conf.debugLevel >= 2) { | counter_u64_zero(link->loopCount); | ||||
counter_u64_add(link->loopCount, | |||||
priv->conf.loopTimeout); | |||||
} else if (loopCount > 2) | |||||
counter_u64_add(link->loopCount, -1); | |||||
else { | |||||
counter_u64_zero(link->loopCount); | |||||
if (priv->conf.debugLevel >= 2) | |||||
log(LOG_INFO, "ng_bridge: %s:" | log(LOG_INFO, "ng_bridge: %s:" | ||||
" restoring looped back %s\n", | " restoring looped back %s\n", | ||||
ng_bridge_nodename(node), NG_HOOK_NAME(hook)); | ng_bridge_nodename(node), | ||||
NG_HOOK_NAME(hook)); | |||||
} | } | ||||
} | } | ||||
(*counter)++; | (*counter)++; | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2) | ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2) | ||||
▲ Show 20 Lines • Show All 56 Lines • Show Last 20 Lines |