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
```