netgraph/ng_bridge: Derive forwarding mode from first attached hook

Handling of unknown MACs on an bridge with incomplete learning
capabilites (aka uplink ports) can be defined in different ways.

The classical approach is to broadcast unicast frames send to an
unknown MAC, because the unknown devices can be everywhere. This mode
is default for ng_bridge(4).

In the case of dedicated uplink ports, which prohibit learning of MAC
addresses in order to save memory and CPU cycles, the broadcast
approach is dangerous. All traffic to the uplink port is broadcasted
to every downlink port, too. In this case, it's better to restrict the
distribution of frames to unknown MAC to the uplink ports only.

In order to keep the chance small and the handling as natural as
possible, the first attached link is used to determine the behaviour
of the bridge: If it is an "uplink" port, then the bridge switch from
classical mode to restricted mode.

Reviewed By:	kp
Approved by:	kp (mentor)
MFC after:	2 weeks
Differential Revision: https://reviews.freebsd.org/D28487
This commit is contained in:
Lutz Donnerhacke 2021-02-06 11:25:04 +01:00
parent 689561d403
commit c869d905ba
2 changed files with 22 additions and 2 deletions

View file

@ -109,6 +109,22 @@ hook of the bridge, and ignore the complexity of the outside world.
Frames with unknown MACs are always sent out to
.Ar uplink
hooks, so no functionality is lost.
.Pp
Frames with unknown destination MAC addresses are replicated to any
available hook, unless the first connected hook is an
.Ar uplink
hook.
In this case the node assumes, that all unknown MAC addresses are
located soley on the
.Ar uplink
hooks and only those hooks will be used to send out frames with
unknown destination MACs.
If the first connected hook is an
.Ar link
hook, the node will replicate such frames to all types of hooks,
even if
.Ar uplink
hooks are connected later.
.Sh CONTROL MESSAGES
This node type supports the generic control messages, plus the
following:

View file

@ -105,7 +105,8 @@ struct ng_bridge_private {
u_int numBuckets; /* num buckets in table */
u_int hashMask; /* numBuckets - 1 */
int numLinks; /* num connected links */
int persistent; /* can exist w/o hooks */
unsigned int persistent : 1, /* can exist w/o hooks */
sendUnknown : 1;/* links receive unknowns by default */
struct callout timer; /* one second periodic timer */
};
typedef struct ng_bridge_private *priv_p;
@ -309,6 +310,7 @@ ng_bridge_constructor(node_p node)
priv->conf.loopTimeout = DEFAULT_LOOP_TIMEOUT;
priv->conf.maxStaleness = DEFAULT_MAX_STALENESS;
priv->conf.minStableAge = DEFAULT_MIN_STABLE_AGE;
priv->sendUnknown = 1; /* classic bridge */
/*
* This node has all kinds of stuff that could be screwed by SMP.
@ -371,9 +373,11 @@ ng_bridge_newhook(node_p node, hook_p hook, const char *name)
if (isUplink) {
link->learnMac = 0;
link->sendUnknown = 1;
if (priv->numLinks == 0) /* if the first link is an uplink */
priv->sendUnknown = 0; /* switch to restrictive mode */
} else {
link->learnMac = 1;
link->sendUnknown = 1;
link->sendUnknown = priv->sendUnknown;
}
NG_HOOK_SET_PRIVATE(hook, link);