diff --git a/net/bridge.go b/net/bridge.go new file mode 100644 index 00000000..07d1f6cb --- /dev/null +++ b/net/bridge.go @@ -0,0 +1,53 @@ +package net + +import ( + "github.com/vishvananda/netlink" +) + +type BridgeType int + +const ( + WeaveBridgeName = "weave" + DatapathName = "datapath" + + None BridgeType = iota + Bridge + Fastdp + BridgedFastdp + Inconsistent +) + +func DetectBridgeType(weaveBridgeName, datapathName string) BridgeType { + bridge, _ := netlink.LinkByName(weaveBridgeName) + datapath, _ := netlink.LinkByName(datapathName) + + switch { + case bridge == nil && datapath == nil: + return None + case isBridge(bridge) && datapath == nil: + return Bridge + case isDatapath(bridge) && datapath == nil: + return Fastdp + case isDatapath(datapath) && isBridge(bridge): + return BridgedFastdp + default: + return Inconsistent + } +} + +func isBridge(link netlink.Link) bool { + _, isBridge := link.(*netlink.Bridge) + return isBridge +} + +func isDatapath(link netlink.Link) bool { + switch link.(type) { + case *netlink.GenericLink: + return link.Type() == "openvswitch" + case *netlink.Device: + // Assume it's our openvswitch device, and the kernel has not been updated to report the kind. + return true + default: + return false + } +} diff --git a/net/veth.go b/net/veth.go index ea3e30d4..72dfd558 100644 --- a/net/veth.go +++ b/net/veth.go @@ -13,13 +13,13 @@ import ( // create and attach a veth to the Weave bridge func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, init func(peer netlink.Link) error) (*netlink.Veth, error) { - maybeBridge, err := netlink.LinkByName(bridgeName) + bridge, err := netlink.LinkByName(bridgeName) if err != nil { return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName) } if mtu == 0 { - mtu = maybeBridge.Attrs().MTU + mtu = bridge.Attrs().MTU } veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{ @@ -36,25 +36,22 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, init func(p return nil, fmt.Errorf(format, a...) } - switch maybeBridge.(type) { - case *netlink.Bridge: - if err := netlink.LinkSetMasterByIndex(veth, maybeBridge.Attrs().Index); err != nil { + switch bridgeType := DetectBridgeType(bridgeName, DatapathName); bridgeType { + case Bridge, BridgedFastdp: + if err := netlink.LinkSetMasterByIndex(veth, bridge.Attrs().Index); err != nil { return cleanup(`unable to set master of %s: %s`, name, err) } - case *netlink.GenericLink: - if maybeBridge.Type() != "openvswitch" { - return cleanup(`device "%s" is of type "%s"`, bridgeName, maybeBridge.Type()) + if bridgeType == Bridge { + if err := EthtoolTXOff(peerName); err != nil { + return cleanup(`unable to set tx off on %q: %s`, peerName, err) + } } - if err := odp.AddDatapathInterface(bridgeName, name); err != nil { - return cleanup(`failed to attach %s to device "%s": %s`, name, bridgeName, err) - } - case *netlink.Device: - // Assume it's our openvswitch device, and the kernel has not been updated to report the kind. + case Fastdp: if err := odp.AddDatapathInterface(bridgeName, name); err != nil { return cleanup(`failed to attach %s to device "%s": %s`, name, bridgeName, err) } default: - return cleanup(`device "%s" is not a bridge`, bridgeName) + return cleanup(`invalid bridge configuration`) } if init != nil { @@ -121,7 +118,6 @@ func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, } name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id _, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, func(veth netlink.Link) error { - EthtoolTXOff(peerName) // TODO: do we want to do this under fastdp? if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil { return fmt.Errorf("failed to move veth to container netns: %s", err) } diff --git a/plugin/net/cni.go b/plugin/net/cni.go index efe247f0..f43ef967 100644 --- a/plugin/net/cni.go +++ b/plugin/net/cni.go @@ -32,7 +32,7 @@ func NewCNIPlugin(weave *weaveapi.Client) *CNIPlugin { func loadNetConf(bytes []byte) (*NetConf, error) { n := &NetConf{ - BrName: "weave", + BrName: weavenet.WeaveBridgeName, } if err := json.Unmarshal(bytes, n); err != nil { return nil, fmt.Errorf("failed to load netconf: %v", err) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index 08f90a73..966fe98b 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -15,10 +15,6 @@ import ( "github.com/weaveworks/weave/plugin/skel" ) -const ( - WeaveBridge = "weave" -) - type driver struct { scope string noMulticastRoute bool @@ -101,7 +97,7 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error driver.logReq("JoinEndpoint", j, fmt.Sprintf("%s:%s to %s", j.NetworkID, j.EndpointID, j.SandboxKey)) name, peerName := vethPair(j.EndpointID) - if _, err := weavenet.CreateAndAttachVeth(name, peerName, WeaveBridge, 0, nil); err != nil { + if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, nil); err != nil { return nil, driver.error("JoinEndpoint", "%s", err) }