View | Details | Raw Unified | Return to bug 278130
Collapse All | Expand All

(-)b/share/man/man4/ng_bridge.4 (+7 lines)
Lines 108-113 Frames with unknown MACs are always sent out to Link Here
108
.Ar uplink
108
.Ar uplink
109
hooks, so no functionality is lost.
109
hooks, so no functionality is lost.
110
.Pp
110
.Pp
111
To have the bridge assign an [up]link number for you, simply name your
112
hook
113
.Ar link
114
or
115
.Ar uplink
116
and omit giving it a number.
117
.Pp
111
Frames with unknown destination MAC addresses are replicated to any
118
Frames with unknown destination MAC addresses are replicated to any
112
available hook, unless the first connected hook is an
119
available hook, unless the first connected hook is an
113
.Ar uplink
120
.Ar uplink
(-)b/sys/netgraph/ng_bridge.c (-24 / +76 lines)
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
- 

Return to bug 278130