From 85023e0a76f7a0dd19717d9738dfe4abfbaf7824 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 21 May 2016 15:34:47 +0000 Subject: [PATCH] Extract AttachContainer() function Also move netlink and netns code from common to net Creates interface if not already there Adds addresses Move the set link 'up' to after addresses are added --- common/utils.go | 29 +++++--------------- {common => net}/arp.go | 2 +- net/netns.go | 37 ++++++++++++++++++++++++++ net/veth.go | 60 ++++++++++++++++++++++++++++++++++++------ plugin/net/cni.go | 25 +++++------------- 5 files changed, 103 insertions(+), 50 deletions(-) rename {common => net}/arp.go (98%) create mode 100644 net/netns.go diff --git a/common/utils.go b/common/utils.go index d856e40e..666eb4f7 100644 --- a/common/utils.go +++ b/common/utils.go @@ -2,12 +2,14 @@ package common import ( "fmt" - "github.com/vishvananda/netlink" - "github.com/vishvananda/netns" "net" "os" - "runtime" "strings" + + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" + + weavenet "github.com/weaveworks/weave/net" ) // Assert test is true, panic otherwise @@ -25,25 +27,6 @@ func ErrorMessages(errors []error) string { return strings.Join(result, "\n") } -func WithNetNS(ns netns.NsHandle, work func() error) error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - oldNs, err := netns.Get() - if err == nil { - defer oldNs.Close() - - err = netns.Set(ns) - if err == nil { - defer netns.Set(oldNs) - - err = work() - } - } - - return err -} - type NetDev struct { Name string MAC net.HardwareAddr @@ -63,7 +46,7 @@ func FindNetDevs(processID int, match func(link netlink.Link) bool) ([]NetDev, e } defer ns.Close() - err = WithNetNS(ns, func() error { + err = weavenet.WithNetNS(ns, func() error { return forEachLink(func(link netlink.Link) error { if match(link) { netDev, err := linkToNetDev(link) diff --git a/common/arp.go b/net/arp.go similarity index 98% rename from common/arp.go rename to net/arp.go index 094d6b16..8315db94 100644 --- a/common/arp.go +++ b/net/arp.go @@ -1,4 +1,4 @@ -package common +package net import "fmt" import "io" diff --git a/net/netns.go b/net/netns.go new file mode 100644 index 00000000..aeb8214c --- /dev/null +++ b/net/netns.go @@ -0,0 +1,37 @@ +package net + +import ( + "runtime" + + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" +) + +func WithNetNS(ns netns.NsHandle, work func() error) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + oldNs, err := netns.Get() + if err == nil { + defer oldNs.Close() + + err = netns.Set(ns) + if err == nil { + defer netns.Set(oldNs) + + err = work() + } + } + + return err +} + +func WithNetNSLink(ns netns.NsHandle, ifName string, work func(link netlink.Link) error) error { + return WithNetNS(ns, func() error { + link, err := netlink.LinkByName(ifName) + if err != nil { + return err + } + return work(link) + }) +} diff --git a/net/veth.go b/net/veth.go index 0c11a325..3710fd7c 100644 --- a/net/veth.go +++ b/net/veth.go @@ -4,9 +4,10 @@ import ( "fmt" "net" + "github.com/j-keck/arping" "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" - "github.com/weaveworks/weave/common" "github.com/weaveworks/weave/common/odp" ) @@ -73,22 +74,65 @@ func CreateAndAttachVeth(localName, peerName, bridgeName string, mtu int, init f return local, nil } -func SetupGuest(guest netlink.Link, name string, cidrs []net.IPNet) error { +func SetupGuest(guest netlink.Link, name string) error { var err error if err = netlink.LinkSetName(guest, name); err != nil { return err } - if err = netlink.LinkSetUp(guest); err != nil { + if err = ConfigureARPCache(name); err != nil { return err } - if err = common.ConfigureARPCache(name); err != nil { + return nil +} + +func AddAddresses(guest netlink.Link, cidrs []*net.IPNet) error { + for _, ipnet := range cidrs { + if err := netlink.AddrAdd(guest, &netlink.Addr{IPNet: ipnet}); err != nil { + return fmt.Errorf("failed to add IP address to %q: %v", guest.Attrs().Name, err) + } + arping.GratuitousArpOverIfaceByName(ipnet.IP, guest.Attrs().Name) + } + return nil +} + +func interfaceExistsInNamespace(ns netns.NsHandle, ifName string) bool { + err := WithNetNS(ns, func() error { + _, err := netlink.LinkByName(ifName) return err + }) + return err == nil +} + +func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, cidrs []*net.IPNet) error { + if !interfaceExistsInNamespace(ns, ifName) { + if len(id) > 5 { + id = id[:5] + } + name, peerName := "vethwepl"+id, "vethwg"+id + _, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, func(local, guest netlink.Link) error { + if err := netlink.LinkSetNsFd(guest, int(ns)); err != nil { + return fmt.Errorf("failed to move veth to container netns: %s", err) + } + if err := WithNetNS(ns, func() error { + return SetupGuest(guest, ifName) + }); err != nil { + return fmt.Errorf("error setting up interface: %s", err) + } + return nil + }) + if err != nil { + return err + } } - for _, ipnet := range cidrs { - if err = netlink.AddrAdd(guest, &netlink.Addr{IPNet: &ipnet}); err != nil { - return fmt.Errorf("failed to add IP address to %q: %v", name, err) + + if err := WithNetNSLink(ns, ifName, func(guest netlink.Link) error { + if err := AddAddresses(guest, cidrs); err != nil { + return err } - arping.GratuitousArpOverIfaceByName(ipnet.IP, name) + return netlink.LinkSetUp(guest) + }); err != nil { + return err } + return nil } diff --git a/plugin/net/cni.go b/plugin/net/cni.go index 574882d7..178b67e7 100644 --- a/plugin/net/cni.go +++ b/plugin/net/cni.go @@ -10,7 +10,6 @@ import ( "github.com/appc/cni/pkg/ipam" "github.com/appc/cni/pkg/skel" "github.com/appc/cni/pkg/types" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" weaveapi "github.com/weaveworks/weave/api" @@ -94,24 +93,14 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { id = fmt.Sprintf("%x", data) } - name, peerName := vethPair(id) - _, err = weavenet.CreateAndAttachVeth(name, peerName, conf.BrName, conf.MTU, func(local, guest netlink.Link) error { - if err = netlink.LinkSetNsFd(guest, int(ns)); err != nil { - return fmt.Errorf("failed to move veth to container netns: %s", err) - } - if err = common.WithNetNS(ns, func() error { - if err := weavenet.SetupGuest(guest, args.IfName, []net.IPNet{result.IP4.IP}); err != nil { - return err - } - return setupRoutes(guest, args.IfName, result.IP4.IP, result.IP4.Gateway, result.IP4.Routes) - }); err != nil { - return fmt.Errorf("error setting up interface: %s", err) - } - return nil - }) - if err != nil { + if err := weavenet.AttachContainer(ns, id, args.IfName, conf.BrName, conf.MTU, []*net.IPNet{&result.IP4.IP}); err != nil { return err } + if err := weavenet.WithNetNSLink(ns, args.IfName, func(guest netlink.Link) error { + return setupRoutes(guest, args.IfName, result.IP4.IP, result.IP4.Gateway, result.IP4.Routes) + }); err != nil { + return fmt.Errorf("error setting up routes: %s", err) + } result.DNS = conf.DNS return result.Print() @@ -186,7 +175,7 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error { return err } defer ns.Close() - err = common.WithNetNS(ns, func() error { + err = weavenet.WithNetNS(ns, func() error { link, err := netlink.LinkByName(args.IfName) if err != nil { return err