Page MenuHomeFreeBSD

netgraph/ng_bridge: move MACs via control message
Needs ReviewPublic

Authored by donner on Feb 9 2021, 8:08 PM.

Details

Reviewers
None
Group Reviewers
network
manpages
Summary

Use the new control message to move ethernet addresses from a link to
a new link in ng_bridge(4). Send this message instead of doing the
work directly requires to move the loop detection into the control
message processing. This will delay the loop detection by a few
frames.

This decouples the read-only activity from the modification under a
more strict writer lock.

Depend on D28516

Test Plan

Build a looped bridge

+ mkpeer bridge b link0
+ name b b
+ mkpeer b: tee link1 left
+ connect b link1 link2 right
+ shutdown b.link1
+ rmhook b
+ mkpeer b: eiface link0 ether
+ mkpeer b: eiface link3 ether
+ msg b: setconfig { debugLevel=3 loopTimeout=60 maxStaleness=900 minStableAge=1 }

Now we have a bridge where link1 and link2 are directly connected.

Sniff on the seondary interface:

# ifconfig ngeth1 up
# tcpdump -eni ngeth1 &

Check state:

# ( ngctl msg b: gettable ; ngctl msg b: getstats 0 ; ngctl msg b: getstats 1 ; ngctl msg b: getstats 2 ; ngctl msg b: getstats 3 ) | fgrep -v response
Args:   {}
Args:   {}
Args:   {}
Args:   {}
Args:   {}

Now send a packet to the bridge:

# ifconfig ngeth0 up
# ifconfig ngeth0 inet 192.168.234.123/28 alias
18:22:15.869790 58:9c:fc:10:ff:93 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.234.123 tell 192.168.234.123, length 28

Only a single packet was forwarded, despite of the loop.

Check the state of the bridge again:

# ( ngctl msg b: gettable ; ngctl msg b: getstats 0 ; ngctl msg b: getstats 1 ; ngctl msg b: getstats 2 ; ngctl msg b: getstats 3 ) | fgrep -v response
Args:   { numHosts=1 hosts=[ { addr=58:9c:fc:10:ff:93 hook="link0" age=27 staleness=27 } ] }
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 }
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 loopDrops=1 loopDetects=1 }
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 loopDrops=1 loopDetects=1 }
Args:   { xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 }

Learning MAC still works.
Loopdetection still works without harming the initial hook.

# dmesg | tail
ngeth0: Ethernet address: 58:9c:fc:10:ff:93
ngeth0: link state changed to UP
ngeth1: Ethernet address: 58:9c:fc:10:ff:c3
ngeth1: link state changed to UP
ngeth1: promiscuous mode enabled
ng_bridge: b: loopback detected on link1
ng_bridge: b: loopback detected on link2

Debug information is still valid in the kernel log.

Waiting for expiry if the loop timeout and staleness timeout

# ( ngctl msg b: gettable ; ngctl msg b: getstats 0 ; ngctl msg b: getstats 1 ; ngctl msg b: getstats 2 ; ngctl msg b: getstats 3 ) | fgrep -v response
Args:   {}
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 }
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 loopDrops=1 loopDetects=1 }
Args:   { recvOctets=42 recvPackets=1 recvBroadcast=1 xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 loopDrops=1 loopDetects=1 }
Args:   { xmitOctets=42 xmitPackets=1 xmitBroadcasts=1 }

Bridge is clean now (beside link stats). So bring a new packet in again:

# ifconfig ngeth0 inet 192.168.234.123/28 -alias
# ifconfig ngeth0 inet 192.168.234.123/28 alias
18:29:09.820185 58:9c:fc:10:ff:93 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.234.123 tell 192.168.234.123, length 28
# ( ngctl msg b: gettable ; ngctl msg b: getstats 0 ; ngctl msg b: getstats 1 ; ngctl msg b: getstats 2 ; ngctl msg b: getstats 3 ) | fgrep -v response
Args:   { numHosts=1 hosts=[ { addr=58:9c:fc:10:ff:93 hook="link0" age=2 staleness=2 } ] }
Args:   { recvOctets=84 recvPackets=2 recvBroadcast=2 }
Args:   { recvOctets=84 recvPackets=2 recvBroadcast=2 xmitOctets=84 xmitPackets=2 xmitBroadcasts=2 loopDrops=2 loopDetects=2 }
Args:   { recvOctets=84 recvPackets=2 recvBroadcast=2 xmitOctets=84 xmitPackets=2 xmitBroadcasts=2 loopDrops=2 loopDetects=2 }
Args:   { xmitOctets=84 xmitPackets=2 xmitBroadcasts=2 }

Now we have the second loop detected and avoided. Try once again, while the loop condition still holds.

# ifconfig ngeth0 inet 192.168.234.123/28 -alias
# ifconfig ngeth0 inet 192.168.234.123/28 alias
18:29:20.724345 58:9c:fc:10:ff:93 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.234.123 tell 192.168.234.123, length 28
# ( ngctl msg b: gettable ; ngctl msg b: getstats 0 ; ngctl msg b: getstats 1 ; ngctl msg b: getstats 2 ; ngctl msg b: getstats 3 ) | fgrep -v response
Args:   { numHosts=1 hosts=[ { addr=58:9c:fc:10:ff:93 hook="link0" age=14 staleness=3 } ] }
Args:   { recvOctets=126 recvPackets=3 recvBroadcast=3 }
Args:   { recvOctets=84 recvPackets=2 recvBroadcast=2 xmitOctets=126 xmitPackets=3 xmitBroadcasts=3 loopDrops=3 loopDetects=2 }
Args:   { recvOctets=84 recvPackets=2 recvBroadcast=2 xmitOctets=126 xmitPackets=3 xmitBroadcasts=3 loopDrops=3 loopDetects=2 }
Args:   { xmitOctets=126 xmitPackets=3 xmitBroadcasts=3 }

Now the packets are dropped without increasing the loopDetect counter (loop is still in place)

Once again the kernel output:

# dmesg | tail
ng_bridge: b: restoring looped back link2
ng_bridge: b: restoring looped back link1
ng_bridge: b: loopback detected on link1
ng_bridge: b: loopback detected on link2

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 37110
Build 33999: arc lint + arc unit

Event Timeline

donner requested review of this revision.Feb 9 2021, 8:08 PM
donner retitled this revision from netgraph/ng_bridge: move MAC via control message to netgraph/ng_bridge: move MACs via control message.Feb 9 2021, 8:52 PM
donner added a reviewer: network.
  • Fix move logic after rebase to modifications to the parent review.
  • Reword some comments.
  • Fix loopCount setting.
sys/netgraph/ng_bridge.c
636–640

Check is now part of the insert_or_move function.
Current check was only for "fresh insert".

835

loopDetects was part of the to be shared routine revdata.
Now it's part of the control message under the WRITER log.
So the counter framework is not longer needed.

  • Document behavior in the man page.
gbe added a subscriber: gbe.

LGTM for the man page parts.