Lines 124-129
struct ng_bridge_private {
Link Here
|
124 |
unsigned int persistent : 1, /* can exist w/o hooks */ |
124 |
unsigned int persistent : 1, /* can exist w/o hooks */ |
125 |
sendUnknown : 1;/* links receive unknowns by default */ |
125 |
sendUnknown : 1;/* links receive unknowns by default */ |
126 |
struct callout timer; /* one second periodic timer */ |
126 |
struct callout timer; /* one second periodic timer */ |
|
|
127 |
struct unrhdr *linkUnit; /* link unit number allocator */ |
128 |
struct unrhdr *uplinkUnit; /* uplink unit number allocator */ |
127 |
}; |
129 |
}; |
128 |
typedef struct ng_bridge_private *priv_p; |
130 |
typedef struct ng_bridge_private *priv_p; |
129 |
typedef struct ng_bridge_private const *priv_cp; /* read only access */ |
131 |
typedef struct ng_bridge_private const *priv_cp; /* read only access */ |
Lines 140-145
struct ng_bridge_host {
Link Here
|
140 |
/* Hash table bucket declaration */ |
142 |
/* Hash table bucket declaration */ |
141 |
SLIST_HEAD(ng_bridge_bucket, ng_bridge_host); |
143 |
SLIST_HEAD(ng_bridge_bucket, ng_bridge_host); |
142 |
|
144 |
|
|
|
145 |
/* [up]link prefix matching */ |
146 |
struct ng_link_prefix { |
147 |
const char * const prefix; |
148 |
size_t len; |
149 |
}; |
150 |
|
151 |
static const struct ng_link_prefix link_pfx = { |
152 |
.prefix = NG_BRIDGE_HOOK_LINK_PREFIX, |
153 |
.len = sizeof(NG_BRIDGE_HOOK_LINK_PREFIX) - 1, |
154 |
}; |
155 |
static const struct ng_link_prefix uplink_pfx = { |
156 |
.prefix = NG_BRIDGE_HOOK_UPLINK_PREFIX, |
157 |
.len = sizeof(NG_BRIDGE_HOOK_UPLINK_PREFIX) - 1, |
158 |
}; |
159 |
|
143 |
/* Netgraph node methods */ |
160 |
/* Netgraph node methods */ |
144 |
static ng_constructor_t ng_bridge_constructor; |
161 |
static ng_constructor_t ng_bridge_constructor; |
145 |
static ng_rcvmsg_t ng_bridge_rcvmsg; |
162 |
static ng_rcvmsg_t ng_bridge_rcvmsg; |
Lines 149-154
static ng_rcvdata_t ng_bridge_rcvdata;
Link Here
|
149 |
static ng_disconnect_t ng_bridge_disconnect; |
166 |
static ng_disconnect_t ng_bridge_disconnect; |
150 |
|
167 |
|
151 |
/* Other internal functions */ |
168 |
/* Other internal functions */ |
|
|
169 |
static const struct ng_link_prefix *ng_get_link_prefix(const char *name); |
152 |
static void ng_bridge_free_link(link_p link); |
170 |
static void ng_bridge_free_link(link_p link); |
153 |
static struct ng_bridge_host *ng_bridge_get(priv_cp priv, const u_char *addr); |
171 |
static struct ng_bridge_host *ng_bridge_get(priv_cp priv, const u_char *addr); |
154 |
static int ng_bridge_put(priv_p priv, const u_char *addr, link_p link); |
172 |
static int ng_bridge_put(priv_p priv, const u_char *addr, link_p link); |
Lines 350-355
ng_bridge_constructor(node_p node)
Link Here
|
350 |
NG_NODE_SET_PRIVATE(node, priv); |
368 |
NG_NODE_SET_PRIVATE(node, priv); |
351 |
priv->node = node; |
369 |
priv->node = node; |
352 |
|
370 |
|
|
|
371 |
/* allocator for links */ |
372 |
priv->linkUnit = new_unrhdr(0, INT_MAX, NULL); |
373 |
priv->uplinkUnit = new_unrhdr(1, INT_MAX, NULL); /* 0 not valid uplink */ |
374 |
|
353 |
/* Start timer; timer is always running while node is alive */ |
375 |
/* Start timer; timer is always running while node is alive */ |
354 |
ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); |
376 |
ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); |
355 |
|
377 |
|
Lines 364-399
static int
Link Here
|
364 |
ng_bridge_newhook(node_p node, hook_p hook, const char *name) |
386 |
ng_bridge_newhook(node_p node, hook_p hook, const char *name) |
365 |
{ |
387 |
{ |
366 |
const priv_p priv = NG_NODE_PRIVATE(node); |
388 |
const priv_p priv = NG_NODE_PRIVATE(node); |
367 |
char linkName[NG_HOOKSIZ]; |
|
|
368 |
u_int32_t linkNum; |
369 |
link_p link; |
389 |
link_p link; |
370 |
const char *prefix = NG_BRIDGE_HOOK_LINK_PREFIX; |
|
|
371 |
bool isUplink; |
390 |
bool isUplink; |
|
|
391 |
uint32_t linkNum; |
392 |
struct unrhdr *unit; |
393 |
|
394 |
const struct ng_link_prefix *pfx = ng_get_link_prefix(name); |
395 |
if (pfx == NULL) |
396 |
return (EINVAL); /* not a valid prefix */ |
397 |
|
398 |
isUplink = (pfx == &uplink_pfx); |
399 |
unit = isUplink ? priv->uplinkUnit : priv->linkUnit; |
400 |
|
401 |
if (strlen(name) > pfx->len) { /* given number */ |
402 |
char linkName[NG_HOOKSIZ]; |
403 |
/* primitive parsing */ |
404 |
linkNum = strtoul(name + pfx->len, NULL, 10); |
405 |
/* validation by comparing against the reconstucted name */ |
406 |
snprintf(linkName, sizeof(linkName), "%s%u", pfx->prefix, |
407 |
linkNum); |
408 |
if (strcmp(linkName, name) != 0) |
409 |
return (EINVAL); |
410 |
if (linkNum == 0 && isUplink) |
411 |
return (EINVAL); |
412 |
alloc_unr_specific(unit, linkNum); |
413 |
} else { |
414 |
/* auto-assign and update hook name */ |
415 |
linkNum = alloc_unr(unit); |
416 |
snprintf(NG_HOOK_NAME(hook), NG_HOOKSIZ, "%s%u", pfx->prefix, linkNum); |
417 |
} |
372 |
|
418 |
|
373 |
/* Check for a link hook */ |
419 |
if(NG_PEER_NODE(hook) == node) { |
374 |
if (strlen(name) <= strlen(prefix)) |
420 |
free_unr(unit, linkNum); |
375 |
return (EINVAL); /* Unknown hook name */ |
|
|
376 |
|
377 |
isUplink = (name[0] == 'u'); |
378 |
if (isUplink) |
379 |
prefix = NG_BRIDGE_HOOK_UPLINK_PREFIX; |
380 |
|
381 |
/* primitive parsing */ |
382 |
linkNum = strtoul(name + strlen(prefix), NULL, 10); |
383 |
/* validation by comparing against the reconstucted name */ |
384 |
snprintf(linkName, sizeof(linkName), "%s%u", prefix, linkNum); |
385 |
if (strcmp(linkName, name) != 0) |
386 |
return (EINVAL); |
387 |
|
388 |
if (linkNum == 0 && isUplink) |
389 |
return (EINVAL); |
390 |
|
391 |
if(NG_PEER_NODE(hook) == node) |
392 |
return (ELOOP); |
421 |
return (ELOOP); |
|
|
422 |
} |
393 |
|
423 |
|
394 |
link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO); |
424 |
link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO); |
395 |
if (link == NULL) |
425 |
if (link == NULL) { |
|
|
426 |
free_unr(unit, linkNum); |
396 |
return (ENOMEM); |
427 |
return (ENOMEM); |
|
|
428 |
} |
397 |
|
429 |
|
398 |
#define NG_BRIDGE_COUNTER_ALLOC(f) do { \ |
430 |
#define NG_BRIDGE_COUNTER_ALLOC(f) do { \ |
399 |
link->stats.f = counter_u64_alloc(M_NOWAIT); \ |
431 |
link->stats.f = counter_u64_alloc(M_NOWAIT); \ |
Lines 431-436
ng_bridge_newhook(node_p node, hook_p hook, const char *name)
Link Here
|
431 |
return (0); |
463 |
return (0); |
432 |
|
464 |
|
433 |
nomem: |
465 |
nomem: |
|
|
466 |
free_unr(unit, linkNum); |
434 |
ng_bridge_free_link(link); |
467 |
ng_bridge_free_link(link); |
435 |
return (ENOMEM); |
468 |
return (ENOMEM); |
436 |
} |
469 |
} |
Lines 913-918
ng_bridge_shutdown(node_p node)
Link Here
|
913 |
KASSERT(priv->numLinks == 0 && priv->numHosts == 0, |
946 |
KASSERT(priv->numLinks == 0 && priv->numHosts == 0, |
914 |
("%s: numLinks=%d numHosts=%d", |
947 |
("%s: numLinks=%d numHosts=%d", |
915 |
__func__, priv->numLinks, priv->numHosts)); |
948 |
__func__, priv->numLinks, priv->numHosts)); |
|
|
949 |
delete_unrhdr(priv->linkUnit); /* assert means no need to clear */ |
950 |
delete_unrhdr(priv->uplinkUnit); |
916 |
ng_uncallout(&priv->timer, node); |
951 |
ng_uncallout(&priv->timer, node); |
917 |
NG_NODE_SET_PRIVATE(node, NULL); |
952 |
NG_NODE_SET_PRIVATE(node, NULL); |
918 |
NG_NODE_UNREF(node); |
953 |
NG_NODE_UNREF(node); |
Lines 927-934
ng_bridge_shutdown(node_p node)
Link Here
|
927 |
static int |
962 |
static int |
928 |
ng_bridge_disconnect(hook_p hook) |
963 |
ng_bridge_disconnect(hook_p hook) |
929 |
{ |
964 |
{ |
|
|
965 |
char *name = NG_HOOK_NAME(hook); |
930 |
const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); |
966 |
const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); |
931 |
link_p link = NG_HOOK_PRIVATE(hook); |
967 |
link_p link = NG_HOOK_PRIVATE(hook); |
|
|
968 |
const struct ng_link_prefix *pfx = ng_get_link_prefix(name); |
969 |
uint32_t linkNum; |
932 |
|
970 |
|
933 |
/* Remove all hosts associated with this link */ |
971 |
/* Remove all hosts associated with this link */ |
934 |
ng_bridge_remove_hosts(priv, link); |
972 |
ng_bridge_remove_hosts(priv, link); |
Lines 937-942
ng_bridge_disconnect(hook_p hook)
Link Here
|
937 |
ng_bridge_free_link(link); |
975 |
ng_bridge_free_link(link); |
938 |
priv->numLinks--; |
976 |
priv->numLinks--; |
939 |
|
977 |
|
|
|
978 |
linkNum = strtoul(name + pfx->len, NULL, 10); |
979 |
free_unr(pfx == &link_pfx ? priv->linkUnit: priv->uplinkUnit, linkNum); |
980 |
|
940 |
/* If no more hooks, go away */ |
981 |
/* If no more hooks, go away */ |
941 |
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) |
982 |
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) |
942 |
&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) |
983 |
&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) |
Lines 1095-1100
ng_bridge_rehash(priv_p priv)
Link Here
|
1095 |
MISC FUNCTIONS |
1136 |
MISC FUNCTIONS |
1096 |
******************************************************************/ |
1137 |
******************************************************************/ |
1097 |
|
1138 |
|
|
|
1139 |
static const struct ng_link_prefix * |
1140 |
ng_get_link_prefix(const char *name) |
1141 |
{ |
1142 |
static const struct ng_link_prefix *pfxs[] = { &link_pfx, &uplink_pfx, }; |
1143 |
|
1144 |
for (u_int i = 0; i < nitems(pfxs); i++) |
1145 |
if (strncmp(pfxs[i]->prefix, name, pfxs[i]->len) == 0) |
1146 |
return (pfxs[i]); |
1147 |
|
1148 |
return (NULL); |
1149 |
} |
1150 |
|
1098 |
/* |
1151 |
/* |
1099 |
* Remove all hosts associated with a specific link from the hashtable. |
1152 |
* Remove all hosts associated with a specific link from the hashtable. |
1100 |
* If linkNum == -1, then remove all hosts in the table. |
1153 |
* If linkNum == -1, then remove all hosts in the table. |
1101 |
- |
|
|