FreeBSD Ethernet Bridges: Layer-2 Forwarding, STP, and Operations
Operate FreeBSD if_bridge with deliberate member roles, correct host addressing, spanning-tree checks, forwarding-table visibility, and safe change tests.
FreeBSD’s if_bridge(4) creates a software Ethernet bridge: a logical Layer-2 forwarding device that learns source MAC addresses and forwards frames between member interfaces. A bridge is not a router, firewall, or guarantee of redundant connectivity. A loop, mismatched spanning-tree design, address placed on the wrong interface, or attached port with unexpected traffic can disrupt every segment connected to it.
Bridges appear in several FreeBSD configurations, including virtual-machine hosts and VNET jails. Those systems add their own tap or epair lifecycle and are covered in their respective guides. This article concentrates on the bridge itself: membership, host addressing, STP, forwarding behavior, monitoring, and a reversible operational test.
Define what the bridge should connect
Begin with an explicit Layer-2 diagram. List every physical NIC and cloned interface, the switch port on each NIC, VLAN membership, guest or jail attachment, and the host’s management path. Decide whether the FreeBSD system is bridging a transparent segment, presenting a host address on that segment, or connecting virtual interfaces to an upstream LAN. Those are different roles, and the correct interface layout depends on the answer.
Confirm interface identities from MAC address, driver, and link state rather than guessing from device names. A bridge can combine interfaces only when their framing is compatible. Ethernet and a compatible Ethernet-like link may bridge; a bridge is not a generic way to join unrelated link technologies. Check the if_bridge(4) and member-driver manuals before relying on offloads, VLAN tags, or unusual media.
ifconfig -a
ifconfig -m igb0
ifconfig igb0
netstat -rn
Capture a baseline of addresses, routes, switch port settings, link counters, and remote management reachability. A change that removes the host’s IP from a member can terminate a remote session. Use a local console or out-of-band management, keep the old route documented, and plan how to detach the bridge if the test fails.
Create a bridge and add members
The runtime sequence is straightforward, but the topology is not implicit. Create the cloned bridge, attach the intended members, bring the ports and bridge up, and then verify the forwarding state. For example, to connect igb0 and igb1 as a transparent bridge:
ifconfig bridge0 create
ifconfig bridge0 addm igb0 addm igb1 up
ifconfig igb0 up
ifconfig igb1 up
ifconfig bridge0
The bridge interface receives a generated Ethernet address when created. The member list and flags in ifconfig bridge0 show the ports and learned bridge parameters. If this is intended as an L2-only forwarder, it may not need an IP address at all. If the FreeBSD host itself needs to communicate on the bridged LAN, assign the host’s address to the bridge interface, not to a member that is being incorporated into the bridge. On FreeBSD 15.1, attempting to assign an IP address to a member, or add a member that already has an IP address, returns EINVAL by default. Setting net.link.bridge.member_ifaddrs=1 restores the deprecated compatibility behavior; the sysctl is removed in FreeBSD 16.0. The manual separately documents IPv6 link-local scope handling, including automatic removal of member IPv6 addresses when the bridge already has IPv6 addresses and the net.link.bridge.allow_llz_overlap control; check that section before assuming every IPv6 case follows the general rule. Put the host’s Layer 3 address on bridge0 rather than relying on the deprecated compatibility setting.
# Example only: documentation address; use the approved host address.
ifconfig bridge0 inet 192.0.2.20/24
route -n get default
arp -an
Never add an addressed management interface to a bridge remotely without out-of-band access. Move the address deliberately and verify the default route, ARP behavior, and SSH path before closing the original session. Do not configure the same address on both bridge and member.
Make a tested configuration persistent
After the runtime topology works, define the clone and membership in /etc/rc.conf. An illustrative two-port bridge with a host address is:
# /etc/rc.conf; merge bridge0 into any existing cloned_interfaces list.
cloned_interfaces="bridge0"
ifconfig_igb0="up"
ifconfig_igb1="up"
ifconfig_bridge0="inet 192.0.2.20/24 addm igb0 addm igb1 up"
This uses a documentation-only address. Preserve existing cloned_interfaces entries when adding a bridge; replacing the variable can silently remove tap, lagg, or other interfaces created elsewhere. rc.conf(5) and the Handbook define the network variables and ordering behavior for the installed release. If configuration management also controls interfaces, modify its source rather than a generated file.
Apply changes during a planned window. Restarting the whole network stack can disrupt jails, VLANs, storage, guest networking, or the session used to make the change. The exact service action for an individual interface depends on the release and topology. Keep a short rollback script that removes the bridge members and restores the prior address and route; test the syntax in a lab before relying on it. A reboot is not a harmless configuration test if the bridge is the only management path.
Prevent loops with spanning tree where the topology requires it
If the bridge can have more than one path to the same Layer-2 segment, spanning tree is essential to avoid a forwarding loop. FreeBSD supports STP and RSTP on bridge member ports. STP is enabled per member, and the current if_bridge(4) documentation describes RSTP as the default protocol mode once enabled. For example:
ifconfig bridge0 stp igb0 stp igb1
ifconfig bridge0
Do not enable STP on a bridge in isolation and assume the wider topology is now safe. Confirm that connected switches participate in a compatible tree, observe the root bridge and port roles, and ensure a transition to a blocked port will not isolate management or storage. A bridge with a single path may not need STP; a bridge attached to redundant switch paths usually does. Keep bridge priority and path-cost choices aligned with the network design rather than leaving multiple devices to become accidental root.
The member state output includes protocol, role, and forwarding state. A port that is not forwarding may be correctly blocked to prevent a loop, or may be blocked by an unexpected topology. Compare the FreeBSD bridge’s reported root ID and roles with switch spanning-tree output. When testing failover, disconnect one path at a time in a controlled window and verify convergence, packet loss duration, and return to the expected topology.
Understand learning, filtering, and observation features
The bridge learns a source MAC address on the interface where a frame arrives and uses its forwarding cache to select an egress port. Entries age out after their timeout; a MAC moving between ports, repeated topology changes, or a cache full of stale observations can produce confusing connectivity. ifconfig bridge0 displays bridge parameters and member information, while netstat -I supplies interface traffic counters. Capture on the appropriate member and on the bridge when needed, keeping in mind that offloads and capture hooks can change which frames are visible.
The if_bridge(4) interface includes controls such as private, span, and sticky. A span port receives copies of frames for passive observation and cannot simultaneously be a normal forwarding member. A private member is prevented from forwarding to another private member. Sticky learning treats dynamically learned addresses as static in the forwarding cache; because those entries do not age or move normally, use the option only when that behavior is intended. These are forwarding controls, not substitutes for a complete network access policy.
Packet filtering requires special care at Layer 2. FreeBSD’s if_bridge(4) documents filtering hooks on the ingress member, bridge, and egress interface; the net.link.bridge.pfil_member and pfil_bridge sysctls control those stages. net.link.bridge.pfil_onlyip changes non-IP handling: ARP and REVARP are forwarded without being filtered, while other non-IP/non-IPv6 Ethernet frames are not forwarded when this option is enabled. IPFW has separate Layer-2 controls, including ipfw_arp and Ethernet-type matching. Inspect the running sysctl values and the selected firewall’s bridge integration, then test ARP, IPv4, IPv6, and every required non-IP protocol separately. A test that only confirms one TCP connection can miss broken neighbor discovery or control traffic.
For centralized telemetry, FreeBSD’s bsnmpd bridge module can expose bridge MIB data, including topology changes and port state. Enable that only through a reviewed SNMP configuration with the monitoring system’s supported authentication and access model. At minimum, record bridge member state, packet counters, STP root/roles, MAC movement, and time since the last topology change so that an intermittent loop can be correlated with an incident.
Diagnose the boundary where forwarding stops
If the host can reach a peer but guests cannot, verify each attachment: guest tap or epair membership, bridge state, physical member carrier, switch port configuration, and peer VLAN. If the bridge has no learned address for a peer, compare ingress counters and captures at both bridge members. If an address is learned on an unexpected port, trace duplicate MACs, a loop, or a device that moved without the expected switch update.
When the host loses network access after creating the bridge, inspect where its IP and default route now reside. If adding a member returns EINVAL, check whether the member still has an IP address; this is the default behavior on FreeBSD 15.1. Only a deliberately enabled net.link.bridge.member_ifaddrs=1 permits the deprecated general behavior, and that sysctl is removed in 16.0, so do not rely on it. For IPv6 link-local addresses, also inspect the documented scope-overlap behavior and the allow_llz_overlap setting. Check that bridge0 itself has the address and that members are only marked up. For IPv6, inspect neighbor discovery and router advertisements on the bridge, not only on the physical member.
If small packets pass but larger transfers fail, test MTU and offloads along every member and switch path. If failover causes an outage, compare RSTP port roles, root identity, interface carrier events, and packet loss timestamps. If firewall behavior differs from routed traffic, determine whether the frames are actually crossing the Layer-2 bridge and which protocol family is being filtered. Change one variable at a time and preserve before/after counters.
Useful bounded evidence includes:
ifconfig bridge0
ifconfig igb0
netstat -I bridge0 -w 1
netstat -I igb0 -w 1
tcpdump -eni igb0 -c 100
The capture is limited to 100 packets to avoid an unbounded file or output stream. Use a narrower BPF expression for a production incident, protect captures as operational data, and correlate the output with a switch mirror or counters. A command that returns normally is not acceptance evidence; verify the expected frame and forwarding direction from a known test peer.
Validate with a reversible failure test
An acceptance test should cover topology, forwarding, host services, and recovery. Confirm bridge and member state, test a known MAC in both directions, verify the host’s own address and default route, test each required protocol, and measure behavior under representative packet size and load. If the host participates in redundant paths, perform a single-link failure test while monitoring both STP and application-level reachability. Restore the link and verify that the bridge returns to the intended root and port roles.
Test the persistent configuration in a maintenance window with console access. Before reboot, review the final variable values, ensure unrelated clones remain in cloned_interfaces, and preserve a copy of the prior config. After reboot, compare the runtime bridge against the previously accepted state and verify the same traffic again. Document whether the bridge is transparent, which interfaces it connects, who owns STP policy, how filtering works, and which monitoring signal indicates a loop or unexpected topology change.
A bridge is reliable when its forwarding boundary is explicit and operators can explain every member. The success criteria are not merely an UP flag: expected MAC learning, correct IP placement, loop-free topology, visible counters, and a tested rollback path are all part of the operational design.
Related:
- Fixing FreeBSD Jail Networking When VNET Jails Can’t Reach the Network
- How to Set Up a bhyve Virtual Machine Step by Step
Sources: