From baa8f229f7ac6c5ae5e389083d9bf4757f9aef8d Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Fri, 25 Nov 2016 18:05:38 +0000 Subject: [PATCH] Detect enabling of hairpin mode on vethwe-bridge Enabled hairpin mode on vethwe-bridge was one of the root causes for installing looping flows in the fastdp mode. Also, it confused the weave custom L2 bridge, as the bridge treats a bounced back packet, e.g. ARP brodcast request, as a local one (the case for "Captured a packet associated with remote host"). --- net/bridge.go | 35 +++++++++++++++++++++++++++++++++ prog/weaver/main.go | 6 ++++++ test/705_detect_hairpin_test.sh | 12 +++++++++++ 3 files changed, 53 insertions(+) create mode 100755 test/705_detect_hairpin_test.sh diff --git a/net/bridge.go b/net/bridge.go index 07d1f6cb..da0bd40a 100644 --- a/net/bridge.go +++ b/net/bridge.go @@ -1,6 +1,9 @@ package net import ( + "fmt" + + "github.com/Sirupsen/logrus" "github.com/vishvananda/netlink" ) @@ -51,3 +54,35 @@ func isDatapath(link netlink.Link) bool { return false } } + +func DetectHairpin(portIfName string, log *logrus.Logger) error { + link, err := netlink.LinkByName(portIfName) + if err != nil { + return fmt.Errorf("Unable to find link %q: %s", portIfName, err) + } + + ch := make(chan netlink.LinkUpdate) + // See EnsureInterface for why done channel is not passed + if err := netlink.LinkSubscribe(ch, nil); err != nil { + return fmt.Errorf("Unable to subscribe to netlink updates: %s", err) + } + + pi, err := netlink.LinkGetProtinfo(link) + if err != nil { + return fmt.Errorf("Unable to get link protinfo %q: %s", portIfName, err) + } + if pi.Hairpin { + return fmt.Errorf("Hairpin mode enabled on %q", portIfName) + } + + go func() { + for up := range ch { + if up.Attrs().Name == portIfName && up.Attrs().Protinfo != nil && + up.Attrs().Protinfo.Hairpin { + log.Errorf("Hairpin mode enabled on %q", portIfName) + } + } + }() + + return nil +} diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 92cb5bba..2050f49e 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -226,6 +226,12 @@ func main() { overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB) networkConfig.Bridge = bridge + if bridge != nil { + if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil { + Log.Errorf("DetectHairpin failed: %s", err) + } + } + name := peerName(routerName, bridge.Interface()) if nickName == "" { diff --git a/test/705_detect_hairpin_test.sh b/test/705_detect_hairpin_test.sh new file mode 100755 index 00000000..4ba915ed --- /dev/null +++ b/test/705_detect_hairpin_test.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +. ./config.sh + +start_suite "Detect hairpin mode" + +weave_on $HOST1 launch + +assert_raises "run_on $HOST1 sudo ip link set vethwe-bridge type bridge_slave hairpin on" +assert_raises "docker_on $HOST1 logs weave 2>&1 | grep -q 'Hairpin mode enabled on \"vethwe-bridge\"'" + +end_suite