ng_bridge.c (9199c09a159c4e3e98c212d4eec1edc5252d9e33) | ng_bridge.c (ed2dbd316aca41338dbad82208cd24cb96b33faa) |
---|---|
1 |
|
1/* 2 * ng_bridge.c | 2/* 3 * ng_bridge.c |
3 */ 4 5/*- | 4 * |
6 * Copyright (c) 2000 Whistle Communications, Inc. 7 * All rights reserved. 8 * 9 * Subject to the following obligations and disclaimer of warranty, use and 10 * redistribution of this software, in source or object code forms, with or 11 * without modifications are expressly permitted by Whistle Communications; 12 * provided, however, that: 13 * 1. Any and all reproductions of the source or object code must include the --- 42 unchanged lines hidden (view full) --- 56 * 57 * This node is optimzed for stable networks, where machines jump 58 * from one port to the other only rarely. 59 */ 60 61#include <sys/param.h> 62#include <sys/systm.h> 63#include <sys/kernel.h> | 5 * Copyright (c) 2000 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and 9 * redistribution of this software, in source or object code forms, with or 10 * without modifications are expressly permitted by Whistle Communications; 11 * provided, however, that: 12 * 1. Any and all reproductions of the source or object code must include the --- 42 unchanged lines hidden (view full) --- 55 * 56 * This node is optimzed for stable networks, where machines jump 57 * from one port to the other only rarely. 58 */ 59 60#include <sys/param.h> 61#include <sys/systm.h> 62#include <sys/kernel.h> |
64#include <sys/lock.h> | |
65#include <sys/malloc.h> 66#include <sys/mbuf.h> 67#include <sys/errno.h> | 63#include <sys/malloc.h> 64#include <sys/mbuf.h> 65#include <sys/errno.h> |
68#include <sys/rwlock.h> | |
69#include <sys/syslog.h> 70#include <sys/socket.h> 71#include <sys/ctype.h> 72 73#include <net/if.h> 74#include <net/ethernet.h> | 66#include <sys/syslog.h> 67#include <sys/socket.h> 68#include <sys/ctype.h> 69 70#include <net/if.h> 71#include <net/ethernet.h> |
75#include <net/vnet.h> | |
76 77#include <netinet/in.h> | 72 73#include <netinet/in.h> |
78#if 0 /* not used yet */ | |
79#include <netinet/ip_fw.h> | 74#include <netinet/ip_fw.h> |
80#endif | 75 |
81#include <netgraph/ng_message.h> 82#include <netgraph/netgraph.h> 83#include <netgraph/ng_parse.h> 84#include <netgraph/ng_bridge.h> | 76#include <netgraph/ng_message.h> 77#include <netgraph/netgraph.h> 78#include <netgraph/ng_parse.h> 79#include <netgraph/ng_bridge.h> |
80#include <netgraph/ng_ether.h> |
|
85 | 81 |
86#ifdef NG_SEPARATE_MALLOC 87MALLOC_DEFINE(M_NETGRAPH_BRIDGE, "netgraph_bridge", "netgraph bridge node "); 88#else 89#define M_NETGRAPH_BRIDGE M_NETGRAPH 90#endif 91 | |
92/* Per-link private data */ 93struct ng_bridge_link { 94 hook_p hook; /* netgraph hook */ 95 u_int16_t loopCount; /* loop ignore timer */ 96 struct ng_bridge_link_stats stats; /* link stats */ 97}; 98 99/* Per-node private data */ --- 17 unchanged lines hidden (view full) --- 117}; 118 119/* Hash table bucket declaration */ 120SLIST_HEAD(ng_bridge_bucket, ng_bridge_hent); 121 122/* Netgraph node methods */ 123static ng_constructor_t ng_bridge_constructor; 124static ng_rcvmsg_t ng_bridge_rcvmsg; | 82/* Per-link private data */ 83struct ng_bridge_link { 84 hook_p hook; /* netgraph hook */ 85 u_int16_t loopCount; /* loop ignore timer */ 86 struct ng_bridge_link_stats stats; /* link stats */ 87}; 88 89/* Per-node private data */ --- 17 unchanged lines hidden (view full) --- 107}; 108 109/* Hash table bucket declaration */ 110SLIST_HEAD(ng_bridge_bucket, ng_bridge_hent); 111 112/* Netgraph node methods */ 113static ng_constructor_t ng_bridge_constructor; 114static ng_rcvmsg_t ng_bridge_rcvmsg; |
125static ng_shutdown_t ng_bridge_shutdown; | 115static ng_shutdown_t ng_bridge_rmnode; |
126static ng_newhook_t ng_bridge_newhook; 127static ng_rcvdata_t ng_bridge_rcvdata; 128static ng_disconnect_t ng_bridge_disconnect; 129 130/* Other internal functions */ 131static struct ng_bridge_host *ng_bridge_get(priv_p priv, const u_char *addr); 132static int ng_bridge_put(priv_p priv, const u_char *addr, int linkNum); 133static void ng_bridge_rehash(priv_p priv); 134static void ng_bridge_remove_hosts(priv_p priv, int linkNum); | 116static ng_newhook_t ng_bridge_newhook; 117static ng_rcvdata_t ng_bridge_rcvdata; 118static ng_disconnect_t ng_bridge_disconnect; 119 120/* Other internal functions */ 121static struct ng_bridge_host *ng_bridge_get(priv_p priv, const u_char *addr); 122static int ng_bridge_put(priv_p priv, const u_char *addr, int linkNum); 123static void ng_bridge_rehash(priv_p priv); 124static void ng_bridge_remove_hosts(priv_p priv, int linkNum); |
135static void ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2); | 125static void ng_bridge_timeout(void *arg); |
136static const char *ng_bridge_nodename(node_p node); 137 138/* Ethernet broadcast */ 139static const u_char ng_bridge_bcast_addr[ETHER_ADDR_LEN] = 140 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 141 142/* Store each hook's link number in the private field */ 143#define LINK_NUM(hook) (*(u_int16_t *)(&(hook)->private)) --- 26 unchanged lines hidden (view full) --- 170{ 171 const struct ng_bridge_host_ary *const hary 172 = (const struct ng_bridge_host_ary *)(buf - sizeof(u_int32_t)); 173 174 return hary->numHosts; 175} 176 177/* Parse type for struct ng_bridge_host_ary */ | 126static const char *ng_bridge_nodename(node_p node); 127 128/* Ethernet broadcast */ 129static const u_char ng_bridge_bcast_addr[ETHER_ADDR_LEN] = 130 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 131 132/* Store each hook's link number in the private field */ 133#define LINK_NUM(hook) (*(u_int16_t *)(&(hook)->private)) --- 26 unchanged lines hidden (view full) --- 160{ 161 const struct ng_bridge_host_ary *const hary 162 = (const struct ng_bridge_host_ary *)(buf - sizeof(u_int32_t)); 163 164 return hary->numHosts; 165} 166 167/* Parse type for struct ng_bridge_host_ary */ |
178static const struct ng_parse_struct_field ng_bridge_host_type_fields[] 179 = NG_BRIDGE_HOST_TYPE_INFO(&ng_parse_enaddr_type); | 168static const struct ng_parse_struct_info ng_bridge_host_type_info 169 = NG_BRIDGE_HOST_TYPE_INFO(&ng_ether_enaddr_type); |
180static const struct ng_parse_type ng_bridge_host_type = { 181 &ng_parse_struct_type, | 170static const struct ng_parse_type ng_bridge_host_type = { 171 &ng_parse_struct_type, |
182 &ng_bridge_host_type_fields | 172 &ng_bridge_host_type_info |
183}; 184static const struct ng_parse_array_info ng_bridge_hary_type_info = { 185 &ng_bridge_host_type, 186 ng_bridge_getTableLength 187}; 188static const struct ng_parse_type ng_bridge_hary_type = { 189 &ng_parse_array_type, 190 &ng_bridge_hary_type_info 191}; | 173}; 174static const struct ng_parse_array_info ng_bridge_hary_type_info = { 175 &ng_bridge_host_type, 176 ng_bridge_getTableLength 177}; 178static const struct ng_parse_type ng_bridge_hary_type = { 179 &ng_parse_array_type, 180 &ng_bridge_hary_type_info 181}; |
192static const struct ng_parse_struct_field ng_bridge_host_ary_type_fields[] | 182static const struct ng_parse_struct_info ng_bridge_host_ary_type_info |
193 = NG_BRIDGE_HOST_ARY_TYPE_INFO(&ng_bridge_hary_type); 194static const struct ng_parse_type ng_bridge_host_ary_type = { 195 &ng_parse_struct_type, | 183 = NG_BRIDGE_HOST_ARY_TYPE_INFO(&ng_bridge_hary_type); 184static const struct ng_parse_type ng_bridge_host_ary_type = { 185 &ng_parse_struct_type, |
196 &ng_bridge_host_ary_type_fields | 186 &ng_bridge_host_ary_type_info |
197}; 198 199/* Parse type for struct ng_bridge_config */ 200static const struct ng_parse_fixedarray_info ng_bridge_ipfwary_type_info = { 201 &ng_parse_uint8_type, 202 NG_BRIDGE_MAX_LINKS 203}; 204static const struct ng_parse_type ng_bridge_ipfwary_type = { 205 &ng_parse_fixedarray_type, 206 &ng_bridge_ipfwary_type_info 207}; | 187}; 188 189/* Parse type for struct ng_bridge_config */ 190static const struct ng_parse_fixedarray_info ng_bridge_ipfwary_type_info = { 191 &ng_parse_uint8_type, 192 NG_BRIDGE_MAX_LINKS 193}; 194static const struct ng_parse_type ng_bridge_ipfwary_type = { 195 &ng_parse_fixedarray_type, 196 &ng_bridge_ipfwary_type_info 197}; |
208static const struct ng_parse_struct_field ng_bridge_config_type_fields[] | 198static const struct ng_parse_struct_info ng_bridge_config_type_info |
209 = NG_BRIDGE_CONFIG_TYPE_INFO(&ng_bridge_ipfwary_type); 210static const struct ng_parse_type ng_bridge_config_type = { 211 &ng_parse_struct_type, | 199 = NG_BRIDGE_CONFIG_TYPE_INFO(&ng_bridge_ipfwary_type); 200static const struct ng_parse_type ng_bridge_config_type = { 201 &ng_parse_struct_type, |
212 &ng_bridge_config_type_fields | 202 &ng_bridge_config_type_info |
213}; 214 215/* Parse type for struct ng_bridge_link_stat */ | 203}; 204 205/* Parse type for struct ng_bridge_link_stat */ |
216static const struct ng_parse_struct_field ng_bridge_stats_type_fields[] 217 = NG_BRIDGE_STATS_TYPE_INFO; | 206static const struct ng_parse_struct_info 207 ng_bridge_stats_type_info = NG_BRIDGE_STATS_TYPE_INFO; |
218static const struct ng_parse_type ng_bridge_stats_type = { 219 &ng_parse_struct_type, | 208static const struct ng_parse_type ng_bridge_stats_type = { 209 &ng_parse_struct_type, |
220 &ng_bridge_stats_type_fields | 210 &ng_bridge_stats_type_info |
221}; 222 223/* List of commands and how to convert arguments to/from ASCII */ 224static const struct ng_cmdlist ng_bridge_cmdlist[] = { 225 { 226 NGM_BRIDGE_COOKIE, 227 NGM_BRIDGE_SET_CONFIG, 228 "setconfig", --- 42 unchanged lines hidden (view full) --- 271 NULL, 272 &ng_bridge_host_ary_type 273 }, 274 { 0 } 275}; 276 277/* Node type descriptor */ 278static struct ng_type ng_bridge_typestruct = { | 211}; 212 213/* List of commands and how to convert arguments to/from ASCII */ 214static const struct ng_cmdlist ng_bridge_cmdlist[] = { 215 { 216 NGM_BRIDGE_COOKIE, 217 NGM_BRIDGE_SET_CONFIG, 218 "setconfig", --- 42 unchanged lines hidden (view full) --- 261 NULL, 262 &ng_bridge_host_ary_type 263 }, 264 { 0 } 265}; 266 267/* Node type descriptor */ 268static struct ng_type ng_bridge_typestruct = { |
279 .version = NG_ABI_VERSION, 280 .name = NG_BRIDGE_NODE_TYPE, 281 .constructor = ng_bridge_constructor, 282 .rcvmsg = ng_bridge_rcvmsg, 283 .shutdown = ng_bridge_shutdown, 284 .newhook = ng_bridge_newhook, 285 .rcvdata = ng_bridge_rcvdata, 286 .disconnect = ng_bridge_disconnect, 287 .cmdlist = ng_bridge_cmdlist, | 269 NG_VERSION, 270 NG_BRIDGE_NODE_TYPE, 271 NULL, 272 ng_bridge_constructor, 273 ng_bridge_rcvmsg, 274 ng_bridge_rmnode, 275 ng_bridge_newhook, 276 NULL, 277 NULL, 278 ng_bridge_rcvdata, 279 ng_bridge_rcvdata, 280 ng_bridge_disconnect, 281 ng_bridge_cmdlist, |
288}; | 282}; |
289NETGRAPH_INIT(bridge, &ng_bridge_typestruct); | 283NETGRAPH_INIT(ether, &ng_bridge_typestruct); |
290 | 284 |
285/* Depend on ng_ether so we can use the Ethernet parse type */ 286MODULE_DEPEND(ng_bridge, ng_ether, 1, 1, 1); 287 |
|
291/****************************************************************** 292 NETGRAPH NODE METHODS 293******************************************************************/ 294 295/* 296 * Node constructor 297 */ 298static int | 288/****************************************************************** 289 NETGRAPH NODE METHODS 290******************************************************************/ 291 292/* 293 * Node constructor 294 */ 295static int |
299ng_bridge_constructor(node_p node) | 296ng_bridge_constructor(node_p *nodep) |
300{ 301 priv_p priv; | 297{ 298 priv_p priv; |
299 int error; |
|
302 303 /* Allocate and initialize private info */ | 300 301 /* Allocate and initialize private info */ |
304 priv = malloc(sizeof(*priv), M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO); | 302 MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT); |
305 if (priv == NULL) 306 return (ENOMEM); | 303 if (priv == NULL) 304 return (ENOMEM); |
307 ng_callout_init(&priv->timer); | 305 bzero(priv, sizeof(*priv)); 306 callout_init(&priv->timer); |
308 309 /* Allocate and initialize hash table, etc. */ | 307 308 /* Allocate and initialize hash table, etc. */ |
310 priv->tab = malloc(MIN_BUCKETS * sizeof(*priv->tab), 311 M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO); | 309 MALLOC(priv->tab, struct ng_bridge_bucket *, 310 MIN_BUCKETS * sizeof(*priv->tab), M_NETGRAPH, M_NOWAIT); |
312 if (priv->tab == NULL) { | 311 if (priv->tab == NULL) { |
313 free(priv, M_NETGRAPH_BRIDGE); | 312 FREE(priv, M_NETGRAPH); |
314 return (ENOMEM); 315 } | 313 return (ENOMEM); 314 } |
315 bzero(priv->tab, MIN_BUCKETS * sizeof(*priv->tab)); /* init SLIST's */ |
|
316 priv->numBuckets = MIN_BUCKETS; 317 priv->hashMask = MIN_BUCKETS - 1; 318 priv->conf.debugLevel = 1; 319 priv->conf.loopTimeout = DEFAULT_LOOP_TIMEOUT; 320 priv->conf.maxStaleness = DEFAULT_MAX_STALENESS; 321 priv->conf.minStableAge = DEFAULT_MIN_STABLE_AGE; 322 | 316 priv->numBuckets = MIN_BUCKETS; 317 priv->hashMask = MIN_BUCKETS - 1; 318 priv->conf.debugLevel = 1; 319 priv->conf.loopTimeout = DEFAULT_LOOP_TIMEOUT; 320 priv->conf.maxStaleness = DEFAULT_MAX_STALENESS; 321 priv->conf.minStableAge = DEFAULT_MIN_STABLE_AGE; 322 |
323 /* 324 * This node has all kinds of stuff that could be screwed by SMP. 325 * Until it gets it's own internal protection, we go through in 326 * single file. This could hurt a machine bridging beteen two 327 * GB ethernets so it should be fixed. 328 * When it's fixed the process SHOULD NOT SLEEP, spinlocks please! 329 * (and atomic ops ) 330 */ 331 NG_NODE_FORCE_WRITER(node); 332 NG_NODE_SET_PRIVATE(node, priv); 333 priv->node = node; | 323 /* Call superclass constructor */ 324 if ((error = ng_make_node_common(&ng_bridge_typestruct, nodep))) { 325 FREE(priv, M_NETGRAPH); 326 return (error); 327 } 328 (*nodep)->private = priv; 329 priv->node = *nodep; |
334 | 330 |
335 /* Start timer; timer is always running while node is alive */ 336 ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); 337 338 /* Done */ | 331 /* Start timer by faking a timeout event */ 332 (*nodep)->refs++; 333 ng_bridge_timeout(*nodep); |
339 return (0); 340} 341 342/* 343 * Method for attaching a new hook 344 */ 345static int 346ng_bridge_newhook(node_p node, hook_p hook, const char *name) 347{ | 334 return (0); 335} 336 337/* 338 * Method for attaching a new hook 339 */ 340static int 341ng_bridge_newhook(node_p node, hook_p hook, const char *name) 342{ |
348 const priv_p priv = NG_NODE_PRIVATE(node); | 343 const priv_p priv = node->private; |
349 350 /* Check for a link hook */ 351 if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX, 352 strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) { 353 const char *cp; 354 char *eptr; 355 u_long linkNum; 356 357 cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX); 358 if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) 359 return (EINVAL); 360 linkNum = strtoul(cp, &eptr, 10); 361 if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS) 362 return (EINVAL); 363 if (priv->links[linkNum] != NULL) 364 return (EISCONN); | 344 345 /* Check for a link hook */ 346 if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX, 347 strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) { 348 const char *cp; 349 char *eptr; 350 u_long linkNum; 351 352 cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX); 353 if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) 354 return (EINVAL); 355 linkNum = strtoul(cp, &eptr, 10); 356 if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS) 357 return (EINVAL); 358 if (priv->links[linkNum] != NULL) 359 return (EISCONN); |
365 priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]), 366 M_NETGRAPH_BRIDGE, M_NOWAIT|M_ZERO); | 360 MALLOC(priv->links[linkNum], struct ng_bridge_link *, 361 sizeof(*priv->links[linkNum]), M_NETGRAPH, M_NOWAIT); |
367 if (priv->links[linkNum] == NULL) 368 return (ENOMEM); | 362 if (priv->links[linkNum] == NULL) 363 return (ENOMEM); |
364 bzero(priv->links[linkNum], sizeof(*priv->links[linkNum])); |
|
369 priv->links[linkNum]->hook = hook; | 365 priv->links[linkNum]->hook = hook; |
370 NG_HOOK_SET_PRIVATE(hook, (void *)linkNum); | 366 LINK_NUM(hook) = linkNum; |
371 priv->numLinks++; 372 return (0); 373 } 374 375 /* Unknown hook name */ 376 return (EINVAL); 377} 378 379/* 380 * Receive a control message 381 */ 382static int | 367 priv->numLinks++; 368 return (0); 369 } 370 371 /* Unknown hook name */ 372 return (EINVAL); 373} 374 375/* 376 * Receive a control message 377 */ 378static int |
383ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook) | 379ng_bridge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, 380 struct ng_mesg **rptr, hook_p lasthook) |
384{ | 381{ |
385 const priv_p priv = NG_NODE_PRIVATE(node); | 382 const priv_p priv = node->private; |
386 struct ng_mesg *resp = NULL; 387 int error = 0; | 383 struct ng_mesg *resp = NULL; 384 int error = 0; |
388 struct ng_mesg *msg; | |
389 | 385 |
390 NGI_GET_MSG(item, msg); | |
391 switch (msg->header.typecookie) { 392 case NGM_BRIDGE_COOKIE: 393 switch (msg->header.cmd) { 394 case NGM_BRIDGE_GET_CONFIG: 395 { 396 struct ng_bridge_config *conf; 397 398 NG_MKRESPONSE(resp, msg, --- 102 unchanged lines hidden (view full) --- 501 } 502 break; 503 default: 504 error = EINVAL; 505 break; 506 } 507 508 /* Done */ | 386 switch (msg->header.typecookie) { 387 case NGM_BRIDGE_COOKIE: 388 switch (msg->header.cmd) { 389 case NGM_BRIDGE_GET_CONFIG: 390 { 391 struct ng_bridge_config *conf; 392 393 NG_MKRESPONSE(resp, msg, --- 102 unchanged lines hidden (view full) --- 496 } 497 break; 498 default: 499 error = EINVAL; 500 break; 501 } 502 503 /* Done */ |
509 NG_RESPOND_MSG(error, node, item, resp); 510 NG_FREE_MSG(msg); | 504 if (rptr) 505 *rptr = resp; 506 else if (resp != NULL) 507 FREE(resp, M_NETGRAPH); 508 FREE(msg, M_NETGRAPH); |
511 return (error); 512} 513 514/* 515 * Receive data on a hook 516 */ 517static int | 509 return (error); 510} 511 512/* 513 * Receive data on a hook 514 */ 515static int |
518ng_bridge_rcvdata(hook_p hook, item_p item) | 516ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta, 517 struct mbuf **ret_m, meta_p *ret_meta) |
519{ | 518{ |
520 const node_p node = NG_HOOK_NODE(hook); 521 const priv_p priv = NG_NODE_PRIVATE(node); | 519 const node_p node = hook->node; 520 const priv_p priv = node->private; |
522 struct ng_bridge_host *host; 523 struct ng_bridge_link *link; 524 struct ether_header *eh; | 521 struct ng_bridge_host *host; 522 struct ng_bridge_link *link; 523 struct ether_header *eh; |
525 int error = 0, linkNum, linksSeen; 526 int manycast; 527 struct mbuf *m; 528 struct ng_bridge_link *firstLink; | 524 int error = 0, linkNum; 525 int i, manycast; |
529 | 526 |
530 NGI_GET_M(item, m); | |
531 /* Get link number */ | 527 /* Get link number */ |
532 linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); | 528 linkNum = LINK_NUM(hook); |
533 KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, | 529 KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, |
534 ("%s: linkNum=%u", __func__, linkNum)); | 530 ("%s: linkNum=%u", __FUNCTION__, linkNum)); |
535 link = priv->links[linkNum]; | 531 link = priv->links[linkNum]; |
536 KASSERT(link != NULL, ("%s: link%d null", __func__, linkNum)); | 532 KASSERT(link != NULL, ("%s: link%d null", __FUNCTION__, linkNum)); |
537 538 /* Sanity check packet and pull up header */ 539 if (m->m_pkthdr.len < ETHER_HDR_LEN) { 540 link->stats.recvRunts++; | 533 534 /* Sanity check packet and pull up header */ 535 if (m->m_pkthdr.len < ETHER_HDR_LEN) { 536 link->stats.recvRunts++; |
541 NG_FREE_ITEM(item); 542 NG_FREE_M(m); | 537 NG_FREE_DATA(m, meta); |
543 return (EINVAL); 544 } 545 if (m->m_len < ETHER_HDR_LEN && !(m = m_pullup(m, ETHER_HDR_LEN))) { 546 link->stats.memoryFailures++; | 538 return (EINVAL); 539 } 540 if (m->m_len < ETHER_HDR_LEN && !(m = m_pullup(m, ETHER_HDR_LEN))) { 541 link->stats.memoryFailures++; |
547 NG_FREE_ITEM(item); | 542 NG_FREE_META(meta); |
548 return (ENOBUFS); 549 } 550 eh = mtod(m, struct ether_header *); 551 if ((eh->ether_shost[0] & 1) != 0) { 552 link->stats.recvInvalid++; | 543 return (ENOBUFS); 544 } 545 eh = mtod(m, struct ether_header *); 546 if ((eh->ether_shost[0] & 1) != 0) { 547 link->stats.recvInvalid++; |
553 NG_FREE_ITEM(item); 554 NG_FREE_M(m); | 548 NG_FREE_DATA(m, meta); |
555 return (EINVAL); 556 } 557 558 /* Is link disabled due to a loopback condition? */ 559 if (link->loopCount != 0) { 560 link->stats.loopDrops++; | 549 return (EINVAL); 550 } 551 552 /* Is link disabled due to a loopback condition? */ 553 if (link->loopCount != 0) { 554 link->stats.loopDrops++; |
561 NG_FREE_ITEM(item); 562 NG_FREE_M(m); | 555 NG_FREE_DATA(m, meta); |
563 return (ELOOP); /* XXX is this an appropriate error? */ 564 } 565 566 /* Update stats */ 567 link->stats.recvPackets++; 568 link->stats.recvOctets += m->m_pkthdr.len; 569 if ((manycast = (eh->ether_dhost[0] & 1)) != 0) { 570 if (ETHER_EQUAL(eh->ether_dhost, ng_bridge_bcast_addr)) { --- 21 unchanged lines hidden (view full) --- 592 593 /* Log the problem */ 594 if (priv->conf.debugLevel >= 2) { 595 struct ifnet *ifp = m->m_pkthdr.rcvif; 596 char suffix[32]; 597 598 if (ifp != NULL) 599 snprintf(suffix, sizeof(suffix), | 556 return (ELOOP); /* XXX is this an appropriate error? */ 557 } 558 559 /* Update stats */ 560 link->stats.recvPackets++; 561 link->stats.recvOctets += m->m_pkthdr.len; 562 if ((manycast = (eh->ether_dhost[0] & 1)) != 0) { 563 if (ETHER_EQUAL(eh->ether_dhost, ng_bridge_bcast_addr)) { --- 21 unchanged lines hidden (view full) --- 585 586 /* Log the problem */ 587 if (priv->conf.debugLevel >= 2) { 588 struct ifnet *ifp = m->m_pkthdr.rcvif; 589 char suffix[32]; 590 591 if (ifp != NULL) 592 snprintf(suffix, sizeof(suffix), |
600 " (%s)", ifp->if_xname); | 593 " (%s%d)", ifp->if_name, 594 ifp->if_unit); |
601 else 602 *suffix = '\0'; 603 log(LOG_WARNING, "ng_bridge: %s:" 604 " loopback detected on %s%s\n", 605 ng_bridge_nodename(node), | 595 else 596 *suffix = '\0'; 597 log(LOG_WARNING, "ng_bridge: %s:" 598 " loopback detected on %s%s\n", 599 ng_bridge_nodename(node), |
606 NG_HOOK_NAME(hook), suffix); | 600 hook->name, suffix); |
607 } 608 609 /* Mark link as linka non grata */ 610 link->loopCount = priv->conf.loopTimeout; 611 link->stats.loopDetects++; 612 613 /* Forget all hosts on this link */ 614 ng_bridge_remove_hosts(priv, linkNum); 615 616 /* Drop packet */ 617 link->stats.loopDrops++; | 601 } 602 603 /* Mark link as linka non grata */ 604 link->loopCount = priv->conf.loopTimeout; 605 link->stats.loopDetects++; 606 607 /* Forget all hosts on this link */ 608 ng_bridge_remove_hosts(priv, linkNum); 609 610 /* Drop packet */ 611 link->stats.loopDrops++; |
618 NG_FREE_ITEM(item); 619 NG_FREE_M(m); | 612 NG_FREE_DATA(m, meta); |
620 return (ELOOP); /* XXX appropriate? */ 621 } 622 623 /* Move host over to new link */ 624 host->linkNum = linkNum; 625 host->age = 0; 626 } 627 } else { 628 if (!ng_bridge_put(priv, eh->ether_shost, linkNum)) { 629 link->stats.memoryFailures++; | 613 return (ELOOP); /* XXX appropriate? */ 614 } 615 616 /* Move host over to new link */ 617 host->linkNum = linkNum; 618 host->age = 0; 619 } 620 } else { 621 if (!ng_bridge_put(priv, eh->ether_shost, linkNum)) { 622 link->stats.memoryFailures++; |
630 NG_FREE_ITEM(item); 631 NG_FREE_M(m); | 623 NG_FREE_DATA(m, meta); |
632 return (ENOMEM); 633 } 634 } 635 636 /* Run packet through ipfw processing, if enabled */ | 624 return (ENOMEM); 625 } 626 } 627 628 /* Run packet through ipfw processing, if enabled */ |
637#if 0 638 if (priv->conf.ipfw[linkNum] && V_fw_enable && V_ip_fw_chk_ptr != NULL) { | 629 if (priv->conf.ipfw[linkNum] && fw_enable && ip_fw_chk_ptr != NULL) { |
639 /* XXX not implemented yet */ 640 } | 630 /* XXX not implemented yet */ 631 } |
641#endif | |
642 643 /* 644 * If unicast and destination host known, deliver to host's link, 645 * unless it is the same link as the packet came in on. 646 */ 647 if (!manycast) { 648 649 /* Determine packet destination link */ 650 if ((host = ng_bridge_get(priv, eh->ether_dhost)) != NULL) { 651 struct ng_bridge_link *const destLink 652 = priv->links[host->linkNum]; 653 654 /* If destination same as incoming link, do nothing */ 655 KASSERT(destLink != NULL, | 632 633 /* 634 * If unicast and destination host known, deliver to host's link, 635 * unless it is the same link as the packet came in on. 636 */ 637 if (!manycast) { 638 639 /* Determine packet destination link */ 640 if ((host = ng_bridge_get(priv, eh->ether_dhost)) != NULL) { 641 struct ng_bridge_link *const destLink 642 = priv->links[host->linkNum]; 643 644 /* If destination same as incoming link, do nothing */ 645 KASSERT(destLink != NULL, |
656 ("%s: link%d null", __func__, host->linkNum)); | 646 ("%s: link%d null", __FUNCTION__, host->linkNum)); |
657 if (destLink == link) { | 647 if (destLink == link) { |
658 NG_FREE_ITEM(item); 659 NG_FREE_M(m); | 648 NG_FREE_DATA(m, meta); |
660 return (0); 661 } 662 663 /* Deliver packet out the destination link */ 664 destLink->stats.xmitPackets++; 665 destLink->stats.xmitOctets += m->m_pkthdr.len; | 649 return (0); 650 } 651 652 /* Deliver packet out the destination link */ 653 destLink->stats.xmitPackets++; 654 destLink->stats.xmitOctets += m->m_pkthdr.len; |
666 NG_FWD_NEW_DATA(error, item, destLink->hook, m); | 655 NG_SEND_DATA(error, destLink->hook, m, meta); |
667 return (error); 668 } 669 670 /* Destination host is not known */ 671 link->stats.recvUnknown++; 672 } 673 674 /* Distribute unknown, multicast, broadcast pkts to all other links */ | 656 return (error); 657 } 658 659 /* Destination host is not known */ 660 link->stats.recvUnknown++; 661 } 662 663 /* Distribute unknown, multicast, broadcast pkts to all other links */ |
675 firstLink = NULL; 676 for (linkNum = linksSeen = 0; linksSeen <= priv->numLinks; linkNum++) { 677 struct ng_bridge_link *destLink; 678 struct mbuf *m2 = NULL; | 664 for (linkNum = i = 0; i < priv->numLinks - 1; linkNum++) { 665 struct ng_bridge_link *const destLink = priv->links[linkNum]; 666 meta_p meta2 = NULL; 667 struct mbuf *m2; |
679 | 668 |
680 /* 681 * If we have checked all the links then now 682 * send the original on its reserved link 683 */ 684 if (linksSeen == priv->numLinks) { 685 /* If we never saw a good link, leave. */ 686 if (firstLink == NULL) { 687 NG_FREE_ITEM(item); 688 NG_FREE_M(m); 689 return (0); 690 } 691 destLink = firstLink; 692 } else { 693 destLink = priv->links[linkNum]; 694 if (destLink != NULL) 695 linksSeen++; 696 /* Skip incoming link and disconnected links */ 697 if (destLink == NULL || destLink == link) { 698 continue; 699 } 700 if (firstLink == NULL) { 701 /* 702 * This is the first usable link we have found. 703 * Reserve it for the originals. 704 * If we never find another we save a copy. 705 */ 706 firstLink = destLink; 707 continue; 708 } | 669 /* Skip incoming link and disconnected links */ 670 if (destLink == NULL || destLink == link) 671 continue; |
709 | 672 |
710 /* 711 * It's usable link but not the reserved (first) one. 712 * Copy mbuf info for sending. 713 */ 714 m2 = m_dup(m, M_DONTWAIT); /* XXX m_copypacket() */ | 673 /* Copy mbuf and meta info */ 674 if (++i == priv->numLinks - 1) { /* last link */ 675 m2 = m; 676 meta2 = meta; 677 } else { 678 m2 = m_copypacket(m, M_NOWAIT); /* XXX m_dup()? */ |
715 if (m2 == NULL) { 716 link->stats.memoryFailures++; | 679 if (m2 == NULL) { 680 link->stats.memoryFailures++; |
717 NG_FREE_ITEM(item); 718 NG_FREE_M(m); | 681 NG_FREE_DATA(m, meta); |
719 return (ENOBUFS); 720 } | 682 return (ENOBUFS); 683 } |
684 if (meta != NULL 685 && (meta2 = ng_copy_meta(meta)) == NULL) { 686 link->stats.memoryFailures++; 687 m_freem(m2); 688 NG_FREE_DATA(m, meta); 689 return (ENOMEM); 690 } |
|
721 } 722 723 /* Update stats */ 724 destLink->stats.xmitPackets++; 725 destLink->stats.xmitOctets += m->m_pkthdr.len; 726 switch (manycast) { 727 case 0: /* unicast */ 728 break; 729 case 1: /* multicast */ 730 destLink->stats.xmitMulticasts++; 731 break; 732 case 2: /* broadcast */ 733 destLink->stats.xmitBroadcasts++; 734 break; 735 } 736 737 /* Send packet */ | 691 } 692 693 /* Update stats */ 694 destLink->stats.xmitPackets++; 695 destLink->stats.xmitOctets += m->m_pkthdr.len; 696 switch (manycast) { 697 case 0: /* unicast */ 698 break; 699 case 1: /* multicast */ 700 destLink->stats.xmitMulticasts++; 701 break; 702 case 2: /* broadcast */ 703 destLink->stats.xmitBroadcasts++; 704 break; 705 } 706 707 /* Send packet */ |
738 if (destLink == firstLink) { 739 /* 740 * If we've sent all the others, send the original 741 * on the first link we found. 742 */ 743 NG_FWD_NEW_DATA(error, item, destLink->hook, m); 744 break; /* always done last - not really needed. */ 745 } else { 746 NG_SEND_DATA_ONLY(error, destLink->hook, m2); 747 } | 708 NG_SEND_DATA(error, destLink->hook, m2, meta2); |
748 } 749 return (error); 750} 751 752/* 753 * Shutdown node 754 */ 755static int | 709 } 710 return (error); 711} 712 713/* 714 * Shutdown node 715 */ 716static int |
756ng_bridge_shutdown(node_p node) | 717ng_bridge_rmnode(node_p node) |
757{ | 718{ |
758 const priv_p priv = NG_NODE_PRIVATE(node); | 719 const priv_p priv = node->private; |
759 | 720 |
760 /* 761 * Shut down everything including the timer. Even if the 762 * callout has already been dequeued and is about to be 763 * run, ng_bridge_timeout() won't be fired as the node 764 * is already marked NGF_INVALID, so we're safe to free 765 * the node now. 766 */ | 721 ng_unname(node); 722 ng_cutlinks(node); /* frees all link and host info */ |
767 KASSERT(priv->numLinks == 0 && priv->numHosts == 0, 768 ("%s: numLinks=%d numHosts=%d", | 723 KASSERT(priv->numLinks == 0 && priv->numHosts == 0, 724 ("%s: numLinks=%d numHosts=%d", |
769 __func__, priv->numLinks, priv->numHosts)); 770 ng_uncallout(&priv->timer, node); 771 NG_NODE_SET_PRIVATE(node, NULL); 772 NG_NODE_UNREF(node); 773 free(priv->tab, M_NETGRAPH_BRIDGE); 774 free(priv, M_NETGRAPH_BRIDGE); | 725 __FUNCTION__, priv->numLinks, priv->numHosts)); 726 FREE(priv->tab, M_NETGRAPH); 727 FREE(priv, M_NETGRAPH); 728 node->private = NULL; 729 ng_unref(node); |
775 return (0); 776} 777 778/* 779 * Hook disconnection. 780 */ 781static int 782ng_bridge_disconnect(hook_p hook) 783{ | 730 return (0); 731} 732 733/* 734 * Hook disconnection. 735 */ 736static int 737ng_bridge_disconnect(hook_p hook) 738{ |
784 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); | 739 const priv_p priv = hook->node->private; |
785 int linkNum; 786 787 /* Get link number */ | 740 int linkNum; 741 742 /* Get link number */ |
788 linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); | 743 linkNum = LINK_NUM(hook); |
789 KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, | 744 KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, |
790 ("%s: linkNum=%u", __func__, linkNum)); | 745 ("%s: linkNum=%u", __FUNCTION__, linkNum)); |
791 792 /* Remove all hosts associated with this link */ 793 ng_bridge_remove_hosts(priv, linkNum); 794 795 /* Free associated link information */ | 746 747 /* Remove all hosts associated with this link */ 748 ng_bridge_remove_hosts(priv, linkNum); 749 750 /* Free associated link information */ |
796 KASSERT(priv->links[linkNum] != NULL, ("%s: no link", __func__)); 797 free(priv->links[linkNum], M_NETGRAPH_BRIDGE); | 751 KASSERT(priv->links[linkNum] != NULL, ("%s: no link", __FUNCTION__)); 752 FREE(priv->links[linkNum], M_NETGRAPH); |
798 priv->links[linkNum] = NULL; 799 priv->numLinks--; 800 801 /* If no more hooks, go away */ | 753 priv->links[linkNum] = NULL; 754 priv->numLinks--; 755 756 /* If no more hooks, go away */ |
802 if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 803 && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 804 ng_rmnode_self(NG_HOOK_NODE(hook)); 805 } | 757 if (hook->node->numhooks == 0) 758 ng_rmnode(hook->node); |
806 return (0); 807} 808 809/****************************************************************** 810 HASH TABLE FUNCTIONS 811******************************************************************/ 812 813/* 814 * Hash algorithm | 759 return (0); 760} 761 762/****************************************************************** 763 HASH TABLE FUNCTIONS 764******************************************************************/ 765 766/* 767 * Hash algorithm |
768 * 769 * Only hashing bytes 3-6 of the Ethernet address is sufficient and fast. |
|
815 */ 816#define HASH(addr,mask) ( (((const u_int16_t *)(addr))[0] \ 817 ^ ((const u_int16_t *)(addr))[1] \ 818 ^ ((const u_int16_t *)(addr))[2]) & (mask) ) 819 820/* 821 * Find a host entry in the table. 822 */ --- 20 unchanged lines hidden (view full) --- 843{ 844 const int bucket = HASH(addr, priv->hashMask); 845 struct ng_bridge_hent *hent; 846 847#ifdef INVARIANTS 848 /* Assert that entry does not already exist in hashtable */ 849 SLIST_FOREACH(hent, &priv->tab[bucket], next) { 850 KASSERT(!ETHER_EQUAL(hent->host.addr, addr), | 770 */ 771#define HASH(addr,mask) ( (((const u_int16_t *)(addr))[0] \ 772 ^ ((const u_int16_t *)(addr))[1] \ 773 ^ ((const u_int16_t *)(addr))[2]) & (mask) ) 774 775/* 776 * Find a host entry in the table. 777 */ --- 20 unchanged lines hidden (view full) --- 798{ 799 const int bucket = HASH(addr, priv->hashMask); 800 struct ng_bridge_hent *hent; 801 802#ifdef INVARIANTS 803 /* Assert that entry does not already exist in hashtable */ 804 SLIST_FOREACH(hent, &priv->tab[bucket], next) { 805 KASSERT(!ETHER_EQUAL(hent->host.addr, addr), |
851 ("%s: entry %6D exists in table", __func__, addr, ":")); | 806 ("%s: entry %6D exists in table", __FUNCTION__, addr, ":")); |
852 } 853#endif 854 855 /* Allocate and initialize new hashtable entry */ | 807 } 808#endif 809 810 /* Allocate and initialize new hashtable entry */ |
856 hent = malloc(sizeof(*hent), M_NETGRAPH_BRIDGE, M_NOWAIT); | 811 MALLOC(hent, struct ng_bridge_hent *, 812 sizeof(*hent), M_NETGRAPH, M_NOWAIT); |
857 if (hent == NULL) 858 return (0); 859 bcopy(addr, hent->host.addr, ETHER_ADDR_LEN); 860 hent->host.linkNum = linkNum; 861 hent->host.staleness = 0; 862 hent->host.age = 0; 863 864 /* Add new element to hash bucket */ --- 27 unchanged lines hidden (view full) --- 892 else if (priv->numHosts < (priv->numBuckets >> 2) 893 && (priv->numBuckets >> 2) >= MIN_BUCKETS) 894 newNumBuckets = priv->numBuckets >> 2; 895 else 896 return; 897 newMask = newNumBuckets - 1; 898 899 /* Allocate and initialize new table */ | 813 if (hent == NULL) 814 return (0); 815 bcopy(addr, hent->host.addr, ETHER_ADDR_LEN); 816 hent->host.linkNum = linkNum; 817 hent->host.staleness = 0; 818 hent->host.age = 0; 819 820 /* Add new element to hash bucket */ --- 27 unchanged lines hidden (view full) --- 848 else if (priv->numHosts < (priv->numBuckets >> 2) 849 && (priv->numBuckets >> 2) >= MIN_BUCKETS) 850 newNumBuckets = priv->numBuckets >> 2; 851 else 852 return; 853 newMask = newNumBuckets - 1; 854 855 /* Allocate and initialize new table */ |
900 newTab = malloc(newNumBuckets * sizeof(*newTab), 901 M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO); | 856 MALLOC(newTab, struct ng_bridge_bucket *, 857 newNumBuckets * sizeof(*newTab), M_NETGRAPH, M_NOWAIT); |
902 if (newTab == NULL) 903 return; | 858 if (newTab == NULL) 859 return; |
860 bzero(newTab, newNumBuckets * sizeof(*newTab)); |
|
904 905 /* Move all entries from old table to new table */ 906 for (oldBucket = 0; oldBucket < priv->numBuckets; oldBucket++) { 907 struct ng_bridge_bucket *const oldList = &priv->tab[oldBucket]; 908 909 while (!SLIST_EMPTY(oldList)) { 910 struct ng_bridge_hent *const hent 911 = SLIST_FIRST(oldList); --- 5 unchanged lines hidden (view full) --- 917 } 918 919 /* Replace old table with new one */ 920 if (priv->conf.debugLevel >= 3) { 921 log(LOG_INFO, "ng_bridge: %s: table size %d -> %d\n", 922 ng_bridge_nodename(priv->node), 923 priv->numBuckets, newNumBuckets); 924 } | 861 862 /* Move all entries from old table to new table */ 863 for (oldBucket = 0; oldBucket < priv->numBuckets; oldBucket++) { 864 struct ng_bridge_bucket *const oldList = &priv->tab[oldBucket]; 865 866 while (!SLIST_EMPTY(oldList)) { 867 struct ng_bridge_hent *const hent 868 = SLIST_FIRST(oldList); --- 5 unchanged lines hidden (view full) --- 874 } 875 876 /* Replace old table with new one */ 877 if (priv->conf.debugLevel >= 3) { 878 log(LOG_INFO, "ng_bridge: %s: table size %d -> %d\n", 879 ng_bridge_nodename(priv->node), 880 priv->numBuckets, newNumBuckets); 881 } |
925 free(priv->tab, M_NETGRAPH_BRIDGE); | 882 FREE(priv->tab, M_NETGRAPH); |
926 priv->numBuckets = newNumBuckets; 927 priv->hashMask = newMask; 928 priv->tab = newTab; 929 return; 930} 931 932/****************************************************************** 933 MISC FUNCTIONS --- 11 unchanged lines hidden (view full) --- 945 for (bucket = 0; bucket < priv->numBuckets; bucket++) { 946 struct ng_bridge_hent **hptr = &SLIST_FIRST(&priv->tab[bucket]); 947 948 while (*hptr != NULL) { 949 struct ng_bridge_hent *const hent = *hptr; 950 951 if (linkNum == -1 || hent->host.linkNum == linkNum) { 952 *hptr = SLIST_NEXT(hent, next); | 883 priv->numBuckets = newNumBuckets; 884 priv->hashMask = newMask; 885 priv->tab = newTab; 886 return; 887} 888 889/****************************************************************** 890 MISC FUNCTIONS --- 11 unchanged lines hidden (view full) --- 902 for (bucket = 0; bucket < priv->numBuckets; bucket++) { 903 struct ng_bridge_hent **hptr = &SLIST_FIRST(&priv->tab[bucket]); 904 905 while (*hptr != NULL) { 906 struct ng_bridge_hent *const hent = *hptr; 907 908 if (linkNum == -1 || hent->host.linkNum == linkNum) { 909 *hptr = SLIST_NEXT(hent, next); |
953 free(hent, M_NETGRAPH_BRIDGE); | 910 FREE(hent, M_NETGRAPH); |
954 priv->numHosts--; 955 } else 956 hptr = &SLIST_NEXT(hent, next); 957 } 958 } 959} 960 961/* 962 * Handle our once-per-second timeout event. We do two things: 963 * we decrement link->loopCount for those links being muted due to 964 * a detected loopback condition, and we remove any hosts from 965 * the hashtable whom we haven't heard from in a long while. 966 */ 967static void | 911 priv->numHosts--; 912 } else 913 hptr = &SLIST_NEXT(hent, next); 914 } 915 } 916} 917 918/* 919 * Handle our once-per-second timeout event. We do two things: 920 * we decrement link->loopCount for those links being muted due to 921 * a detected loopback condition, and we remove any hosts from 922 * the hashtable whom we haven't heard from in a long while. 923 */ 924static void |
968ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2) | 925ng_bridge_timeout(void *arg) |
969{ | 926{ |
970 const priv_p priv = NG_NODE_PRIVATE(node); 971 int bucket; | 927 const node_p node = arg; 928 const priv_p priv = node->private; 929 int s, bucket; |
972 int counter = 0; 973 int linkNum; 974 | 930 int counter = 0; 931 int linkNum; 932 |
933 /* Avoid race condition with ng_bridge_shutdown() */ 934 s = splnet(); 935 if ((node->flags & NG_INVALID) != 0 || priv == NULL) { 936 ng_unref(node); 937 splx(s); 938 return; 939 } 940 941 /* Register a new timeout, keeping the existing node reference */ 942 callout_reset(&priv->timer, hz, ng_bridge_timeout, node); 943 |
|
975 /* Update host time counters and remove stale entries */ 976 for (bucket = 0; bucket < priv->numBuckets; bucket++) { 977 struct ng_bridge_hent **hptr = &SLIST_FIRST(&priv->tab[bucket]); 978 979 while (*hptr != NULL) { 980 struct ng_bridge_hent *const hent = *hptr; 981 982 /* Make sure host's link really exists */ 983 KASSERT(priv->links[hent->host.linkNum] != NULL, 984 ("%s: host %6D on nonexistent link %d\n", | 944 /* Update host time counters and remove stale entries */ 945 for (bucket = 0; bucket < priv->numBuckets; bucket++) { 946 struct ng_bridge_hent **hptr = &SLIST_FIRST(&priv->tab[bucket]); 947 948 while (*hptr != NULL) { 949 struct ng_bridge_hent *const hent = *hptr; 950 951 /* Make sure host's link really exists */ 952 KASSERT(priv->links[hent->host.linkNum] != NULL, 953 ("%s: host %6D on nonexistent link %d\n", |
985 __func__, hent->host.addr, ":", | 954 __FUNCTION__, hent->host.addr, ":", |
986 hent->host.linkNum)); 987 988 /* Remove hosts we haven't heard from in a while */ 989 if (++hent->host.staleness >= priv->conf.maxStaleness) { 990 *hptr = SLIST_NEXT(hent, next); | 955 hent->host.linkNum)); 956 957 /* Remove hosts we haven't heard from in a while */ 958 if (++hent->host.staleness >= priv->conf.maxStaleness) { 959 *hptr = SLIST_NEXT(hent, next); |
991 free(hent, M_NETGRAPH_BRIDGE); | 960 FREE(hent, M_NETGRAPH); |
992 priv->numHosts--; 993 } else { 994 if (hent->host.age < 0xffff) 995 hent->host.age++; 996 hptr = &SLIST_NEXT(hent, next); 997 counter++; 998 } 999 } 1000 } 1001 KASSERT(priv->numHosts == counter, | 961 priv->numHosts--; 962 } else { 963 if (hent->host.age < 0xffff) 964 hent->host.age++; 965 hptr = &SLIST_NEXT(hent, next); 966 counter++; 967 } 968 } 969 } 970 KASSERT(priv->numHosts == counter, |
1002 ("%s: hosts: %d != %d", __func__, priv->numHosts, counter)); | 971 ("%s: hosts: %d != %d", __FUNCTION__, priv->numHosts, counter)); |
1003 1004 /* Decrease table size if necessary */ 1005 ng_bridge_rehash(priv); 1006 1007 /* Decrease loop counter on muted looped back links */ 1008 for (counter = linkNum = 0; linkNum < NG_BRIDGE_MAX_LINKS; linkNum++) { 1009 struct ng_bridge_link *const link = priv->links[linkNum]; 1010 --- 6 unchanged lines hidden (view full) --- 1017 " restoring looped back link%d\n", 1018 ng_bridge_nodename(node), linkNum); 1019 } 1020 } 1021 counter++; 1022 } 1023 } 1024 KASSERT(priv->numLinks == counter, | 972 973 /* Decrease table size if necessary */ 974 ng_bridge_rehash(priv); 975 976 /* Decrease loop counter on muted looped back links */ 977 for (counter = linkNum = 0; linkNum < NG_BRIDGE_MAX_LINKS; linkNum++) { 978 struct ng_bridge_link *const link = priv->links[linkNum]; 979 --- 6 unchanged lines hidden (view full) --- 986 " restoring looped back link%d\n", 987 ng_bridge_nodename(node), linkNum); 988 } 989 } 990 counter++; 991 } 992 } 993 KASSERT(priv->numLinks == counter, |
1025 ("%s: links: %d != %d", __func__, priv->numLinks, counter)); | 994 ("%s: links: %d != %d", __FUNCTION__, priv->numLinks, counter)); |
1026 | 995 |
1027 /* Register a new timeout, keeping the existing node reference */ 1028 ng_callout(&priv->timer, node, NULL, hz, ng_bridge_timeout, NULL, 0); | 996 /* Done */ 997 splx(s); |
1029} 1030 1031/* 1032 * Return node's "name", even if it doesn't have one. 1033 */ 1034static const char * 1035ng_bridge_nodename(node_p node) 1036{ | 998} 999 1000/* 1001 * Return node's "name", even if it doesn't have one. 1002 */ 1003static const char * 1004ng_bridge_nodename(node_p node) 1005{ |
1037 static char name[NG_NODESIZ]; | 1006 static char name[NG_NODELEN+1]; |
1038 | 1007 |
1039 if (NG_NODE_NAME(node) != NULL) 1040 snprintf(name, sizeof(name), "%s", NG_NODE_NAME(node)); | 1008 if (node->name != NULL) 1009 snprintf(name, sizeof(name), "%s", node->name); |
1041 else 1042 snprintf(name, sizeof(name), "[%x]", ng_node2ID(node)); 1043 return name; 1044} 1045 | 1010 else 1011 snprintf(name, sizeof(name), "[%x]", ng_node2ID(node)); 1012 return name; 1013} 1014 |