diff --git a/net/veth.go b/net/veth.go new file mode 100644 index 00000000..f070f96d --- /dev/null +++ b/net/veth.go @@ -0,0 +1,57 @@ +package net + +import ( + "fmt" + + "github.com/vishvananda/netlink" + + "github.com/weaveworks/weave/common/odp" +) + +// create and attach local name to the Weave bridge +func CreateAndAttachVeth(localName, peerName, bridgeName string, mtu int) (*netlink.Veth, error) { + maybeBridge, 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 + } + local := &netlink.Veth{ + LinkAttrs: netlink.LinkAttrs{ + Name: localName, + MTU: mtu}, + PeerName: peerName, + } + if err := netlink.LinkAdd(local); err != nil { + return nil, fmt.Errorf(`could not create veth pair %s-%s: %s`, local.Name, local.PeerName, err) + } + + switch maybeBridge.(type) { + case *netlink.Bridge: + if err := netlink.LinkSetMasterByIndex(local, maybeBridge.Attrs().Index); err != nil { + return nil, fmt.Errorf(`unable to set master of %s: %s`, local.Name, err) + } + case *netlink.GenericLink: + if maybeBridge.Type() != "openvswitch" { + return nil, fmt.Errorf(`device "%s" is of type "%s"`, bridgeName, maybeBridge.Type()) + } + if err := odp.AddDatapathInterface(bridgeName, local.Name); err != nil { + return nil, fmt.Errorf(`failed to attach %s to device "%s": %s`, local.Name, bridgeName, err) + } + case *netlink.Device: + // Assume it's our openvswitch device, and the kernel has not been updated to report the kind. + if err := odp.AddDatapathInterface(bridgeName, local.Name); err != nil { + return nil, fmt.Errorf(`failed to attach %s to device "%s": %s`, local.Name, bridgeName, err) + } + default: + return nil, fmt.Errorf(`device "%s" is not a bridge`, bridgeName) + } + + if err := netlink.LinkSetUp(local); err != nil { + return nil, fmt.Errorf("unable to bring veth up: %s", err) + } + + return local, nil +} diff --git a/plugin/net/cni.go b/plugin/net/cni.go index 3682a721..328dadd3 100644 --- a/plugin/net/cni.go +++ b/plugin/net/cni.go @@ -15,6 +15,7 @@ import ( "github.com/vishvananda/netns" weaveapi "github.com/weaveworks/weave/api" "github.com/weaveworks/weave/common" + weavenet "github.com/weaveworks/weave/net" ipamplugin "github.com/weaveworks/weave/plugin/ipam" ) @@ -70,7 +71,8 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { id = fmt.Sprintf("%x", data) } - local, err := createAndAttach(id, conf.BrName, conf.MTU) + name, peerName := vethPair(id) + local, err := weavenet.CreateAndAttachVeth(name, peerName, conf.BrName, conf.MTU) if err != nil { return err } @@ -87,10 +89,6 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { return cleanup(fmt.Errorf("failed to move veth to container netns: %s", err)) } - if err := netlink.LinkSetUp(local); err != nil { - return cleanup(fmt.Errorf("unable to bring veth up: %s", err)) - } - var result *types.Result // Default IPAM is Weave's own if conf.IPAM.Type == "" { diff --git a/plugin/net/driver.go b/plugin/net/driver.go index 751e10ae..c162f117 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -11,7 +11,7 @@ import ( weaveapi "github.com/weaveworks/weave/api" "github.com/weaveworks/weave/common" "github.com/weaveworks/weave/common/docker" - "github.com/weaveworks/weave/common/odp" + weavenet "github.com/weaveworks/weave/net" "github.com/weaveworks/weave/plugin/skel" ) @@ -100,15 +100,12 @@ func (driver *driver) EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointI 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)) - local, err := createAndAttach(j.EndpointID, WeaveBridge, 0) + name, peerName := vethPair(j.EndpointID) + local, err := weavenet.CreateAndAttachVeth(name, peerName, WeaveBridge, 0) if err != nil { return nil, driver.error("JoinEndpoint", "%s", err) } - if err := netlink.LinkSetUp(local); err != nil { - return nil, driver.error("JoinEndpoint", "unable to bring up veth %s-%s: %s", local.Name, local.PeerName, err) - } - ifname := &api.InterfaceName{ SrcName: local.PeerName, DstPrefix: "ethwe", @@ -128,50 +125,11 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error return response, nil } -// create and attach local name to the Weave bridge -func createAndAttach(id, bridgeName string, mtu int) (*netlink.Veth, error) { - maybeBridge, err := netlink.LinkByName(bridgeName) - if err != nil { - return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName) - } - - local := vethPair(id[:5]) - if mtu == 0 { - local.Attrs().MTU = maybeBridge.Attrs().MTU - } else { - local.Attrs().MTU = mtu - } - if err := netlink.LinkAdd(local); err != nil { - return nil, fmt.Errorf(`could not create veth pair %s-%s: %s`, local.Name, local.PeerName, err) - } - - switch maybeBridge.(type) { - case *netlink.Bridge: - if err := netlink.LinkSetMasterByIndex(local, maybeBridge.Attrs().Index); err != nil { - return nil, fmt.Errorf(`unable to set master of %s: %s`, local.Name, err) - } - case *netlink.GenericLink: - if maybeBridge.Type() != "openvswitch" { - return nil, fmt.Errorf(`device "%s" is of type "%s"`, bridgeName, maybeBridge.Type()) - } - if err := odp.AddDatapathInterface(bridgeName, local.Name); err != nil { - return nil, fmt.Errorf(`failed to attach %s to device "%s": %s`, local.Name, bridgeName, err) - } - case *netlink.Device: - // Assume it's our openvswitch device, and the kernel has not been updated to report the kind. - if err := odp.AddDatapathInterface(bridgeName, local.Name); err != nil { - return nil, fmt.Errorf(`failed to attach %s to device "%s": %s`, local.Name, bridgeName, err) - } - default: - return nil, fmt.Errorf(`device "%s" is not a bridge`, bridgeName) - } - return local, nil -} - func (driver *driver) LeaveEndpoint(leave *api.LeaveRequest) error { driver.logReq("LeaveEndpoint", leave, fmt.Sprintf("%s:%s", leave.NetworkID, leave.EndpointID)) - local := vethPair(leave.EndpointID[:5]) + name, _ := vethPair(leave.EndpointID) + local := &netlink.Veth{LinkAttrs: netlink.LinkAttrs{Name: name}} if err := netlink.LinkDel(local); err != nil { driver.warn("LeaveEndpoint", "unable to delete veth: %s", err) } @@ -188,13 +146,8 @@ func (driver *driver) DiscoverDelete(disco *api.DiscoveryNotification) error { return nil } -// === - -func vethPair(suffix string) *netlink.Veth { - return &netlink.Veth{ - LinkAttrs: netlink.LinkAttrs{Name: "vethwl" + suffix}, - PeerName: "vethwg" + suffix, - } +func vethPair(id string) (string, string) { + return "vethwl" + id[:5], "vethwg" + id[:5] } // logging