ns: add interface, use it, and fix thread-related namespace switch issues

Add a namespace object interface for somewhat cleaner code when
creating and switching between network namespaces.  All created
namespaces are now mounted in /var/run/netns to ensure they
have persistent inodes and paths that can be passed around
between plugin components without relying on the current namespace
being correct.

Also remove the thread-locking arguments from the ns package
per https://github.com/appc/cni/issues/183 by doing all the namespace
changes in a separate goroutine that locks/unlocks itself, instead of
the caller having to track OS thread locking.
This commit is contained in:
Dan Williams
2016-04-05 11:10:31 -05:00
parent 3e1c3c60da
commit c0d34c692f
19 changed files with 373 additions and 460 deletions

View File

@ -19,7 +19,6 @@ import (
"errors"
"fmt"
"net"
"os"
"runtime"
"syscall"
@ -129,10 +128,10 @@ func ensureBridge(brName string, mtu int) (*netlink.Bridge, error) {
return br, nil
}
func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool) error {
func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool) error {
var hostVethName string
err := ns.WithNetNSPath(netns, false, func(hostNS *os.File) error {
err := netns.Do(func(hostNS ns.NetNS) error {
// create the veth pair in the container and move host end into host netns
hostVeth, _, err := ip.SetupVeth(ifName, mtu, hostNS)
if err != nil {
@ -191,7 +190,13 @@ func cmdAdd(args *skel.CmdArgs) error {
return err
}
if err = setupVeth(args.Netns, br, args.IfName, n.MTU, n.HairpinMode); err != nil {
netns, err := ns.GetNS(args.Netns)
if err != nil {
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
}
defer netns.Close()
if err = setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode); err != nil {
return err
}
@ -209,7 +214,7 @@ func cmdAdd(args *skel.CmdArgs) error {
result.IP4.Gateway = calcGatewayIP(&result.IP4.IP)
}
err = ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error {
err = netns.Do(func(_ ns.NetNS) error {
return ipam.ConfigureIface(args.IfName, result)
})
if err != nil {
@ -254,7 +259,7 @@ func cmdDel(args *skel.CmdArgs) error {
}
var ipn *net.IPNet
err = ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error {
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
var err error
ipn, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4)
return err