Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_bridge.c
Show First 20 Lines • Show All 228 Lines • ▼ Show 20 Lines | |||||
/* Parse type for struct ng_bridge_link_stat */ | /* Parse type for struct ng_bridge_link_stat */ | ||||
static const struct ng_parse_struct_field ng_bridge_stats_type_fields[] | static const struct ng_parse_struct_field ng_bridge_stats_type_fields[] | ||||
= NG_BRIDGE_STATS_TYPE_INFO; | = NG_BRIDGE_STATS_TYPE_INFO; | ||||
static const struct ng_parse_type ng_bridge_stats_type = { | static const struct ng_parse_type ng_bridge_stats_type = { | ||||
&ng_parse_struct_type, | &ng_parse_struct_type, | ||||
&ng_bridge_stats_type_fields | &ng_bridge_stats_type_fields | ||||
}; | }; | ||||
/* Parse type for struct ng_bridge_move_host */ | |||||
static const struct ng_parse_struct_field ng_bridge_move_host_type_fields[] | |||||
= NG_BRIDGE_MOVE_HOST_TYPE_INFO(&ng_parse_enaddr_type); | |||||
static const struct ng_parse_type ng_bridge_move_host_type = { | |||||
&ng_parse_struct_type, | |||||
&ng_bridge_move_host_type_fields | |||||
}; | |||||
/* List of commands and how to convert arguments to/from ASCII */ | /* List of commands and how to convert arguments to/from ASCII */ | ||||
static const struct ng_cmdlist ng_bridge_cmdlist[] = { | static const struct ng_cmdlist ng_bridge_cmdlist[] = { | ||||
{ | { | ||||
NGM_BRIDGE_COOKIE, | NGM_BRIDGE_COOKIE, | ||||
NGM_BRIDGE_SET_CONFIG, | NGM_BRIDGE_SET_CONFIG, | ||||
"setconfig", | "setconfig", | ||||
&ng_bridge_config_type, | &ng_bridge_config_type, | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | static const struct ng_cmdlist ng_bridge_cmdlist[] = { | ||||
}, | }, | ||||
{ | { | ||||
NGM_BRIDGE_COOKIE, | NGM_BRIDGE_COOKIE, | ||||
NGM_BRIDGE_SET_PERSISTENT, | NGM_BRIDGE_SET_PERSISTENT, | ||||
"setpersistent", | "setpersistent", | ||||
NULL, | NULL, | ||||
NULL | NULL | ||||
}, | }, | ||||
{ | |||||
NGM_BRIDGE_COOKIE, | |||||
NGM_BRIDGE_MOVE_HOST, | |||||
"movehost", | |||||
&ng_bridge_move_host_type, | |||||
NULL | |||||
}, | |||||
{ 0 } | { 0 } | ||||
}; | }; | ||||
/* Node type descriptor */ | /* Node type descriptor */ | ||||
static struct ng_type ng_bridge_typestruct = { | static struct ng_type ng_bridge_typestruct = { | ||||
.version = NG_ABI_VERSION, | .version = NG_ABI_VERSION, | ||||
.name = NG_BRIDGE_NODE_TYPE, | .name = NG_BRIDGE_NODE_TYPE, | ||||
.constructor = ng_bridge_constructor, | .constructor = ng_bridge_constructor, | ||||
▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | case NGM_BRIDGE_GET_TABLE: | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
case NGM_BRIDGE_SET_PERSISTENT: | case NGM_BRIDGE_SET_PERSISTENT: | ||||
{ | { | ||||
priv->persistent = 1; | priv->persistent = 1; | ||||
break; | break; | ||||
} | } | ||||
case NGM_BRIDGE_MOVE_HOST: | |||||
{ | |||||
struct ng_bridge_move_host *mh; | |||||
hook_p hook; | |||||
struct ng_bridge_host *host; | |||||
if (msg->header.arglen < sizeof(*mh)) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
mh = (struct ng_bridge_move_host *)msg->data; | |||||
hook = (mh->hook[0] == 0) | |||||
? lasthook | |||||
: ng_findhook(node, mh->hook); | |||||
if (hook == NULL) { | |||||
error = ENOENT; | |||||
break; | |||||
} | |||||
host = ng_bridge_get(priv, mh->addr); | |||||
if (host != NULL) { | |||||
error = EADDRINUSE; | |||||
break; | |||||
} | |||||
error = ng_bridge_put(priv, mh->addr, NG_HOOK_PRIVATE(hook)); | |||||
break; | |||||
} | |||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | if (host->link != ctx.incoming) { | ||||
return (ELOOP); /* XXX appropriate? */ | return (ELOOP); /* XXX appropriate? */ | ||||
} | } | ||||
/* Move host over to new link */ | /* Move host over to new link */ | ||||
host->link = ctx.incoming; | host->link = ctx.incoming; | ||||
host->age = 0; | host->age = 0; | ||||
} | } | ||||
} else if (ctx.incoming->learnMac) { | } else if (ctx.incoming->learnMac) { | ||||
if (!ng_bridge_put(priv, eh->ether_shost, ctx.incoming)) { | struct ng_mesg *msg; | ||||
struct ng_bridge_move_host *mh; | |||||
int error = 0; | |||||
NG_MKMESSAGE(msg, NGM_BRIDGE_COOKIE, NGM_BRIDGE_MOVE_HOST, | |||||
sizeof(*mh), M_NOWAIT); | |||||
if (msg == NULL) { | |||||
counter_u64_add(ctx.incoming->stats.memoryFailures, 1); | counter_u64_add(ctx.incoming->stats.memoryFailures, 1); | ||||
NG_FREE_ITEM(item); | NG_FREE_ITEM(item); | ||||
NG_FREE_M(ctx.m); | NG_FREE_M(ctx.m); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
mh = (struct ng_bridge_move_host *)msg->data; | |||||
strncpy(mh->hook, NG_HOOK_NAME(ctx.incoming->hook), | |||||
sizeof(mh->hook)); | |||||
memcpy(mh->addr, eh->ether_shost, sizeof(mh->addr)); | |||||
NG_SEND_MSG_ID(error, node, msg, NG_NODE_ID(node), | |||||
NG_NODE_ID(node)); | |||||
if (error) | |||||
counter_u64_add(ctx.incoming->stats.memoryFailures, 1); | |||||
} | } | ||||
/* Run packet through ipfw processing, if enabled */ | /* Run packet through ipfw processing, if enabled */ | ||||
#if 0 | #if 0 | ||||
if (priv->conf.ipfw[linkNum] && V_fw_enable && V_ip_fw_chk_ptr != NULL) { | if (priv->conf.ipfw[linkNum] && V_fw_enable && V_ip_fw_chk_ptr != NULL) { | ||||
/* XXX not implemented yet */ | /* XXX not implemented yet */ | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | SLIST_FOREACH(host, &priv->tab[bucket], next) { | ||||
if (ETHER_EQUAL(host->addr, addr)) | if (ETHER_EQUAL(host->addr, addr)) | ||||
return (host); | return (host); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Add a new host entry to the table. This assumes the host doesn't | * Add a new host entry to the table. This assumes the host doesn't | ||||
* already exist in the table. Returns 1 on success, 0 if there | * already exist in the table. Returns 0 on success. | ||||
* was a memory allocation failure. | |||||
*/ | */ | ||||
static int | static int | ||||
ng_bridge_put(priv_p priv, const u_char *addr, link_p link) | ng_bridge_put(priv_p priv, const u_char *addr, link_p link) | ||||
{ | { | ||||
const int bucket = HASH(addr, priv->hashMask); | const int bucket = HASH(addr, priv->hashMask); | ||||
struct ng_bridge_host *host; | struct ng_bridge_host *host; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
/* Assert that entry does not already exist in hashtable */ | /* Assert that entry does not already exist in hashtable */ | ||||
SLIST_FOREACH(host, &priv->tab[bucket], next) { | KASSERT(ng_bridge_get(priv, addr) == NULL, | ||||
KASSERT(!ETHER_EQUAL(host->addr, addr), | |||||
("%s: entry %6D exists in table", __func__, addr, ":")); | ("%s: entry %6D exists in table", __func__, addr, ":")); | ||||
} | |||||
donner: Avoid code duplication. | |||||
#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 (ENOMEM); | ||||
bcopy(addr, host->addr, ETHER_ADDR_LEN); | bcopy(addr, host->addr, ETHER_ADDR_LEN); | ||||
host->link = link; | host->link = link; | ||||
host->staleness = 0; | host->staleness = 0; | ||||
host->age = 0; | host->age = 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 (0); | ||||
} | } | ||||
/* | /* | ||||
* Resize the hash table. We try to maintain the number of buckets | * Resize the hash table. We try to maintain the number of buckets | ||||
* such that the load factor is in the range 0.25 to 1.0. | * such that the load factor is in the range 0.25 to 1.0. | ||||
* | * | ||||
* If we can't get the new memory then we silently fail. This is OK | * If we can't get the new memory then we silently fail. This is OK | ||||
* because things will still work and we'll try again soon anyway. | * because things will still work and we'll try again soon anyway. | ||||
▲ Show 20 Lines • Show All 166 Lines • Show Last 20 Lines |
Avoid code duplication.