When setting up a Linux bridge between two Ethernet interfaces in a virtualized environment (Hyper-V in this case), several configuration elements need to be verified:
# Sample bridge configuration (/etc/conf.d/net)
bridge_br0=("eth0 eth1")
config_eth0=("null")
config_eth1=("null")
config_br0=("192.168.1.197 netmask 255.255.255.0 brd 192.168.1.255")
routes_br0=("default via 192.168.1.101")
First, check if the bridge is properly created and interfaces are added:
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.00155d000108 no eth0
eth1
The forwarding state of each interface is crucial:
# brctl showstp br0
eth0 (1) state forwarding
eth1 (2) state forwarding
Several kernel parameters affect bridge packet forwarding:
# /etc/sysctl.conf settings
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-iptables = 0
Verify that MAC addresses are being learned correctly:
# brctl showmacs br0
port no mac addr is local? ageing timer
1 00:15:5d:00:01:03 no 1.51
1 00:15:5d:00:01:08 yes 0.00
2 00:15:5d:00:01:12 no 36.22
2 00:15:5d:00:01:13 yes 0.00
When working with Hyper-V or other hypervisors:
- Ensure promiscuous mode is enabled for virtual switches
- Verify that MAC address spoofing is allowed
- Check for VLAN tagging conflicts
Additional diagnostic tools can help identify issues:
# Check bridge filtering
ebtables -L --Lc
# Monitor bridge traffic
tcpdump -i br0 -nn -e
# Verify ARP entries
arp -n
For modern Linux systems, consider using iproute2 instead of brctl:
# Create bridge with iproute2
ip link add name br0 type bridge
ip link set dev eth0 master br0
ip link set dev eth1 master br0
ip link set br0 up
After making changes, verify connectivity:
# From bridge host
ping 192.168.1.195 # NUX3
ping 192.168.1.101 # Router
# From NUX3
ping 192.168.1.197 # Bridge
ping 192.168.1.101 # Router
We're working with a virtualized environment where:
- NUX3 (192.168.1.195/24) connects to eth1
- Router (192.168.1.101/24) connects to eth0
- Bridge br0 has IP 192.168.1.197/24
The bridge is correctly set up with both interfaces showing as forwarding:
# brctl showstp br0
eth0 (1) state forwarding
eth1 (2) state forwarding
However, connectivity fails between NUX3 and the bridge/router despite proper MAC address learning:
# brctl showmacs br0
port no mac addr is local? ageing timer
1 00:15:5d:00:01:03 no 1.51
1 00:15:5d:00:01:08 yes 0.00
2 00:15:5d:00:01:12 no 36.22
2 00:15:5d:00:01:13 yes 0.00
First, verify the bridge filtering database:
# bridge fdb show
00:15:5d:00:01:03 dev eth0
00:15:5d:00:01:12 dev eth1
Check for VLAN filtering (common issue in virtualized environments):
# bridge vlan show
port vlan ids
eth0 1 PVID Egress Untagged
eth1 1 PVID Egress Untagged
br0 1 PVID Egress Untagged
For Hyper-V virtual switches, ensure MAC address spoofing is enabled:
# Check if NICs are in promiscuous mode
# ip link show eth0
# ip link show eth1
Verify the virtual switch configuration in Hyper-V Manager:
- Ensure the vSwitch is in External mode
- Check "Allow management OS to share this network adapter"
- Enable MAC address spoofing for both NICs
Packet capture verification:
# tcpdump -i eth0 -n -e
# tcpdump -i eth1 -n -e
# tcpdump -i br0 -n -e
Bridge monitoring:
# watch -n 1 "brctl showmacs br0"
Try these configuration adjustments:
# Disable bridge netfilter completely
echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 0 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
echo 0 > /proc/sys/net/bridge/bridge-nf-call-arptables
# Set bridge forward delay to 0
brctl setfd br0 0
# Enable hairpin mode (for virtualized environments)
brctl hairpin br0 eth0 on
brctl hairpin br0 eth1 on
Alternative configuration file (/etc/network/interfaces style):
auto br0
iface br0 inet static
address 192.168.1.197
netmask 255.255.255.0
gateway 192.168.1.101
bridge_ports eth0 eth1
bridge_stp off
bridge_fd 0
bridge_maxwait 0
Check kernel bridging statistics:
# cat /sys/class/net/br0/bridge/forward_delay
# cat /sys/class/net/br0/bridge/stp_state
Monitor bridge traffic with counters:
# brctl showstp br0 | grep -A 10 transmitted
# ethtool -S eth0 | grep -i discard
# ethtool -S eth1 | grep -i discard
After applying changes, verify with:
# ping -I br0 192.168.1.101
# ping -I br0 192.168.1.195
# arping -I br0 192.168.1.195
# tracepath -n 192.168.1.195