Ethernet Bridge
The Ethernet bridge joins several Ethernet (or IEEE 802.11) network devices into one layer 2 network, like a simple learning switch. It follows the IEEE 802.1D transparent bridge model without the spanning tree protocol.
A bridge is a virtual network device, br0 for example. Real devices are
added to it as ports. Frames received on a port are forwarded to the other
ports, and frames for the local host are passed to the network stack through
the bridge device. The IP configuration belongs to the bridge device: the
ports normally have no IP address.
IP stack (sockets, DHCP server, ...)
|
[ br0 ] <- IP address, MAC address
/ \
[ eth0 ] [ wlan0 ] <- ports, no IP address
| |
wired LAN Wi-Fi clients
Configuration Options
CONFIG_NET_BRIDGEEnable bridge support. Requires
CONFIG_NET_ETHERNET.CONFIG_NET_BRIDGE_MAX_PORTSMaximum number of ports per bridge (default 4).
CONFIG_NET_BRIDGE_FDB_SIZENumber of MAC addresses that each bridge can learn (default 32). When the table is full, the least recently seen address is replaced.
CONFIG_NET_BRIDGE_AGEING_TIMESeconds after which an address that sent no frame is forgotten (default 300).
Usage
Bridges are configured with the Linux bridge ioctl commands, which the
brctl command (CONFIG_SYSTEM_BRCTL) wraps:
SIOCBRADDBRCreate a bridge. The argument is the name of the new device.
SIOCBRDELBRDelete a bridge. The bridge must be down.
SIOCBRADDIF/SIOCBRDELIFAdd a port to a bridge or remove it. The argument is a
struct ifreqwith the bridge name inifr_nameand the interface index of the port inifr_ifindex.
Example from NSH:
nsh> ifup eth0
nsh> ifup eth1
nsh> brctl addbr br0
nsh> brctl addif br0 eth0
nsh> brctl addif br0 eth1
nsh> ifconfig br0 10.0.0.2 netmask 255.255.255.0
nsh> ifup br0
The bridge takes the MAC address of its first port, unless one was set before. Its MTU is the smallest MTU of its ports.
Forwarding
The source address of every received frame is learned in the filtering database (FDB) of the bridge, together with the receiving port.
Unicast frames for the address of the bridge or of one of its ports go to the local host.
Unicast frames for a learned address are sent on the port of that address, or dropped if that is the receiving port.
Unicast frames for an unknown address are sent on all other ports (flooding).
Broadcast and multicast frames go to the local host and to all other ports, except the IEEE 802.1D reserved addresses
01:80:C2:00:00:00to01:80:C2:00:00:0F, which only go to the local host.Frames sent by the local host through the bridge device are forwarded the same way.
Packet sockets bound to a port see every frame received on it. Packet sockets bound to the bridge device see the frames for the local host and the frames it sends.
Limitations
There is no spanning tree protocol. The network must not contain loops through the bridge, or broadcast frames will circulate forever.
Only devices that use the upper-half driver interface (
include/nuttx/net/netdev_lowerhalf.h) can be ports. Adding another device fails withEOPNOTSUPP.To forward unicast frames, a port must receive frames for foreign MAC addresses: Ethernet devices need
CONFIG_NET_PROMISCUOUS(if their driver supports it), and IEEE 802.11 devices must be in access point mode, since a station cannot send frames with foreign source addresses.There is no VLAN filtering: tagged frames are forwarded unchanged.
A frame for a port that has no room is dropped, as there is no queue between the bridge and the ports. Frames sent by the local host through the bridge device are not dropped for that reason: the network stack waits until the ports have room.
Implementation
The code is in drivers/net/bridge.c. The bridge device is a network
device of the upper-half driver interface, like a VLAN device, and the ports
are ordinary upper-half devices:
Receive: the upper half of a port gives every received frame to the bridge instead of the network stack. The bridge learns the source address, sends the frame to the other ports with the
transmitoperation of the port, and passes it to the network stack withnetdev_lower_input()when the frame is for the local host.Transmit: the
transmitoperation of the bridge device forwards a frame sent by the local host in the same way. The TX quota of the bridge device is the room of its ports with the least room, so the network stack only polls the bridge device when the ports can take a frame, and polls again when a port reports a completed transmission.Locking: the bridge lock serializes the filtering database and the transmission to the ports, and it is never held while a network device lock is taken, so the receive path of a port, which holds the port lock, can forward to another port without a lock order inversion.
Testing on the Simulator
The sim:bridge configuration has two TAP devices, eth0 and eth1.
On the Linux host, put each TAP device in its own network namespace (as
root), then bridge them in NuttX as shown above:
# ip netns add bra
# ip link set tap0 netns bra
# ip -n bra addr add 10.0.0.1/24 dev tap0
# ip -n bra link set tap0 up
# ip netns add brb
# ip link set tap1 netns brb
# ip -n brb addr add 10.0.0.3/24 dev tap1
# ip -n brb link set tap1 up
# ip netns exec bra ping 10.0.0.3
The nuttx program must run as root (or with CAP_NET_ADMIN) to create
the TAP devices.