Преглед на файлове

Merge pull request #37 from aboch/update

Sync libnetwork code to latest docker/master
Jana Radhakrishnan преди 10 години
родител
ревизия
53541c24a4
променени са 43 файла, в които са добавени 469 реда и са изтрити 5169 реда
  1. 9 22
      libnetwork/Godeps/Godeps.json
  2. 0 720
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver.go
  3. 0 161
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver_test.go
  4. 0 160
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator.go
  5. 0 681
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator_test.go
  6. 0 10
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network.go
  7. 0 175
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network_test.go
  8. 0 153
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator.go
  9. 0 245
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator_test.go
  10. 0 176
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper.go
  11. 0 152
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper_test.go
  12. 0 18
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mock_proxy.go
  13. 0 161
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/proxy.go
  14. 0 118
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/utils.go
  15. 0 2
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/MAINTAINERS
  16. 20 13
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/iptables.go
  17. 17 23
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/iptables_test.go
  18. 0 1
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/MAINTAINERS
  19. 3 3
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/tcp_proxy.go
  20. 4 4
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/udp_proxy.go
  21. 0 1
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/MAINTAINERS
  22. 7 1
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/reexec.go
  23. 0 2
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/MAINTAINERS
  24. 0 31
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink.go
  25. 0 1307
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux.go
  26. 0 5
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_arm.go
  27. 0 7
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_notarm.go
  28. 0 408
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
  29. 0 88
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_unsupported.go
  30. 17 0
      libnetwork/drivers/bridge/bridge.go
  31. 2 3
      libnetwork/drivers/bridge/network.go
  32. 1 2
      libnetwork/drivers/bridge/setup_fixedcidrv4.go
  33. 1 2
      libnetwork/drivers/bridge/setup_fixedcidrv4_test.go
  34. 1 2
      libnetwork/drivers/bridge/setup_fixedcidrv6.go
  35. 1 2
      libnetwork/drivers/bridge/setup_fixedcidrv6_test.go
  36. 36 23
      libnetwork/drivers/bridge/setup_ip_tables.go
  37. 15 14
      libnetwork/drivers/bridge/setup_ip_tables_test.go
  38. 30 21
      libnetwork/ipallocator/allocator.go
  39. 95 86
      libnetwork/ipallocator/allocator_test.go
  40. 88 51
      libnetwork/portallocator/portallocator.go
  41. 51 57
      libnetwork/portallocator/portallocator_test.go
  42. 51 35
      libnetwork/portmapper/mapper.go
  43. 20 23
      libnetwork/portmapper/mapper_test.go

+ 9 - 22
libnetwork/Godeps/Godeps.json

@@ -1,44 +1,31 @@
 {
 	"ImportPath": "github.com/docker/libnetwork",
-	"GoVersion": "go1.4.2",
-	"Packages": [
-		"./..."
-	],
+	"GoVersion": "go1.2.1",
 	"Deps": [
 		{
 			"ImportPath": "github.com/Sirupsen/logrus",
 			"Comment": "v0.6.4-12-g467d9d5",
 			"Rev": "467d9d55c2d2c17248441a8fc661561161f40d5e"
 		},
-		{
-			"ImportPath": "github.com/docker/docker/daemon/networkdriver",
-			"Comment": "v1.4.1-1379-g8e107a9",
-			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
-		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/iptables",
-			"Comment": "v1.4.1-1379-g8e107a9",
-			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/parsers/kernel",
-			"Comment": "v1.4.1-1379-g8e107a9",
-			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/proxy",
-			"Comment": "v1.4.1-1379-g8e107a9",
-			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/reexec",
-			"Comment": "v1.4.1-1379-g8e107a9",
-			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
-		},
-		{
-			"ImportPath": "github.com/docker/libcontainer/netlink",
-			"Comment": "v1.4.0-324-g88989e6",
-			"Rev": "88989e66d3a1ab960deb37f3dd7f824d85e1b9bc"
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 		},
 		{
 			"ImportPath": "github.com/vishvananda/netlink",

+ 0 - 720
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver.go

@@ -1,720 +0,0 @@
-package bridge
-
-import (
-	"encoding/hex"
-	"errors"
-	"fmt"
-	"io/ioutil"
-	"net"
-	"os"
-	"strings"
-	"sync"
-
-	log "github.com/Sirupsen/logrus"
-	"github.com/docker/docker/daemon/networkdriver"
-	"github.com/docker/docker/daemon/networkdriver/ipallocator"
-	"github.com/docker/docker/daemon/networkdriver/portmapper"
-	"github.com/docker/docker/engine"
-	"github.com/docker/docker/nat"
-	"github.com/docker/docker/pkg/iptables"
-	"github.com/docker/docker/pkg/networkfs/resolvconf"
-	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/libcontainer/netlink"
-)
-
-const (
-	DefaultNetworkBridge     = "docker0"
-	MaxAllocatedPortAttempts = 10
-)
-
-// Network interface represents the networking stack of a container
-type networkInterface struct {
-	IP           net.IP
-	IPv6         net.IP
-	PortMappings []net.Addr // there are mappings to the host interfaces
-}
-
-type ifaces struct {
-	c map[string]*networkInterface
-	sync.Mutex
-}
-
-func (i *ifaces) Set(key string, n *networkInterface) {
-	i.Lock()
-	i.c[key] = n
-	i.Unlock()
-}
-
-func (i *ifaces) Get(key string) *networkInterface {
-	i.Lock()
-	res := i.c[key]
-	i.Unlock()
-	return res
-}
-
-var (
-	addrs = []string{
-		// Here we don't follow the convention of using the 1st IP of the range for the gateway.
-		// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
-		// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
-		// on the internal addressing or other stupid things like that.
-		// They shouldn't, but hey, let's not break them unless we really have to.
-		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
-		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
-		"10.1.42.1/16",
-		"10.42.42.1/16",
-		"172.16.42.1/24",
-		"172.16.43.1/24",
-		"172.16.44.1/24",
-		"10.0.42.1/24",
-		"10.0.43.1/24",
-		"192.168.42.1/24",
-		"192.168.43.1/24",
-		"192.168.44.1/24",
-	}
-
-	bridgeIface       string
-	bridgeIPv4Network *net.IPNet
-	bridgeIPv6Addr    net.IP
-	globalIPv6Network *net.IPNet
-
-	defaultBindingIP  = net.ParseIP("0.0.0.0")
-	currentInterfaces = ifaces{c: make(map[string]*networkInterface)}
-)
-
-func InitDriver(job *engine.Job) engine.Status {
-	var (
-		networkv4      *net.IPNet
-		networkv6      *net.IPNet
-		addrv4         net.Addr
-		addrsv6        []net.Addr
-		enableIPTables = job.GetenvBool("EnableIptables")
-		enableIPv6     = job.GetenvBool("EnableIPv6")
-		icc            = job.GetenvBool("InterContainerCommunication")
-		ipMasq         = job.GetenvBool("EnableIpMasq")
-		ipForward      = job.GetenvBool("EnableIpForward")
-		bridgeIP       = job.Getenv("BridgeIP")
-		bridgeIPv6     = "fe80::1/64"
-		fixedCIDR      = job.Getenv("FixedCIDR")
-		fixedCIDRv6    = job.Getenv("FixedCIDRv6")
-	)
-
-	if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
-		defaultBindingIP = net.ParseIP(defaultIP)
-	}
-
-	bridgeIface = job.Getenv("BridgeIface")
-	usingDefaultBridge := false
-	if bridgeIface == "" {
-		usingDefaultBridge = true
-		bridgeIface = DefaultNetworkBridge
-	}
-
-	addrv4, addrsv6, err := networkdriver.GetIfaceAddr(bridgeIface)
-
-	if err != nil {
-		// No Bridge existent, create one
-		// If we're not using the default bridge, fail without trying to create it
-		if !usingDefaultBridge {
-			return job.Error(err)
-		}
-
-		// If the iface is not found, try to create it
-		if err := configureBridge(bridgeIP, bridgeIPv6, enableIPv6); err != nil {
-			return job.Error(err)
-		}
-
-		addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
-		if err != nil {
-			return job.Error(err)
-		}
-
-		if fixedCIDRv6 != "" {
-			// Setting route to global IPv6 subnet
-			log.Infof("Adding route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
-			if err := netlink.AddRoute(fixedCIDRv6, "", "", bridgeIface); err != nil {
-				log.Fatalf("Could not add route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
-			}
-		}
-	} else {
-		// Bridge exists already, getting info...
-		// validate that the bridge ip matches the ip specified by BridgeIP
-		if bridgeIP != "" {
-			networkv4 = addrv4.(*net.IPNet)
-			bip, _, err := net.ParseCIDR(bridgeIP)
-			if err != nil {
-				return job.Error(err)
-			}
-			if !networkv4.IP.Equal(bip) {
-				return job.Errorf("bridge ip (%s) does not match existing bridge configuration %s", networkv4.IP, bip)
-			}
-		}
-
-		// a bridge might exist but not have any IPv6 addr associated with it yet
-		// (for example, an existing Docker installation that has only been used
-		// with IPv4 and docker0 already is set up) In that case, we can perform
-		// the bridge init for IPv6 here, else we will error out below if --ipv6=true
-		if len(addrsv6) == 0 && enableIPv6 {
-			if err := setupIPv6Bridge(bridgeIPv6); err != nil {
-				return job.Error(err)
-			}
-			// recheck addresses now that IPv6 is setup on the bridge
-			addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
-			if err != nil {
-				return job.Error(err)
-			}
-		}
-
-		// TODO: Check if route to fixedCIDRv6 is set
-	}
-
-	if enableIPv6 {
-		bip6, _, err := net.ParseCIDR(bridgeIPv6)
-		if err != nil {
-			return job.Error(err)
-		}
-		found := false
-		for _, addrv6 := range addrsv6 {
-			networkv6 = addrv6.(*net.IPNet)
-			if networkv6.IP.Equal(bip6) {
-				found = true
-				break
-			}
-		}
-		if !found {
-			return job.Errorf("bridge IPv6 does not match existing bridge configuration %s", bip6)
-		}
-	}
-
-	networkv4 = addrv4.(*net.IPNet)
-
-	if enableIPv6 {
-		if len(addrsv6) == 0 {
-			return job.Error(errors.New("IPv6 enabled but no IPv6 detected"))
-		}
-		bridgeIPv6Addr = networkv6.IP
-	}
-
-	// Configure iptables for link support
-	if enableIPTables {
-		if err := setupIPTables(addrv4, icc, ipMasq); err != nil {
-			return job.Error(err)
-		}
-
-	}
-
-	if ipForward {
-		// Enable IPv4 forwarding
-		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
-			job.Logf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
-		}
-
-		if fixedCIDRv6 != "" {
-			// Enable IPv6 forwarding
-			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
-				job.Logf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
-			}
-			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/all/forwarding", []byte{'1', '\n'}, 0644); err != nil {
-				job.Logf("WARNING: unable to enable IPv6 all forwarding: %s\n", err)
-			}
-		}
-	}
-
-	// We can always try removing the iptables
-	if err := iptables.RemoveExistingChain("DOCKER", iptables.Nat); err != nil {
-		return job.Error(err)
-	}
-
-	if enableIPTables {
-		_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
-		if err != nil {
-			return job.Error(err)
-		}
-		chain, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
-		if err != nil {
-			return job.Error(err)
-		}
-		portmapper.SetIptablesChain(chain)
-	}
-
-	bridgeIPv4Network = networkv4
-	if fixedCIDR != "" {
-		_, subnet, err := net.ParseCIDR(fixedCIDR)
-		if err != nil {
-			return job.Error(err)
-		}
-		log.Debugf("Subnet: %v", subnet)
-		if err := ipallocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil {
-			return job.Error(err)
-		}
-	}
-
-	if fixedCIDRv6 != "" {
-		_, subnet, err := net.ParseCIDR(fixedCIDRv6)
-		if err != nil {
-			return job.Error(err)
-		}
-		log.Debugf("Subnet: %v", subnet)
-		if err := ipallocator.RegisterSubnet(subnet, subnet); err != nil {
-			return job.Error(err)
-		}
-		globalIPv6Network = subnet
-	}
-
-	// Block BridgeIP in IP allocator
-	ipallocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
-
-	// https://github.com/docker/docker/issues/2768
-	job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeIPv4Network.IP)
-
-	for name, f := range map[string]engine.Handler{
-		"allocate_interface": Allocate,
-		"release_interface":  Release,
-		"allocate_port":      AllocatePort,
-		"link":               LinkContainers,
-	} {
-		if err := job.Eng.Register(name, f); err != nil {
-			return job.Error(err)
-		}
-	}
-	return engine.StatusOK
-}
-
-func setupIPTables(addr net.Addr, icc, ipmasq bool) error {
-	// Enable NAT
-
-	if ipmasq {
-		natArgs := []string{"POSTROUTING", "-t", "nat", "-s", addr.String(), "!", "-o", bridgeIface, "-j", "MASQUERADE"}
-
-		if !iptables.Exists(natArgs...) {
-			if output, err := iptables.Raw(append([]string{"-I"}, natArgs...)...); err != nil {
-				return fmt.Errorf("Unable to enable network bridge NAT: %s", err)
-			} else if len(output) != 0 {
-				return &iptables.ChainError{Chain: "POSTROUTING", Output: output}
-			}
-		}
-	}
-
-	var (
-		args       = []string{"FORWARD", "-i", bridgeIface, "-o", bridgeIface, "-j"}
-		acceptArgs = append(args, "ACCEPT")
-		dropArgs   = append(args, "DROP")
-	)
-
-	if !icc {
-		iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
-
-		if !iptables.Exists(dropArgs...) {
-			log.Debugf("Disable inter-container communication")
-			if output, err := iptables.Raw(append([]string{"-I"}, dropArgs...)...); err != nil {
-				return fmt.Errorf("Unable to prevent intercontainer communication: %s", err)
-			} else if len(output) != 0 {
-				return fmt.Errorf("Error disabling intercontainer communication: %s", output)
-			}
-		}
-	} else {
-		iptables.Raw(append([]string{"-D"}, dropArgs...)...)
-
-		if !iptables.Exists(acceptArgs...) {
-			log.Debugf("Enable inter-container communication")
-			if output, err := iptables.Raw(append([]string{"-I"}, acceptArgs...)...); err != nil {
-				return fmt.Errorf("Unable to allow intercontainer communication: %s", err)
-			} else if len(output) != 0 {
-				return fmt.Errorf("Error enabling intercontainer communication: %s", output)
-			}
-		}
-	}
-
-	// Accept all non-intercontainer outgoing packets
-	outgoingArgs := []string{"FORWARD", "-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}
-	if !iptables.Exists(outgoingArgs...) {
-		if output, err := iptables.Raw(append([]string{"-I"}, outgoingArgs...)...); err != nil {
-			return fmt.Errorf("Unable to allow outgoing packets: %s", err)
-		} else if len(output) != 0 {
-			return &iptables.ChainError{Chain: "FORWARD outgoing", Output: output}
-		}
-	}
-
-	// Accept incoming packets for existing connections
-	existingArgs := []string{"FORWARD", "-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
-
-	if !iptables.Exists(existingArgs...) {
-		if output, err := iptables.Raw(append([]string{"-I"}, existingArgs...)...); err != nil {
-			return fmt.Errorf("Unable to allow incoming packets: %s", err)
-		} else if len(output) != 0 {
-			return &iptables.ChainError{Chain: "FORWARD incoming", Output: output}
-		}
-	}
-	return nil
-}
-
-// configureBridge attempts to create and configure a network bridge interface named `bridgeIface` on the host
-// If bridgeIP is empty, it will try to find a non-conflicting IP from the Docker-specified private ranges
-// If the bridge `bridgeIface` already exists, it will only perform the IP address association with the existing
-// bridge (fixes issue #8444)
-// If an address which doesn't conflict with existing interfaces can't be found, an error is returned.
-func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error {
-	nameservers := []string{}
-	resolvConf, _ := resolvconf.Get()
-	// we don't check for an error here, because we don't really care
-	// if we can't read /etc/resolv.conf. So instead we skip the append
-	// if resolvConf is nil. It either doesn't exist, or we can't read it
-	// for some reason.
-	if resolvConf != nil {
-		nameservers = append(nameservers, resolvconf.GetNameserversAsCIDR(resolvConf)...)
-	}
-
-	var ifaceAddr string
-	if len(bridgeIP) != 0 {
-		_, _, err := net.ParseCIDR(bridgeIP)
-		if err != nil {
-			return err
-		}
-		ifaceAddr = bridgeIP
-	} else {
-		for _, addr := range addrs {
-			_, dockerNetwork, err := net.ParseCIDR(addr)
-			if err != nil {
-				return err
-			}
-			if err := networkdriver.CheckNameserverOverlaps(nameservers, dockerNetwork); err == nil {
-				if err := networkdriver.CheckRouteOverlaps(dockerNetwork); err == nil {
-					ifaceAddr = addr
-					break
-				} else {
-					log.Debugf("%s %s", addr, err)
-				}
-			}
-		}
-	}
-
-	if ifaceAddr == "" {
-		return fmt.Errorf("Could not find a free IP address range for interface '%s'. Please configure its address manually and run 'docker -b %s'", bridgeIface, bridgeIface)
-	}
-	log.Debugf("Creating bridge %s with network %s", bridgeIface, ifaceAddr)
-
-	if err := createBridgeIface(bridgeIface); err != nil {
-		// the bridge may already exist, therefore we can ignore an "exists" error
-		if !os.IsExist(err) {
-			return err
-		}
-	}
-
-	iface, err := net.InterfaceByName(bridgeIface)
-	if err != nil {
-		return err
-	}
-
-	ipAddr, ipNet, err := net.ParseCIDR(ifaceAddr)
-	if err != nil {
-		return err
-	}
-
-	if err := netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
-		return fmt.Errorf("Unable to add private network: %s", err)
-	}
-
-	if enableIPv6 {
-		if err := setupIPv6Bridge(bridgeIPv6); err != nil {
-			return err
-		}
-	}
-
-	if err := netlink.NetworkLinkUp(iface); err != nil {
-		return fmt.Errorf("Unable to start network bridge: %s", err)
-	}
-	return nil
-}
-
-func setupIPv6Bridge(bridgeIPv6 string) error {
-
-	iface, err := net.InterfaceByName(bridgeIface)
-	if err != nil {
-		return err
-	}
-	// Enable IPv6 on the bridge
-	procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
-	if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
-		return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
-	}
-
-	ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
-	if err != nil {
-		return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
-	}
-
-	if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
-		return fmt.Errorf("Unable to add private IPv6 network: %v", err)
-	}
-
-	return nil
-}
-
-func createBridgeIface(name string) error {
-	kv, err := kernel.GetKernelVersion()
-	// only set the bridge's mac address if the kernel version is > 3.3
-	// before that it was not supported
-	setBridgeMacAddr := err == nil && (kv.Kernel >= 3 && kv.Major >= 3)
-	log.Debugf("setting bridge mac address = %v", setBridgeMacAddr)
-	return netlink.CreateBridge(name, setBridgeMacAddr)
-}
-
-// Generate a IEEE802 compliant MAC address from the given IP address.
-//
-// The generator is guaranteed to be consistent: the same IP will always yield the same
-// MAC address. This is to avoid ARP cache issues.
-func generateMacAddr(ip net.IP) net.HardwareAddr {
-	hw := make(net.HardwareAddr, 6)
-
-	// The first byte of the MAC address has to comply with these rules:
-	// 1. Unicast: Set the least-significant bit to 0.
-	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
-	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
-	hw[0] = 0x02
-
-	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
-	// Since this address is locally administered, we can do whatever we want as long as
-	// it doesn't conflict with other addresses.
-	hw[1] = 0x42
-
-	// Insert the IP address into the last 32 bits of the MAC address.
-	// This is a simple way to guarantee the address will be consistent and unique.
-	copy(hw[2:], ip.To4())
-
-	return hw
-}
-
-func linkLocalIPv6FromMac(mac string) (string, error) {
-	hx := strings.Replace(mac, ":", "", -1)
-	hw, err := hex.DecodeString(hx)
-	if err != nil {
-		return "", errors.New("Could not parse MAC address " + mac)
-	}
-
-	hw[0] ^= 0x2
-
-	return fmt.Sprintf("fe80::%x%x:%xff:fe%x:%x%x/64", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]), nil
-}
-
-// Allocate a network interface
-func Allocate(job *engine.Job) engine.Status {
-	var (
-		ip            net.IP
-		mac           net.HardwareAddr
-		err           error
-		id            = job.Args[0]
-		requestedIP   = net.ParseIP(job.Getenv("RequestedIP"))
-		requestedIPv6 = net.ParseIP(job.Getenv("RequestedIPv6"))
-		globalIPv6    net.IP
-	)
-
-	if requestedIP != nil {
-		ip, err = ipallocator.RequestIP(bridgeIPv4Network, requestedIP)
-	} else {
-		ip, err = ipallocator.RequestIP(bridgeIPv4Network, nil)
-	}
-	if err != nil {
-		return job.Error(err)
-	}
-
-	// If no explicit mac address was given, generate a random one.
-	if mac, err = net.ParseMAC(job.Getenv("RequestedMac")); err != nil {
-		mac = generateMacAddr(ip)
-	}
-
-	if globalIPv6Network != nil {
-		// if globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
-		netmask_ones, _ := globalIPv6Network.Mask.Size()
-		if requestedIPv6 == nil && netmask_ones <= 80 {
-			requestedIPv6 = globalIPv6Network.IP
-			for i, h := range mac {
-				requestedIPv6[i+10] = h
-			}
-		}
-
-		globalIPv6, err = ipallocator.RequestIP(globalIPv6Network, requestedIPv6)
-		if err != nil {
-			log.Errorf("Allocator: RequestIP v6: %s", err.Error())
-			return job.Error(err)
-		}
-		log.Infof("Allocated IPv6 %s", globalIPv6)
-	}
-
-	out := engine.Env{}
-	out.Set("IP", ip.String())
-	out.Set("Mask", bridgeIPv4Network.Mask.String())
-	out.Set("Gateway", bridgeIPv4Network.IP.String())
-	out.Set("MacAddress", mac.String())
-	out.Set("Bridge", bridgeIface)
-
-	size, _ := bridgeIPv4Network.Mask.Size()
-	out.SetInt("IPPrefixLen", size)
-
-	// if linklocal IPv6
-	localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
-	if err != nil {
-		return job.Error(err)
-	}
-	localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
-	out.Set("LinkLocalIPv6", localIPv6.String())
-	out.Set("MacAddress", mac.String())
-
-	if globalIPv6Network != nil {
-		out.Set("GlobalIPv6", globalIPv6.String())
-		sizev6, _ := globalIPv6Network.Mask.Size()
-		out.SetInt("GlobalIPv6PrefixLen", sizev6)
-		out.Set("IPv6Gateway", bridgeIPv6Addr.String())
-	}
-
-	currentInterfaces.Set(id, &networkInterface{
-		IP:   ip,
-		IPv6: globalIPv6,
-	})
-
-	out.WriteTo(job.Stdout)
-
-	return engine.StatusOK
-}
-
-// release an interface for a select ip
-func Release(job *engine.Job) engine.Status {
-	var (
-		id                 = job.Args[0]
-		containerInterface = currentInterfaces.Get(id)
-	)
-
-	if containerInterface == nil {
-		return job.Errorf("No network information to release for %s", id)
-	}
-
-	for _, nat := range containerInterface.PortMappings {
-		if err := portmapper.Unmap(nat); err != nil {
-			log.Infof("Unable to unmap port %s: %s", nat, err)
-		}
-	}
-
-	if err := ipallocator.ReleaseIP(bridgeIPv4Network, containerInterface.IP); err != nil {
-		log.Infof("Unable to release IPv4 %s", err)
-	}
-	if globalIPv6Network != nil {
-		if err := ipallocator.ReleaseIP(globalIPv6Network, containerInterface.IPv6); err != nil {
-			log.Infof("Unable to release IPv6 %s", err)
-		}
-	}
-	return engine.StatusOK
-}
-
-// Allocate an external port and map it to the interface
-func AllocatePort(job *engine.Job) engine.Status {
-	var (
-		err error
-
-		ip            = defaultBindingIP
-		id            = job.Args[0]
-		hostIP        = job.Getenv("HostIP")
-		hostPort      = job.GetenvInt("HostPort")
-		containerPort = job.GetenvInt("ContainerPort")
-		proto         = job.Getenv("Proto")
-		network       = currentInterfaces.Get(id)
-	)
-
-	if hostIP != "" {
-		ip = net.ParseIP(hostIP)
-		if ip == nil {
-			return job.Errorf("Bad parameter: invalid host ip %s", hostIP)
-		}
-	}
-
-	// host ip, proto, and host port
-	var container net.Addr
-	switch proto {
-	case "tcp":
-		container = &net.TCPAddr{IP: network.IP, Port: containerPort}
-	case "udp":
-		container = &net.UDPAddr{IP: network.IP, Port: containerPort}
-	default:
-		return job.Errorf("unsupported address type %s", proto)
-	}
-
-	//
-	// Try up to 10 times to get a port that's not already allocated.
-	//
-	// In the event of failure to bind, return the error that portmapper.Map
-	// yields.
-	//
-
-	var host net.Addr
-	for i := 0; i < MaxAllocatedPortAttempts; i++ {
-		if host, err = portmapper.Map(container, ip, hostPort); err == nil {
-			break
-		}
-		// There is no point in immediately retrying to map an explicitly
-		// chosen port.
-		if hostPort != 0 {
-			job.Logf("Failed to allocate and map port %d: %s", hostPort, err)
-			break
-		}
-		job.Logf("Failed to allocate and map port: %s, retry: %d", err, i+1)
-	}
-
-	if err != nil {
-		return job.Error(err)
-	}
-
-	network.PortMappings = append(network.PortMappings, host)
-
-	out := engine.Env{}
-	switch netAddr := host.(type) {
-	case *net.TCPAddr:
-		out.Set("HostIP", netAddr.IP.String())
-		out.SetInt("HostPort", netAddr.Port)
-	case *net.UDPAddr:
-		out.Set("HostIP", netAddr.IP.String())
-		out.SetInt("HostPort", netAddr.Port)
-	}
-	if _, err := out.WriteTo(job.Stdout); err != nil {
-		return job.Error(err)
-	}
-
-	return engine.StatusOK
-}
-
-func LinkContainers(job *engine.Job) engine.Status {
-	var (
-		action       = job.Args[0]
-		nfAction     iptables.Action
-		childIP      = job.Getenv("ChildIP")
-		parentIP     = job.Getenv("ParentIP")
-		ignoreErrors = job.GetenvBool("IgnoreErrors")
-		ports        = job.GetenvList("Ports")
-	)
-
-	switch action {
-	case "-A":
-		nfAction = iptables.Append
-	case "-I":
-		nfAction = iptables.Insert
-	case "-D":
-		nfAction = iptables.Delete
-	default:
-		return job.Errorf("Invalid action '%s' specified", action)
-	}
-
-	ip1 := net.ParseIP(parentIP)
-	if ip1 == nil {
-		return job.Errorf("parent IP '%s' is invalid", parentIP)
-	}
-	ip2 := net.ParseIP(childIP)
-	if ip2 == nil {
-		return job.Errorf("child IP '%s' is invalid", childIP)
-	}
-
-	chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
-	for _, p := range ports {
-		port := nat.Port(p)
-		if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
-			return job.Error(err)
-		}
-	}
-	return engine.StatusOK
-}

+ 0 - 161
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver_test.go

@@ -1,161 +0,0 @@
-package bridge
-
-import (
-	"net"
-	"strconv"
-	"testing"
-
-	"github.com/docker/docker/daemon/networkdriver/portmapper"
-	"github.com/docker/docker/engine"
-	"github.com/docker/docker/pkg/iptables"
-)
-
-func init() {
-	// reset the new proxy command for mocking out the userland proxy in tests
-	portmapper.NewProxy = portmapper.NewMockProxyCommand
-}
-
-func findFreePort(t *testing.T) int {
-	l, err := net.Listen("tcp", ":0")
-	if err != nil {
-		t.Fatal("Failed to find a free port")
-	}
-	defer l.Close()
-
-	result, err := net.ResolveTCPAddr("tcp", l.Addr().String())
-	if err != nil {
-		t.Fatal("Failed to resolve address to identify free port")
-	}
-	return result.Port
-}
-
-func newPortAllocationJob(eng *engine.Engine, port int) (job *engine.Job) {
-	strPort := strconv.Itoa(port)
-
-	job = eng.Job("allocate_port", "container_id")
-	job.Setenv("HostIP", "127.0.0.1")
-	job.Setenv("HostPort", strPort)
-	job.Setenv("Proto", "tcp")
-	job.Setenv("ContainerPort", strPort)
-	return
-}
-
-func newPortAllocationJobWithInvalidHostIP(eng *engine.Engine, port int) (job *engine.Job) {
-	strPort := strconv.Itoa(port)
-
-	job = eng.Job("allocate_port", "container_id")
-	job.Setenv("HostIP", "localhost")
-	job.Setenv("HostPort", strPort)
-	job.Setenv("Proto", "tcp")
-	job.Setenv("ContainerPort", strPort)
-	return
-}
-
-func TestAllocatePortDetection(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
-	freePort := findFreePort(t)
-
-	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != engine.StatusOK {
-		t.Fatal("Failed to initialize network driver")
-	}
-
-	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != engine.StatusOK {
-		t.Fatal("Failed to allocate network interface")
-	}
-
-	// Allocate same port twice, expect failure on second call
-	job = newPortAllocationJob(eng, freePort)
-	if res := AllocatePort(job); res != engine.StatusOK {
-		t.Fatal("Failed to find a free port to allocate")
-	}
-	if res := AllocatePort(job); res == engine.StatusOK {
-		t.Fatal("Duplicate port allocation granted by AllocatePort")
-	}
-}
-
-func TestHostnameFormatChecking(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
-	freePort := findFreePort(t)
-
-	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != engine.StatusOK {
-		t.Fatal("Failed to initialize network driver")
-	}
-
-	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != engine.StatusOK {
-		t.Fatal("Failed to allocate network interface")
-	}
-
-	// Allocate port with invalid HostIP, expect failure with Bad Request http status
-	job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
-	if res := AllocatePort(job); res == engine.StatusOK {
-		t.Fatal("Failed to check invalid HostIP")
-	}
-}
-
-func TestMacAddrGeneration(t *testing.T) {
-	ip := net.ParseIP("192.168.0.1")
-	mac := generateMacAddr(ip).String()
-
-	// Should be consistent.
-	if generateMacAddr(ip).String() != mac {
-		t.Fatal("Inconsistent MAC address")
-	}
-
-	// Should be unique.
-	ip2 := net.ParseIP("192.168.0.2")
-	if generateMacAddr(ip2).String() == mac {
-		t.Fatal("Non-unique MAC address")
-	}
-}
-
-func TestLinkContainers(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
-	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != engine.StatusOK {
-		t.Fatal("Failed to initialize network driver")
-	}
-
-	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != engine.StatusOK {
-		t.Fatal("Failed to allocate network interface")
-	}
-
-	job.Args[0] = "-I"
-
-	job.Setenv("ChildIP", "172.17.0.2")
-	job.Setenv("ParentIP", "172.17.0.1")
-	job.SetenvBool("IgnoreErrors", false)
-	job.SetenvList("Ports", []string{"1234"})
-
-	bridgeIface = "lo"
-	_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if res := LinkContainers(job); res != engine.StatusOK {
-		t.Fatalf("LinkContainers failed")
-	}
-
-	// flush rules
-	if _, err = iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
-		t.Fatal(err)
-	}
-
-}

+ 0 - 160
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator.go

@@ -1,160 +0,0 @@
-package ipallocator
-
-import (
-	"errors"
-	"math/big"
-	"net"
-	"sync"
-
-	log "github.com/Sirupsen/logrus"
-	"github.com/docker/docker/daemon/networkdriver"
-)
-
-// allocatedMap is thread-unsafe set of allocated IP
-type allocatedMap struct {
-	p     map[string]struct{}
-	last  *big.Int
-	begin *big.Int
-	end   *big.Int
-}
-
-func newAllocatedMap(network *net.IPNet) *allocatedMap {
-	firstIP, lastIP := networkdriver.NetworkRange(network)
-	begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
-	end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1))
-
-	return &allocatedMap{
-		p:     make(map[string]struct{}),
-		begin: begin,
-		end:   end,
-		last:  big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin
-	}
-}
-
-type networkSet map[string]*allocatedMap
-
-var (
-	ErrNoAvailableIPs           = errors.New("no available ip addresses on network")
-	ErrIPAlreadyAllocated       = errors.New("ip already allocated")
-	ErrIPOutOfRange             = errors.New("requested ip is out of range")
-	ErrNetworkAlreadyRegistered = errors.New("network already registered")
-	ErrBadSubnet                = errors.New("network does not contain specified subnet")
-)
-
-var (
-	lock         = sync.Mutex{}
-	allocatedIPs = networkSet{}
-)
-
-// RegisterSubnet registers network in global allocator with bounds
-// defined by subnet. If you want to use network range you must call
-// this method before first RequestIP, otherwise full network range will be used
-func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
-	lock.Lock()
-	defer lock.Unlock()
-	key := network.String()
-	if _, ok := allocatedIPs[key]; ok {
-		return ErrNetworkAlreadyRegistered
-	}
-	n := newAllocatedMap(network)
-	beginIP, endIP := networkdriver.NetworkRange(subnet)
-	begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1))
-	end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1))
-
-	// Check that subnet is within network
-	if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) {
-		return ErrBadSubnet
-	}
-	n.begin.Set(begin)
-	n.end.Set(end)
-	n.last.Sub(begin, big.NewInt(1))
-	allocatedIPs[key] = n
-	return nil
-}
-
-// RequestIP requests an available ip from the given network.  It
-// will return the next available ip if the ip provided is nil.  If the
-// ip provided is not nil it will validate that the provided ip is available
-// for use or return an error
-func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
-	lock.Lock()
-	defer lock.Unlock()
-	key := network.String()
-	allocated, ok := allocatedIPs[key]
-	if !ok {
-		allocated = newAllocatedMap(network)
-		allocatedIPs[key] = allocated
-	}
-
-	if ip == nil {
-		return allocated.getNextIP()
-	}
-	return allocated.checkIP(ip)
-}
-
-// ReleaseIP adds the provided ip back into the pool of
-// available ips to be returned for use.
-func ReleaseIP(network *net.IPNet, ip net.IP) error {
-	lock.Lock()
-	defer lock.Unlock()
-	if allocated, exists := allocatedIPs[network.String()]; exists {
-		delete(allocated.p, ip.String())
-	}
-	return nil
-}
-
-func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
-	if _, ok := allocated.p[ip.String()]; ok {
-		return nil, ErrIPAlreadyAllocated
-	}
-
-	pos := ipToBigInt(ip)
-	// Verify that the IP address is within our network range.
-	if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
-		return nil, ErrIPOutOfRange
-	}
-
-	// Register the IP.
-	allocated.p[ip.String()] = struct{}{}
-
-	return ip, nil
-}
-
-// return an available ip if one is currently available.  If not,
-// return the next available ip for the nextwork
-func (allocated *allocatedMap) getNextIP() (net.IP, error) {
-	pos := big.NewInt(0).Set(allocated.last)
-	allRange := big.NewInt(0).Sub(allocated.end, allocated.begin)
-	for i := big.NewInt(0); i.Cmp(allRange) <= 0; i.Add(i, big.NewInt(1)) {
-		pos.Add(pos, big.NewInt(1))
-		if pos.Cmp(allocated.end) == 1 {
-			pos.Set(allocated.begin)
-		}
-		if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
-			continue
-		}
-		allocated.p[bigIntToIP(pos).String()] = struct{}{}
-		allocated.last.Set(pos)
-		return bigIntToIP(pos), nil
-	}
-	return nil, ErrNoAvailableIPs
-}
-
-// Converts a 4 bytes IP into a 128 bit integer
-func ipToBigInt(ip net.IP) *big.Int {
-	x := big.NewInt(0)
-	if ip4 := ip.To4(); ip4 != nil {
-		return x.SetBytes(ip4)
-	}
-	if ip6 := ip.To16(); ip6 != nil {
-		return x.SetBytes(ip6)
-	}
-
-	log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
-	return nil
-}
-
-// Converts 128 bit integer into a 4 bytes IP address
-func bigIntToIP(v *big.Int) net.IP {
-	return net.IP(v.Bytes())
-}

+ 0 - 681
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator_test.go

@@ -1,681 +0,0 @@
-package ipallocator
-
-import (
-	"fmt"
-	"math/big"
-	"net"
-	"testing"
-)
-
-func reset() {
-	allocatedIPs = networkSet{}
-}
-
-func TestConversion(t *testing.T) {
-	ip := net.ParseIP("127.0.0.1")
-	i := ipToBigInt(ip)
-	if i.Cmp(big.NewInt(0x7f000001)) != 0 {
-		t.Fatal("incorrect conversion")
-	}
-	conv := bigIntToIP(i)
-	if !ip.Equal(conv) {
-		t.Error(conv.String())
-	}
-}
-
-func TestConversionIPv6(t *testing.T) {
-	ip := net.ParseIP("2a00:1450::1")
-	ip2 := net.ParseIP("2a00:1450::2")
-	ip3 := net.ParseIP("2a00:1450::1:1")
-	i := ipToBigInt(ip)
-	val, success := big.NewInt(0).SetString("2a001450000000000000000000000001", 16)
-	if !success {
-		t.Fatal("Hex-String to BigInt conversion failed.")
-	}
-	if i.Cmp(val) != 0 {
-		t.Fatal("incorrent conversion")
-	}
-
-	conv := bigIntToIP(i)
-	conv2 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(1)))
-	conv3 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(0x10000)))
-
-	if !ip.Equal(conv) {
-		t.Error("2a00:1450::1 should be equal to " + conv.String())
-	}
-	if !ip2.Equal(conv2) {
-		t.Error("2a00:1450::2 should be equal to " + conv2.String())
-	}
-	if !ip3.Equal(conv3) {
-		t.Error("2a00:1450::1:1 should be equal to " + conv3.String())
-	}
-}
-
-func TestRequestNewIps(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-
-	var ip net.IP
-	var err error
-
-	for i := 1; i < 10; i++ {
-		ip, err = RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if expected := fmt.Sprintf("192.168.0.%d", i); ip.String() != expected {
-			t.Fatalf("Expected ip %s got %s", expected, ip.String())
-		}
-	}
-	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-	ip, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if ip.String() != value {
-		t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
-	}
-}
-
-func TestRequestNewIpV6(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
-	}
-
-	var ip net.IP
-	var err error
-	for i := 1; i < 10; i++ {
-		ip, err = RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if expected := fmt.Sprintf("2a00:1450::%d", i); ip.String() != expected {
-			t.Fatalf("Expected ip %s got %s", expected, ip.String())
-		}
-	}
-	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-	ip, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if ip.String() != value {
-		t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
-	}
-}
-
-func TestReleaseIp(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-
-	ip, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestReleaseIpV6(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
-	}
-
-	ip, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestGetReleasedIp(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-
-	ip, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	value := ip.String()
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-
-	for i := 0; i < 253; i++ {
-		_, err = RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		err = ReleaseIP(network, ip)
-		if err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	ip, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if ip.String() != value {
-		t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
-	}
-}
-
-func TestGetReleasedIpV6(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
-	}
-
-	ip, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	value := ip.String()
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-
-	for i := 0; i < 253; i++ {
-		_, err = RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		err = ReleaseIP(network, ip)
-		if err != nil {
-			t.Fatal(err)
-		}
-	}
-
-	ip, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if ip.String() != value {
-		t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
-	}
-}
-
-func TestRequestSpecificIp(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 224},
-	}
-
-	ip := net.ParseIP("192.168.0.5")
-
-	// Request a "good" IP.
-	if _, err := RequestIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-
-	// Request the same IP again.
-	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
-		t.Fatalf("Got the same IP twice: %#v", err)
-	}
-
-	// Request an out of range IP.
-	if _, err := RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
-		t.Fatalf("Got an out of range IP: %#v", err)
-	}
-}
-
-func TestRequestSpecificIpV6(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
-	}
-
-	ip := net.ParseIP("2a00:1450::5")
-
-	// Request a "good" IP.
-	if _, err := RequestIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-
-	// Request the same IP again.
-	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
-		t.Fatalf("Got the same IP twice: %#v", err)
-	}
-
-	// Request an out of range IP.
-	if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
-		t.Fatalf("Got an out of range IP: %#v", err)
-	}
-}
-
-func TestIPAllocator(t *testing.T) {
-	expectedIPs := []net.IP{
-		0: net.IPv4(127, 0, 0, 1),
-		1: net.IPv4(127, 0, 0, 2),
-		2: net.IPv4(127, 0, 0, 3),
-		3: net.IPv4(127, 0, 0, 4),
-		4: net.IPv4(127, 0, 0, 5),
-		5: net.IPv4(127, 0, 0, 6),
-	}
-
-	gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
-
-	network := &net.IPNet{IP: gwIP, Mask: n.Mask}
-	// Pool after initialisation (f = free, u = used)
-	// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
-	//  ↑
-
-	// Check that we get 6 IPs, from 127.0.0.1–127.0.0.6, in that
-	// order.
-	for i := 0; i < 6; i++ {
-		ip, err := RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		assertIPEquals(t, expectedIPs[i], ip)
-	}
-	// Before loop begin
-	// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
-	//  ↑
-
-	// After i = 0
-	// 1(u) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
-	//         ↑
-
-	// After i = 1
-	// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(f)
-	//                ↑
-
-	// After i = 2
-	// 1(u) - 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
-	//                       ↑
-
-	// After i = 3
-	// 1(u) - 2(u) - 3(u) - 4(u) - 5(f) - 6(f)
-	//                              ↑
-
-	// After i = 4
-	// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(f)
-	//                                     ↑
-
-	// After i = 5
-	// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
-	//  ↑
-
-	// Check that there are no more IPs
-	ip, err := RequestIP(network, nil)
-	if err == nil {
-		t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
-	}
-
-	// Release some IPs in non-sequential order
-	if err := ReleaseIP(network, expectedIPs[3]); err != nil {
-		t.Fatal(err)
-	}
-	// 1(u) - 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
-	//                       ↑
-
-	if err := ReleaseIP(network, expectedIPs[2]); err != nil {
-		t.Fatal(err)
-	}
-	// 1(u) - 2(u) - 3(f) - 4(f) - 5(u) - 6(u)
-	//                ↑
-
-	if err := ReleaseIP(network, expectedIPs[4]); err != nil {
-		t.Fatal(err)
-	}
-	// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(u)
-	//                              ↑
-
-	// Make sure that IPs are reused in sequential order, starting
-	// with the first released IP
-	newIPs := make([]net.IP, 3)
-	for i := 0; i < 3; i++ {
-		ip, err := RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		newIPs[i] = ip
-	}
-	assertIPEquals(t, expectedIPs[2], newIPs[0])
-	assertIPEquals(t, expectedIPs[3], newIPs[1])
-	assertIPEquals(t, expectedIPs[4], newIPs[2])
-
-	_, err = RequestIP(network, nil)
-	if err == nil {
-		t.Fatal("There shouldn't be any IP addresses at this point")
-	}
-}
-
-func TestAllocateFirstIP(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 0},
-		Mask: []byte{255, 255, 255, 0},
-	}
-
-	firstIP := network.IP.To4().Mask(network.Mask)
-	first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
-
-	ip, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	allocated := ipToBigInt(ip)
-
-	if allocated == first {
-		t.Fatalf("allocated ip should not equal first ip: %d == %d", first, allocated)
-	}
-}
-
-func TestAllocateAllIps(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-
-	var (
-		current, first net.IP
-		err            error
-		isFirst        = true
-	)
-
-	for err == nil {
-		current, err = RequestIP(network, nil)
-		if isFirst {
-			first = current
-			isFirst = false
-		}
-	}
-
-	if err != ErrNoAvailableIPs {
-		t.Fatal(err)
-	}
-
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
-		t.Fatal(err)
-	}
-
-	if err := ReleaseIP(network, first); err != nil {
-		t.Fatal(err)
-	}
-
-	again, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assertIPEquals(t, first, again)
-
-	// ensure that alloc.last == alloc.begin won't result in dead loop
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
-		t.Fatal(err)
-	}
-
-	// Test by making alloc.last the only free ip and ensure we get it back
-	// #1. first of the range, (alloc.last == ipToInt(first) already)
-	if err := ReleaseIP(network, first); err != nil {
-		t.Fatal(err)
-	}
-
-	ret, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assertIPEquals(t, first, ret)
-
-	// #2. last of the range, note that current is the last one
-	last := net.IPv4(192, 168, 0, 254)
-	setLastTo(t, network, last)
-
-	ret, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assertIPEquals(t, last, ret)
-
-	// #3. middle of the range
-	mid := net.IPv4(192, 168, 0, 7)
-	setLastTo(t, network, mid)
-
-	ret, err = RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assertIPEquals(t, mid, ret)
-}
-
-// make sure the pool is full when calling setLastTo.
-// we don't cheat here
-func setLastTo(t *testing.T, network *net.IPNet, ip net.IP) {
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-
-	ret, err := RequestIP(network, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assertIPEquals(t, ip, ret)
-
-	if err := ReleaseIP(network, ip); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestAllocateDifferentSubnets(t *testing.T) {
-	defer reset()
-	network1 := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	network2 := &net.IPNet{
-		IP:   []byte{127, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	network3 := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
-	}
-	network4 := &net.IPNet{
-		IP:   []byte{0x2a, 0x00, 0x16, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
-		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
-	}
-	expectedIPs := []net.IP{
-		0: net.IPv4(192, 168, 0, 1),
-		1: net.IPv4(192, 168, 0, 2),
-		2: net.IPv4(127, 0, 0, 1),
-		3: net.IPv4(127, 0, 0, 2),
-		4: net.ParseIP("2a00:1450::1"),
-		5: net.ParseIP("2a00:1450::2"),
-		6: net.ParseIP("2a00:1450::3"),
-		7: net.ParseIP("2a00:1632::1"),
-		8: net.ParseIP("2a00:1632::2"),
-	}
-
-	ip11, err := RequestIP(network1, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip12, err := RequestIP(network1, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip21, err := RequestIP(network2, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip22, err := RequestIP(network2, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip31, err := RequestIP(network3, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip32, err := RequestIP(network3, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip33, err := RequestIP(network3, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip41, err := RequestIP(network4, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ip42, err := RequestIP(network4, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	assertIPEquals(t, expectedIPs[0], ip11)
-	assertIPEquals(t, expectedIPs[1], ip12)
-	assertIPEquals(t, expectedIPs[2], ip21)
-	assertIPEquals(t, expectedIPs[3], ip22)
-	assertIPEquals(t, expectedIPs[4], ip31)
-	assertIPEquals(t, expectedIPs[5], ip32)
-	assertIPEquals(t, expectedIPs[6], ip33)
-	assertIPEquals(t, expectedIPs[7], ip41)
-	assertIPEquals(t, expectedIPs[8], ip42)
-}
-
-func TestRegisterBadTwice(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 1, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	subnet := &net.IPNet{
-		IP:   []byte{192, 168, 1, 8},
-		Mask: []byte{255, 255, 255, 248},
-	}
-
-	if err := RegisterSubnet(network, subnet); err != nil {
-		t.Fatal(err)
-	}
-	subnet = &net.IPNet{
-		IP:   []byte{192, 168, 1, 16},
-		Mask: []byte{255, 255, 255, 248},
-	}
-	if err := RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
-		t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err)
-	}
-}
-
-func TestRegisterBadRange(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 1, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	subnet := &net.IPNet{
-		IP:   []byte{192, 168, 1, 1},
-		Mask: []byte{255, 255, 0, 0},
-	}
-	if err := RegisterSubnet(network, subnet); err != ErrBadSubnet {
-		t.Fatalf("Expected ErrBadSubnet error, got %v", err)
-	}
-}
-
-func TestAllocateFromRange(t *testing.T) {
-	defer reset()
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	// 192.168.1.9 - 192.168.1.14
-	subnet := &net.IPNet{
-		IP:   []byte{192, 168, 0, 8},
-		Mask: []byte{255, 255, 255, 248},
-	}
-
-	if err := RegisterSubnet(network, subnet); err != nil {
-		t.Fatal(err)
-	}
-	expectedIPs := []net.IP{
-		0: net.IPv4(192, 168, 0, 9),
-		1: net.IPv4(192, 168, 0, 10),
-		2: net.IPv4(192, 168, 0, 11),
-		3: net.IPv4(192, 168, 0, 12),
-		4: net.IPv4(192, 168, 0, 13),
-		5: net.IPv4(192, 168, 0, 14),
-	}
-	for _, ip := range expectedIPs {
-		rip, err := RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		assertIPEquals(t, ip, rip)
-	}
-
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
-		t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err)
-	}
-	for _, ip := range expectedIPs {
-		ReleaseIP(network, ip)
-		rip, err := RequestIP(network, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		assertIPEquals(t, ip, rip)
-	}
-}
-
-func assertIPEquals(t *testing.T, ip1, ip2 net.IP) {
-	if !ip1.Equal(ip2) {
-		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
-	}
-}
-
-func BenchmarkRequestIP(b *testing.B) {
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		for j := 0; j < 253; j++ {
-			_, err := RequestIP(network, nil)
-			if err != nil {
-				b.Fatal(err)
-			}
-		}
-		reset()
-	}
-}

+ 0 - 10
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network.go

@@ -1,10 +0,0 @@
-package networkdriver
-
-import (
-	"errors"
-)
-
-var (
-	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
-	ErrNetworkOverlaps                = errors.New("requested network overlaps with existing network")
-)

+ 0 - 175
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network_test.go

@@ -1,175 +0,0 @@
-package networkdriver
-
-import (
-	"github.com/docker/libcontainer/netlink"
-	"net"
-	"testing"
-)
-
-func TestNonOverlapingNameservers(t *testing.T) {
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	nameservers := []string{
-		"127.0.0.1/32",
-	}
-
-	if err := CheckNameserverOverlaps(nameservers, network); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestOverlapingNameservers(t *testing.T) {
-	network := &net.IPNet{
-		IP:   []byte{192, 168, 0, 1},
-		Mask: []byte{255, 255, 255, 0},
-	}
-	nameservers := []string{
-		"192.168.0.1/32",
-	}
-
-	if err := CheckNameserverOverlaps(nameservers, network); err == nil {
-		t.Fatalf("Expected error %s got %s", ErrNetworkOverlapsWithNameservers, err)
-	}
-}
-
-func TestCheckRouteOverlaps(t *testing.T) {
-	orig := networkGetRoutesFct
-	defer func() {
-		networkGetRoutesFct = orig
-	}()
-	networkGetRoutesFct = func() ([]netlink.Route, error) {
-		routesData := []string{"10.0.2.0/32", "10.0.3.0/24", "10.0.42.0/24", "172.16.42.0/24", "192.168.142.0/24"}
-
-		routes := []netlink.Route{}
-		for _, addr := range routesData {
-			_, netX, _ := net.ParseCIDR(addr)
-			routes = append(routes, netlink.Route{IPNet: netX})
-		}
-		return routes, nil
-	}
-
-	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
-	if err := CheckRouteOverlaps(netX); err != nil {
-		t.Fatal(err)
-	}
-
-	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
-	if err := CheckRouteOverlaps(netX); err == nil {
-		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
-	}
-}
-
-func TestCheckNameserverOverlaps(t *testing.T) {
-	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
-
-	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
-
-	if err := CheckNameserverOverlaps(nameservers, netX); err == nil {
-		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
-	}
-
-	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
-
-	if err := CheckNameserverOverlaps(nameservers, netX); err != nil {
-		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
-	}
-}
-
-func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
-	_, netX, _ := net.ParseCIDR(CIDRx)
-	_, netY, _ := net.ParseCIDR(CIDRy)
-	if !NetworkOverlaps(netX, netY) {
-		t.Errorf("%v and %v should overlap", netX, netY)
-	}
-}
-
-func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
-	_, netX, _ := net.ParseCIDR(CIDRx)
-	_, netY, _ := net.ParseCIDR(CIDRy)
-	if NetworkOverlaps(netX, netY) {
-		t.Errorf("%v and %v should not overlap", netX, netY)
-	}
-}
-
-func TestNetworkOverlaps(t *testing.T) {
-	//netY starts at same IP and ends within netX
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
-	//netY starts within netX and ends at same IP
-	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
-	//netY starts and ends within netX
-	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
-	//netY starts at same IP and ends outside of netX
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
-	//netY starts before and ends at same IP of netX
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
-	//netY starts before and ends outside of netX
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/22", t)
-	//netY starts and ends before netX
-	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
-	//netX starts and ends before netY
-	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
-}
-
-func TestNetworkRange(t *testing.T) {
-	// Simple class C test
-	_, network, _ := net.ParseCIDR("192.168.0.1/24")
-	first, last := NetworkRange(network)
-	if !first.Equal(net.ParseIP("192.168.0.0")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("192.168.0.255")) {
-		t.Error(last.String())
-	}
-
-	// Class A test
-	_, network, _ = net.ParseCIDR("10.0.0.1/8")
-	first, last = NetworkRange(network)
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
-		t.Error(last.String())
-	}
-
-	// Class A, random IP address
-	_, network, _ = net.ParseCIDR("10.1.2.3/8")
-	first, last = NetworkRange(network)
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
-		t.Error(last.String())
-	}
-
-	// 32bit mask
-	_, network, _ = net.ParseCIDR("10.1.2.3/32")
-	first, last = NetworkRange(network)
-	if !first.Equal(net.ParseIP("10.1.2.3")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
-		t.Error(last.String())
-	}
-
-	// 31bit mask
-	_, network, _ = net.ParseCIDR("10.1.2.3/31")
-	first, last = NetworkRange(network)
-	if !first.Equal(net.ParseIP("10.1.2.2")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
-		t.Error(last.String())
-	}
-
-	// 26bit mask
-	_, network, _ = net.ParseCIDR("10.1.2.3/26")
-	first, last = NetworkRange(network)
-	if !first.Equal(net.ParseIP("10.1.2.0")) {
-		t.Error(first.String())
-	}
-	if !last.Equal(net.ParseIP("10.1.2.63")) {
-		t.Error(last.String())
-	}
-}

+ 0 - 153
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator.go

@@ -1,153 +0,0 @@
-package portallocator
-
-import (
-	"errors"
-	"fmt"
-	"net"
-	"sync"
-)
-
-type portMap struct {
-	p    map[int]struct{}
-	last int
-}
-
-func newPortMap() *portMap {
-	return &portMap{
-		p:    map[int]struct{}{},
-		last: EndPortRange,
-	}
-}
-
-type protoMap map[string]*portMap
-
-func newProtoMap() protoMap {
-	return protoMap{
-		"tcp": newPortMap(),
-		"udp": newPortMap(),
-	}
-}
-
-type ipMapping map[string]protoMap
-
-const (
-	BeginPortRange = 49153
-	EndPortRange   = 65535
-)
-
-var (
-	ErrAllPortsAllocated = errors.New("all ports are allocated")
-	ErrUnknownProtocol   = errors.New("unknown protocol")
-)
-
-var (
-	mutex sync.Mutex
-
-	defaultIP = net.ParseIP("0.0.0.0")
-	globalMap = ipMapping{}
-)
-
-type ErrPortAlreadyAllocated struct {
-	ip   string
-	port int
-}
-
-func NewErrPortAlreadyAllocated(ip string, port int) ErrPortAlreadyAllocated {
-	return ErrPortAlreadyAllocated{
-		ip:   ip,
-		port: port,
-	}
-}
-
-func (e ErrPortAlreadyAllocated) IP() string {
-	return e.ip
-}
-
-func (e ErrPortAlreadyAllocated) Port() int {
-	return e.port
-}
-
-func (e ErrPortAlreadyAllocated) IPPort() string {
-	return fmt.Sprintf("%s:%d", e.ip, e.port)
-}
-
-func (e ErrPortAlreadyAllocated) Error() string {
-	return fmt.Sprintf("Bind for %s:%d failed: port is already allocated", e.ip, e.port)
-}
-
-// RequestPort requests new port from global ports pool for specified ip and proto.
-// If port is 0 it returns first free port. Otherwise it cheks port availability
-// in pool and return that port or error if port is already busy.
-func RequestPort(ip net.IP, proto string, port int) (int, error) {
-	mutex.Lock()
-	defer mutex.Unlock()
-
-	if proto != "tcp" && proto != "udp" {
-		return 0, ErrUnknownProtocol
-	}
-
-	if ip == nil {
-		ip = defaultIP
-	}
-	ipstr := ip.String()
-	protomap, ok := globalMap[ipstr]
-	if !ok {
-		protomap = newProtoMap()
-		globalMap[ipstr] = protomap
-	}
-	mapping := protomap[proto]
-	if port > 0 {
-		if _, ok := mapping.p[port]; !ok {
-			mapping.p[port] = struct{}{}
-			return port, nil
-		}
-		return 0, NewErrPortAlreadyAllocated(ipstr, port)
-	}
-
-	port, err := mapping.findPort()
-	if err != nil {
-		return 0, err
-	}
-	return port, nil
-}
-
-// ReleasePort releases port from global ports pool for specified ip and proto.
-func ReleasePort(ip net.IP, proto string, port int) error {
-	mutex.Lock()
-	defer mutex.Unlock()
-
-	if ip == nil {
-		ip = defaultIP
-	}
-	protomap, ok := globalMap[ip.String()]
-	if !ok {
-		return nil
-	}
-	delete(protomap[proto].p, port)
-	return nil
-}
-
-// ReleaseAll releases all ports for all ips.
-func ReleaseAll() error {
-	mutex.Lock()
-	globalMap = ipMapping{}
-	mutex.Unlock()
-	return nil
-}
-
-func (pm *portMap) findPort() (int, error) {
-	port := pm.last
-	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
-		port++
-		if port > EndPortRange {
-			port = BeginPortRange
-		}
-
-		if _, ok := pm.p[port]; !ok {
-			pm.p[port] = struct{}{}
-			pm.last = port
-			return port, nil
-		}
-	}
-	return 0, ErrAllPortsAllocated
-}

+ 0 - 245
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator_test.go

@@ -1,245 +0,0 @@
-package portallocator
-
-import (
-	"net"
-	"testing"
-)
-
-func reset() {
-	ReleaseAll()
-}
-
-func TestRequestNewPort(t *testing.T) {
-	defer reset()
-
-	port, err := RequestPort(defaultIP, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if expected := BeginPortRange; port != expected {
-		t.Fatalf("Expected port %d got %d", expected, port)
-	}
-}
-
-func TestRequestSpecificPort(t *testing.T) {
-	defer reset()
-
-	port, err := RequestPort(defaultIP, "tcp", 5000)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port != 5000 {
-		t.Fatalf("Expected port 5000 got %d", port)
-	}
-}
-
-func TestReleasePort(t *testing.T) {
-	defer reset()
-
-	port, err := RequestPort(defaultIP, "tcp", 5000)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port != 5000 {
-		t.Fatalf("Expected port 5000 got %d", port)
-	}
-
-	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestReuseReleasedPort(t *testing.T) {
-	defer reset()
-
-	port, err := RequestPort(defaultIP, "tcp", 5000)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port != 5000 {
-		t.Fatalf("Expected port 5000 got %d", port)
-	}
-
-	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
-		t.Fatal(err)
-	}
-
-	port, err = RequestPort(defaultIP, "tcp", 5000)
-	if err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestReleaseUnreadledPort(t *testing.T) {
-	defer reset()
-
-	port, err := RequestPort(defaultIP, "tcp", 5000)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port != 5000 {
-		t.Fatalf("Expected port 5000 got %d", port)
-	}
-
-	port, err = RequestPort(defaultIP, "tcp", 5000)
-
-	switch err.(type) {
-	case ErrPortAlreadyAllocated:
-	default:
-		t.Fatalf("Expected port allocation error got %s", err)
-	}
-}
-
-func TestUnknowProtocol(t *testing.T) {
-	defer reset()
-
-	if _, err := RequestPort(defaultIP, "tcpp", 0); err != ErrUnknownProtocol {
-		t.Fatalf("Expected error %s got %s", ErrUnknownProtocol, err)
-	}
-}
-
-func TestAllocateAllPorts(t *testing.T) {
-	defer reset()
-
-	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
-		port, err := RequestPort(defaultIP, "tcp", 0)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if expected := BeginPortRange + i; port != expected {
-			t.Fatalf("Expected port %d got %d", expected, port)
-		}
-	}
-
-	if _, err := RequestPort(defaultIP, "tcp", 0); err != ErrAllPortsAllocated {
-		t.Fatalf("Expected error %s got %s", ErrAllPortsAllocated, err)
-	}
-
-	_, err := RequestPort(defaultIP, "udp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	// release a port in the middle and ensure we get another tcp port
-	port := BeginPortRange + 5
-	if err := ReleasePort(defaultIP, "tcp", port); err != nil {
-		t.Fatal(err)
-	}
-	newPort, err := RequestPort(defaultIP, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if newPort != port {
-		t.Fatalf("Expected port %d got %d", port, newPort)
-	}
-
-	// now pm.last == newPort, release it so that it's the only free port of
-	// the range, and ensure we get it back
-	if err := ReleasePort(defaultIP, "tcp", newPort); err != nil {
-		t.Fatal(err)
-	}
-	port, err = RequestPort(defaultIP, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if newPort != port {
-		t.Fatalf("Expected port %d got %d", newPort, port)
-	}
-}
-
-func BenchmarkAllocatePorts(b *testing.B) {
-	defer reset()
-
-	for i := 0; i < b.N; i++ {
-		for i := 0; i <= EndPortRange-BeginPortRange; i++ {
-			port, err := RequestPort(defaultIP, "tcp", 0)
-			if err != nil {
-				b.Fatal(err)
-			}
-
-			if expected := BeginPortRange + i; port != expected {
-				b.Fatalf("Expected port %d got %d", expected, port)
-			}
-		}
-		reset()
-	}
-}
-
-func TestPortAllocation(t *testing.T) {
-	defer reset()
-
-	ip := net.ParseIP("192.168.0.1")
-	ip2 := net.ParseIP("192.168.0.2")
-	if port, err := RequestPort(ip, "tcp", 80); err != nil {
-		t.Fatal(err)
-	} else if port != 80 {
-		t.Fatalf("Acquire(80) should return 80, not %d", port)
-	}
-	port, err := RequestPort(ip, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port <= 0 {
-		t.Fatalf("Acquire(0) should return a non-zero port")
-	}
-
-	if _, err := RequestPort(ip, "tcp", port); err == nil {
-		t.Fatalf("Acquiring a port already in use should return an error")
-	}
-
-	if newPort, err := RequestPort(ip, "tcp", 0); err != nil {
-		t.Fatal(err)
-	} else if newPort == port {
-		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
-	}
-
-	if _, err := RequestPort(ip, "tcp", 80); err == nil {
-		t.Fatalf("Acquiring a port already in use should return an error")
-	}
-	if _, err := RequestPort(ip2, "tcp", 80); err != nil {
-		t.Fatalf("It should be possible to allocate the same port on a different interface")
-	}
-	if _, err := RequestPort(ip2, "tcp", 80); err == nil {
-		t.Fatalf("Acquiring a port already in use should return an error")
-	}
-	if err := ReleasePort(ip, "tcp", 80); err != nil {
-		t.Fatal(err)
-	}
-	if _, err := RequestPort(ip, "tcp", 80); err != nil {
-		t.Fatal(err)
-	}
-
-	port, err = RequestPort(ip, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	port2, err := RequestPort(ip, "tcp", port+1)
-	if err != nil {
-		t.Fatal(err)
-	}
-	port3, err := RequestPort(ip, "tcp", 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if port3 == port2 {
-		t.Fatal("Requesting a dynamic port should never allocate a used port")
-	}
-}
-
-func TestNoDuplicateBPR(t *testing.T) {
-	defer reset()
-
-	if port, err := RequestPort(defaultIP, "tcp", BeginPortRange); err != nil {
-		t.Fatal(err)
-	} else if port != BeginPortRange {
-		t.Fatalf("Expected port %d got %d", BeginPortRange, port)
-	}
-
-	if port, err := RequestPort(defaultIP, "tcp", 0); err != nil {
-		t.Fatal(err)
-	} else if port == BeginPortRange {
-		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
-	}
-}

+ 0 - 176
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper.go

@@ -1,176 +0,0 @@
-package portmapper
-
-import (
-	"errors"
-	"fmt"
-	"net"
-	"sync"
-
-	log "github.com/Sirupsen/logrus"
-	"github.com/docker/docker/daemon/networkdriver/portallocator"
-	"github.com/docker/docker/pkg/iptables"
-)
-
-type mapping struct {
-	proto         string
-	userlandProxy UserlandProxy
-	host          net.Addr
-	container     net.Addr
-}
-
-var (
-	chain *iptables.Chain
-	lock  sync.Mutex
-
-	// udp:ip:port
-	currentMappings = make(map[string]*mapping)
-
-	NewProxy = NewProxyCommand
-)
-
-var (
-	ErrUnknownBackendAddressType = errors.New("unknown container address type not supported")
-	ErrPortMappedForIP           = errors.New("port is already mapped to ip")
-	ErrPortNotMapped             = errors.New("port is not mapped")
-)
-
-func SetIptablesChain(c *iptables.Chain) {
-	chain = c
-}
-
-func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err error) {
-	lock.Lock()
-	defer lock.Unlock()
-
-	var (
-		m                 *mapping
-		proto             string
-		allocatedHostPort int
-		proxy             UserlandProxy
-	)
-
-	switch container.(type) {
-	case *net.TCPAddr:
-		proto = "tcp"
-		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
-			return nil, err
-		}
-
-		m = &mapping{
-			proto:     proto,
-			host:      &net.TCPAddr{IP: hostIP, Port: allocatedHostPort},
-			container: container,
-		}
-
-		proxy = NewProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port)
-	case *net.UDPAddr:
-		proto = "udp"
-		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
-			return nil, err
-		}
-
-		m = &mapping{
-			proto:     proto,
-			host:      &net.UDPAddr{IP: hostIP, Port: allocatedHostPort},
-			container: container,
-		}
-
-		proxy = NewProxy(proto, hostIP, allocatedHostPort, container.(*net.UDPAddr).IP, container.(*net.UDPAddr).Port)
-	default:
-		return nil, ErrUnknownBackendAddressType
-	}
-
-	// release the allocated port on any further error during return.
-	defer func() {
-		if err != nil {
-			portallocator.ReleasePort(hostIP, proto, allocatedHostPort)
-		}
-	}()
-
-	key := getKey(m.host)
-	if _, exists := currentMappings[key]; exists {
-		return nil, ErrPortMappedForIP
-	}
-
-	containerIP, containerPort := getIPAndPort(m.container)
-	if err := forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
-		return nil, err
-	}
-
-	cleanup := func() error {
-		// need to undo the iptables rules before we return
-		proxy.Stop()
-		forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
-		if err := portallocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
-			return err
-		}
-
-		return nil
-	}
-
-	if err := proxy.Start(); err != nil {
-		if err := cleanup(); err != nil {
-			return nil, fmt.Errorf("Error during port allocation cleanup: %v", err)
-		}
-		return nil, err
-	}
-	m.userlandProxy = proxy
-	currentMappings[key] = m
-	return m.host, nil
-}
-
-func Unmap(host net.Addr) error {
-	lock.Lock()
-	defer lock.Unlock()
-
-	key := getKey(host)
-	data, exists := currentMappings[key]
-	if !exists {
-		return ErrPortNotMapped
-	}
-
-	data.userlandProxy.Stop()
-
-	delete(currentMappings, key)
-
-	containerIP, containerPort := getIPAndPort(data.container)
-	hostIP, hostPort := getIPAndPort(data.host)
-	if err := forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
-		log.Errorf("Error on iptables delete: %s", err)
-	}
-
-	switch a := host.(type) {
-	case *net.TCPAddr:
-		return portallocator.ReleasePort(a.IP, "tcp", a.Port)
-	case *net.UDPAddr:
-		return portallocator.ReleasePort(a.IP, "udp", a.Port)
-	}
-	return nil
-}
-
-func getKey(a net.Addr) string {
-	switch t := a.(type) {
-	case *net.TCPAddr:
-		return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "tcp")
-	case *net.UDPAddr:
-		return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "udp")
-	}
-	return ""
-}
-
-func getIPAndPort(a net.Addr) (net.IP, int) {
-	switch t := a.(type) {
-	case *net.TCPAddr:
-		return t.IP, t.Port
-	case *net.UDPAddr:
-		return t.IP, t.Port
-	}
-	return nil, 0
-}
-
-func forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
-	if chain == nil {
-		return nil
-	}
-	return chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
-}

+ 0 - 152
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper_test.go

@@ -1,152 +0,0 @@
-package portmapper
-
-import (
-	"net"
-	"testing"
-
-	"github.com/docker/docker/daemon/networkdriver/portallocator"
-	"github.com/docker/docker/pkg/iptables"
-)
-
-func init() {
-	// override this func to mock out the proxy server
-	NewProxy = NewMockProxyCommand
-}
-
-func reset() {
-	chain = nil
-	currentMappings = make(map[string]*mapping)
-}
-
-func TestSetIptablesChain(t *testing.T) {
-	defer reset()
-
-	c := &iptables.Chain{
-		Name:   "TEST",
-		Bridge: "192.168.1.1",
-	}
-
-	if chain != nil {
-		t.Fatal("chain should be nil at init")
-	}
-
-	SetIptablesChain(c)
-	if chain == nil {
-		t.Fatal("chain should not be nil after set")
-	}
-}
-
-func TestMapPorts(t *testing.T) {
-	dstIp1 := net.ParseIP("192.168.0.1")
-	dstIp2 := net.ParseIP("192.168.0.2")
-	dstAddr1 := &net.TCPAddr{IP: dstIp1, Port: 80}
-	dstAddr2 := &net.TCPAddr{IP: dstIp2, Port: 80}
-
-	srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
-	srcAddr2 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")}
-
-	addrEqual := func(addr1, addr2 net.Addr) bool {
-		return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String())
-	}
-
-	if host, err := Map(srcAddr1, dstIp1, 80); err != nil {
-		t.Fatalf("Failed to allocate port: %s", err)
-	} else if !addrEqual(dstAddr1, host) {
-		t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s",
-			dstAddr1.String(), dstAddr1.Network(), host.String(), host.Network())
-	}
-
-	if _, err := Map(srcAddr1, dstIp1, 80); err == nil {
-		t.Fatalf("Port is in use - mapping should have failed")
-	}
-
-	if _, err := Map(srcAddr2, dstIp1, 80); err == nil {
-		t.Fatalf("Port is in use - mapping should have failed")
-	}
-
-	if _, err := Map(srcAddr2, dstIp2, 80); err != nil {
-		t.Fatalf("Failed to allocate port: %s", err)
-	}
-
-	if Unmap(dstAddr1) != nil {
-		t.Fatalf("Failed to release port")
-	}
-
-	if Unmap(dstAddr2) != nil {
-		t.Fatalf("Failed to release port")
-	}
-
-	if Unmap(dstAddr2) == nil {
-		t.Fatalf("Port already released, but no error reported")
-	}
-}
-
-func TestGetUDPKey(t *testing.T) {
-	addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53}
-
-	key := getKey(addr)
-
-	if expected := "192.168.1.5:53/udp"; key != expected {
-		t.Fatalf("expected key %s got %s", expected, key)
-	}
-}
-
-func TestGetTCPKey(t *testing.T) {
-	addr := &net.TCPAddr{IP: net.ParseIP("192.168.1.5"), Port: 80}
-
-	key := getKey(addr)
-
-	if expected := "192.168.1.5:80/tcp"; key != expected {
-		t.Fatalf("expected key %s got %s", expected, key)
-	}
-}
-
-func TestGetUDPIPAndPort(t *testing.T) {
-	addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53}
-
-	ip, port := getIPAndPort(addr)
-	if expected := "192.168.1.5"; ip.String() != expected {
-		t.Fatalf("expected ip %s got %s", expected, ip)
-	}
-
-	if ep := 53; port != ep {
-		t.Fatalf("expected port %d got %d", ep, port)
-	}
-}
-
-func TestMapAllPortsSingleInterface(t *testing.T) {
-	dstIp1 := net.ParseIP("0.0.0.0")
-	srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
-
-	hosts := []net.Addr{}
-	var host net.Addr
-	var err error
-
-	defer func() {
-		for _, val := range hosts {
-			Unmap(val)
-		}
-	}()
-
-	for i := 0; i < 10; i++ {
-		for i := portallocator.BeginPortRange; i < portallocator.EndPortRange; i++ {
-			if host, err = Map(srcAddr1, dstIp1, 0); err != nil {
-				t.Fatal(err)
-			}
-
-			hosts = append(hosts, host)
-		}
-
-		if _, err := Map(srcAddr1, dstIp1, portallocator.BeginPortRange); err == nil {
-			t.Fatalf("Port %d should be bound but is not", portallocator.BeginPortRange)
-		}
-
-		for _, val := range hosts {
-			if err := Unmap(val); err != nil {
-				t.Fatal(err)
-			}
-		}
-
-		hosts = []net.Addr{}
-	}
-}

+ 0 - 18
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mock_proxy.go

@@ -1,18 +0,0 @@
-package portmapper
-
-import "net"
-
-func NewMockProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) UserlandProxy {
-	return &mockProxyCommand{}
-}
-
-type mockProxyCommand struct {
-}
-
-func (p *mockProxyCommand) Start() error {
-	return nil
-}
-
-func (p *mockProxyCommand) Stop() error {
-	return nil
-}

+ 0 - 161
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/proxy.go

@@ -1,161 +0,0 @@
-package portmapper
-
-import (
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"net"
-	"os"
-	"os/exec"
-	"os/signal"
-	"strconv"
-	"syscall"
-	"time"
-
-	"github.com/docker/docker/pkg/proxy"
-	"github.com/docker/docker/pkg/reexec"
-)
-
-const userlandProxyCommandName = "docker-proxy"
-
-func init() {
-	reexec.Register(userlandProxyCommandName, execProxy)
-}
-
-type UserlandProxy interface {
-	Start() error
-	Stop() error
-}
-
-// proxyCommand wraps an exec.Cmd to run the userland TCP and UDP
-// proxies as separate processes.
-type proxyCommand struct {
-	cmd *exec.Cmd
-}
-
-// execProxy is the reexec function that is registered to start the userland proxies
-func execProxy() {
-	f := os.NewFile(3, "signal-parent")
-	host, container := parseHostContainerAddrs()
-
-	p, err := proxy.NewProxy(host, container)
-	if err != nil {
-		fmt.Fprintf(f, "1\n%s", err)
-		f.Close()
-		os.Exit(1)
-	}
-	go handleStopSignals(p)
-	fmt.Fprint(f, "0\n")
-	f.Close()
-
-	// Run will block until the proxy stops
-	p.Run()
-}
-
-// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP
-// net.Addrs to map the host and container ports
-func parseHostContainerAddrs() (host net.Addr, container net.Addr) {
-	var (
-		proto         = flag.String("proto", "tcp", "proxy protocol")
-		hostIP        = flag.String("host-ip", "", "host ip")
-		hostPort      = flag.Int("host-port", -1, "host port")
-		containerIP   = flag.String("container-ip", "", "container ip")
-		containerPort = flag.Int("container-port", -1, "container port")
-	)
-
-	flag.Parse()
-
-	switch *proto {
-	case "tcp":
-		host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
-		container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort}
-	case "udp":
-		host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
-		container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort}
-	default:
-		log.Fatalf("unsupported protocol %s", *proto)
-	}
-
-	return host, container
-}
-
-func handleStopSignals(p proxy.Proxy) {
-	s := make(chan os.Signal, 10)
-	signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
-
-	for _ = range s {
-		p.Close()
-
-		os.Exit(0)
-	}
-}
-
-func NewProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) UserlandProxy {
-	args := []string{
-		userlandProxyCommandName,
-		"-proto", proto,
-		"-host-ip", hostIP.String(),
-		"-host-port", strconv.Itoa(hostPort),
-		"-container-ip", containerIP.String(),
-		"-container-port", strconv.Itoa(containerPort),
-	}
-
-	return &proxyCommand{
-		cmd: &exec.Cmd{
-			Path: reexec.Self(),
-			Args: args,
-			SysProcAttr: &syscall.SysProcAttr{
-				Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies
-			},
-		},
-	}
-}
-
-func (p *proxyCommand) Start() error {
-	r, w, err := os.Pipe()
-	if err != nil {
-		return fmt.Errorf("proxy unable to open os.Pipe %s", err)
-	}
-	defer r.Close()
-	p.cmd.ExtraFiles = []*os.File{w}
-	if err := p.cmd.Start(); err != nil {
-		return err
-	}
-	w.Close()
-
-	errchan := make(chan error, 1)
-	go func() {
-		buf := make([]byte, 2)
-		r.Read(buf)
-
-		if string(buf) != "0\n" {
-			errStr, err := ioutil.ReadAll(r)
-			if err != nil {
-				errchan <- fmt.Errorf("Error reading exit status from userland proxy: %v", err)
-				return
-			}
-
-			errchan <- fmt.Errorf("Error starting userland proxy: %s", errStr)
-			return
-		}
-		errchan <- nil
-	}()
-
-	select {
-	case err := <-errchan:
-		return err
-	case <-time.After(16 * time.Second):
-		return fmt.Errorf("Timed out proxy starting the userland proxy")
-	}
-}
-
-func (p *proxyCommand) Stop() error {
-	if p.cmd.Process != nil {
-		if err := p.cmd.Process.Signal(os.Interrupt); err != nil {
-			return err
-		}
-		return p.cmd.Wait()
-	}
-	return nil
-}

+ 0 - 118
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/utils.go

@@ -1,118 +0,0 @@
-package networkdriver
-
-import (
-	"errors"
-	"fmt"
-	"net"
-
-	"github.com/docker/libcontainer/netlink"
-)
-
-var (
-	networkGetRoutesFct = netlink.NetworkGetRoutes
-	ErrNoDefaultRoute   = errors.New("no default route")
-)
-
-func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
-	if len(nameservers) > 0 {
-		for _, ns := range nameservers {
-			_, nsNetwork, err := net.ParseCIDR(ns)
-			if err != nil {
-				return err
-			}
-			if NetworkOverlaps(toCheck, nsNetwork) {
-				return ErrNetworkOverlapsWithNameservers
-			}
-		}
-	}
-	return nil
-}
-
-func CheckRouteOverlaps(toCheck *net.IPNet) error {
-	networks, err := networkGetRoutesFct()
-	if err != nil {
-		return err
-	}
-
-	for _, network := range networks {
-		if network.IPNet != nil && NetworkOverlaps(toCheck, network.IPNet) {
-			return ErrNetworkOverlaps
-		}
-	}
-	return nil
-}
-
-// Detects overlap between one IPNet and another
-func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
-	if len(netX.IP) == len(netY.IP) {
-		if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
-			return true
-		}
-		if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
-			return true
-		}
-	}
-	return false
-}
-
-// Calculates the first and last IP addresses in an IPNet
-func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
-	var netIP net.IP
-	if network.IP.To4() != nil {
-		netIP = network.IP.To4()
-	} else if network.IP.To16() != nil {
-		netIP = network.IP.To16()
-	} else {
-		return nil, nil
-	}
-
-	lastIP := make([]byte, len(netIP), len(netIP))
-
-	for i := 0; i < len(netIP); i++ {
-		lastIP[i] = netIP[i] | ^network.Mask[i]
-	}
-	return netIP.Mask(network.Mask), net.IP(lastIP)
-}
-
-// Return the first IPv4 address and slice of IPv6 addresses for the specified network interface
-func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
-	iface, err := net.InterfaceByName(name)
-	if err != nil {
-		return nil, nil, err
-	}
-	addrs, err := iface.Addrs()
-	if err != nil {
-		return nil, nil, err
-	}
-	var addrs4 []net.Addr
-	var addrs6 []net.Addr
-	for _, addr := range addrs {
-		ip := (addr.(*net.IPNet)).IP
-		if ip4 := ip.To4(); ip4 != nil {
-			addrs4 = append(addrs4, addr)
-		} else if ip6 := ip.To16(); len(ip6) == net.IPv6len {
-			addrs6 = append(addrs6, addr)
-		}
-	}
-	switch {
-	case len(addrs4) == 0:
-		return nil, nil, fmt.Errorf("Interface %v has no IPv4 addresses", name)
-	case len(addrs4) > 1:
-		fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
-			name, (addrs4[0].(*net.IPNet)).IP)
-	}
-	return addrs4[0], addrs6, nil
-}
-
-func GetDefaultRouteIface() (*net.Interface, error) {
-	rs, err := networkGetRoutesFct()
-	if err != nil {
-		return nil, fmt.Errorf("unable to get routes: %v", err)
-	}
-	for _, r := range rs {
-		if r.Default {
-			return r.Iface, nil
-		}
-	}
-	return nil, ErrNoDefaultRoute
-}

+ 0 - 2
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/MAINTAINERS

@@ -1,2 +0,0 @@
-Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
-Jessie Frazelle <jess@docker.com> (@jfrazelle)

+ 20 - 13
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/iptables.go

@@ -9,7 +9,7 @@ import (
 	"strconv"
 	"strings"
 
-	log "github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus"
 )
 
 type Action string
@@ -21,6 +21,7 @@ const (
 	Insert Action = "-I"
 	Nat    Table  = "nat"
 	Filter Table  = "filter"
+	Mangle Table  = "mangle"
 )
 
 var (
@@ -82,7 +83,7 @@ func NewChain(name, bridge string, table Table) (*Chain, error) {
 		preroute := []string{
 			"-m", "addrtype",
 			"--dst-type", "LOCAL"}
-		if !Exists(preroute...) {
+		if !Exists(Nat, "PREROUTING", preroute...) {
 			if err := c.Prerouting(Append, preroute...); err != nil {
 				return nil, fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
 			}
@@ -91,17 +92,17 @@ func NewChain(name, bridge string, table Table) (*Chain, error) {
 			"-m", "addrtype",
 			"--dst-type", "LOCAL",
 			"!", "--dst", "127.0.0.0/8"}
-		if !Exists(output...) {
+		if !Exists(Nat, "OUTPUT", output...) {
 			if err := c.Output(Append, output...); err != nil {
 				return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
 			}
 		}
 	case Filter:
-		link := []string{"FORWARD",
+		link := []string{
 			"-o", c.Bridge,
 			"-j", c.Name}
-		if !Exists(link...) {
-			insert := append([]string{string(Insert)}, link...)
+		if !Exists(Filter, "FORWARD", link...) {
+			insert := append([]string{string(Insert), "FORWARD"}, link...)
 			if output, err := Raw(insert...); err != nil {
 				return nil, err
 			} else if len(output) != 0 {
@@ -242,19 +243,25 @@ func (c *Chain) Remove() error {
 }
 
 // Check if a rule exists
-func Exists(args ...string) bool {
+func Exists(table Table, chain string, rule ...string) bool {
+	if string(table) == "" {
+		table = Filter
+	}
+
 	// iptables -C, --check option was added in v.1.4.11
 	// http://ftp.netfilter.org/pub/iptables/changes-iptables-1.4.11.txt
 
 	// try -C
 	// if exit status is 0 then return true, the rule exists
-	if _, err := Raw(append([]string{"-C"}, args...)...); err == nil {
+	if _, err := Raw(append([]string{
+		"-t", string(table), "-C", chain}, rule...)...); err == nil {
 		return true
 	}
 
-	// parse iptables-save for the rule
-	rule := strings.Replace(strings.Join(args, " "), "-t nat ", "", -1)
-	existingRules, _ := exec.Command("iptables-save").Output()
+	// parse "iptables -S" for the rule (this checks rules in a specific chain
+	// in a specific table)
+	ruleString := strings.Join(rule, " ")
+	existingRules, _ := exec.Command("iptables", "-t", string(table), "-S", chain).Output()
 
 	// regex to replace ips in rule
 	// because MASQUERADE rule will not be exactly what was passed
@@ -262,7 +269,7 @@ func Exists(args ...string) bool {
 
 	return strings.Contains(
 		re.ReplaceAllString(string(existingRules), "?"),
-		re.ReplaceAllString(rule, "?"),
+		re.ReplaceAllString(ruleString, "?"),
 	)
 }
 
@@ -276,7 +283,7 @@ func Raw(args ...string) ([]byte, error) {
 		args = append([]string{"--wait"}, args...)
 	}
 
-	log.Debugf("%s, %v", iptablesPath, args)
+	logrus.Debugf("%s, %v", iptablesPath, args)
 
 	output, err := exec.Command(iptablesPath, args...).CombinedOutput()
 	if err != nil {

+ 17 - 23
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/iptables/iptables_test.go

@@ -39,8 +39,7 @@ func TestForward(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	dnatRule := []string{natChain.Name,
-		"-t", string(natChain.Table),
+	dnatRule := []string{
 		"!", "-i", filterChain.Bridge,
 		"-d", ip.String(),
 		"-p", proto,
@@ -49,12 +48,11 @@ func TestForward(t *testing.T) {
 		"--to-destination", dstAddr + ":" + strconv.Itoa(dstPort),
 	}
 
-	if !Exists(dnatRule...) {
+	if !Exists(natChain.Table, natChain.Name, dnatRule...) {
 		t.Fatalf("DNAT rule does not exist")
 	}
 
-	filterRule := []string{filterChain.Name,
-		"-t", string(filterChain.Table),
+	filterRule := []string{
 		"!", "-i", filterChain.Bridge,
 		"-o", filterChain.Bridge,
 		"-d", dstAddr,
@@ -63,12 +61,11 @@ func TestForward(t *testing.T) {
 		"-j", "ACCEPT",
 	}
 
-	if !Exists(filterRule...) {
+	if !Exists(filterChain.Table, filterChain.Name, filterRule...) {
 		t.Fatalf("filter rule does not exist")
 	}
 
-	masqRule := []string{"POSTROUTING",
-		"-t", string(natChain.Table),
+	masqRule := []string{
 		"-d", dstAddr,
 		"-s", dstAddr,
 		"-p", proto,
@@ -76,7 +73,7 @@ func TestForward(t *testing.T) {
 		"-j", "MASQUERADE",
 	}
 
-	if !Exists(masqRule...) {
+	if !Exists(natChain.Table, "POSTROUTING", masqRule...) {
 		t.Fatalf("MASQUERADE rule does not exist")
 	}
 }
@@ -94,8 +91,7 @@ func TestLink(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	rule1 := []string{filterChain.Name,
-		"-t", string(filterChain.Table),
+	rule1 := []string{
 		"-i", filterChain.Bridge,
 		"-o", filterChain.Bridge,
 		"-p", proto,
@@ -104,12 +100,11 @@ func TestLink(t *testing.T) {
 		"--dport", strconv.Itoa(port),
 		"-j", "ACCEPT"}
 
-	if !Exists(rule1...) {
+	if !Exists(filterChain.Table, filterChain.Name, rule1...) {
 		t.Fatalf("rule1 does not exist")
 	}
 
-	rule2 := []string{filterChain.Name,
-		"-t", string(filterChain.Table),
+	rule2 := []string{
 		"-i", filterChain.Bridge,
 		"-o", filterChain.Bridge,
 		"-p", proto,
@@ -118,7 +113,7 @@ func TestLink(t *testing.T) {
 		"--sport", strconv.Itoa(port),
 		"-j", "ACCEPT"}
 
-	if !Exists(rule2...) {
+	if !Exists(filterChain.Table, filterChain.Name, rule2...) {
 		t.Fatalf("rule2 does not exist")
 	}
 }
@@ -133,17 +128,16 @@ func TestPrerouting(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	rule := []string{"PREROUTING",
-		"-t", string(Nat),
+	rule := []string{
 		"-j", natChain.Name}
 
 	rule = append(rule, args...)
 
-	if !Exists(rule...) {
+	if !Exists(natChain.Table, "PREROUTING", rule...) {
 		t.Fatalf("rule does not exist")
 	}
 
-	delRule := append([]string{"-D"}, rule...)
+	delRule := append([]string{"-D", "PREROUTING", "-t", string(Nat)}, rule...)
 	if _, err = Raw(delRule...); err != nil {
 		t.Fatal(err)
 	}
@@ -159,17 +153,17 @@ func TestOutput(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	rule := []string{"OUTPUT",
-		"-t", string(natChain.Table),
+	rule := []string{
 		"-j", natChain.Name}
 
 	rule = append(rule, args...)
 
-	if !Exists(rule...) {
+	if !Exists(natChain.Table, "OUTPUT", rule...) {
 		t.Fatalf("rule does not exist")
 	}
 
-	delRule := append([]string{"-D"}, rule...)
+	delRule := append([]string{"-D", "OUTPUT", "-t",
+		string(natChain.Table)}, rule...)
 	if _, err = Raw(delRule...); err != nil {
 		t.Fatal(err)
 	}

+ 0 - 1
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/MAINTAINERS

@@ -1 +0,0 @@
-Erik Hollensbe <github@hollensbe.org> (@erikh)

+ 3 - 3
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/tcp_proxy.go

@@ -5,7 +5,7 @@ import (
 	"net"
 	"syscall"
 
-	log "github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus"
 )
 
 type TCPProxy struct {
@@ -31,7 +31,7 @@ func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) {
 func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) {
 	backend, err := net.DialTCP("tcp", nil, proxy.backendAddr)
 	if err != nil {
-		log.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err)
+		logrus.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err)
 		client.Close()
 		return
 	}
@@ -78,7 +78,7 @@ func (proxy *TCPProxy) Run() {
 	for {
 		client, err := proxy.listener.Accept()
 		if err != nil {
-			log.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
+			logrus.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
 			return
 		}
 		go proxy.clientLoop(client.(*net.TCPConn), quit)

+ 4 - 4
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/proxy/udp_proxy.go

@@ -8,7 +8,7 @@ import (
 	"syscall"
 	"time"
 
-	log "github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus"
 )
 
 const (
@@ -105,7 +105,7 @@ func (proxy *UDPProxy) Run() {
 			// ECONNREFUSED like Read do (see comment in
 			// UDPProxy.replyLoop)
 			if !isClosedError(err) {
-				log.Printf("Stopping proxy on udp/%v for udp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
+				logrus.Printf("Stopping proxy on udp/%v for udp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
 			}
 			break
 		}
@@ -116,7 +116,7 @@ func (proxy *UDPProxy) Run() {
 		if !hit {
 			proxyConn, err = net.DialUDP("udp", nil, proxy.backendAddr)
 			if err != nil {
-				log.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
+				logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
 				proxy.connTrackLock.Unlock()
 				continue
 			}
@@ -127,7 +127,7 @@ func (proxy *UDPProxy) Run() {
 		for i := 0; i != read; {
 			written, err := proxyConn.Write(readBuf[i:read])
 			if err != nil {
-				log.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
+				logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
 				break
 			}
 			i += written

+ 0 - 1
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/MAINTAINERS

@@ -1 +0,0 @@
-Michael Crosby <michael@docker.com> (@crosbymichael)

+ 7 - 1
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/reexec.go

@@ -35,8 +35,14 @@ func Self() string {
 	name := os.Args[0]
 	if filepath.Base(name) == name {
 		if lp, err := exec.LookPath(name); err == nil {
-			name = lp
+			return lp
 		}
 	}
+	// handle conversion of relative paths to absolute
+	if absName, err := filepath.Abs(name); err == nil {
+		return absName
+	}
+	// if we coudn't get absolute name, return original
+	// (NOTE: Go only errors on Abs() if os.Getwd fails)
 	return name
 }

+ 0 - 2
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/MAINTAINERS

@@ -1,2 +0,0 @@
-Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
-Guillaume J. Charmes <guillaume@docker.com> (@creack)

+ 0 - 31
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink.go

@@ -1,31 +0,0 @@
-// Packet netlink provide access to low level Netlink sockets and messages.
-//
-// Actual implementations are in:
-// netlink_linux.go
-// netlink_darwin.go
-package netlink
-
-import (
-	"errors"
-	"net"
-)
-
-var (
-	ErrWrongSockType   = errors.New("Wrong socket type")
-	ErrShortResponse   = errors.New("Got short response from netlink")
-	ErrInterfaceExists = errors.New("Network interface already exists")
-)
-
-// A Route is a subnet associated with the interface to reach it.
-type Route struct {
-	*net.IPNet
-	Iface   *net.Interface
-	Default bool
-}
-
-// An IfAddr defines IP network settings for a given network interface
-type IfAddr struct {
-	Iface *net.Interface
-	IP    net.IP
-	IPNet *net.IPNet
-}

+ 0 - 1307
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux.go

@@ -1,1307 +0,0 @@
-package netlink
-
-import (
-	"encoding/binary"
-	"fmt"
-	"io"
-	"math/rand"
-	"net"
-	"os"
-	"sync/atomic"
-	"syscall"
-	"unsafe"
-)
-
-const (
-	IFNAMSIZ          = 16
-	DEFAULT_CHANGE    = 0xFFFFFFFF
-	IFLA_INFO_KIND    = 1
-	IFLA_INFO_DATA    = 2
-	VETH_INFO_PEER    = 1
-	IFLA_MACVLAN_MODE = 1
-	IFLA_VLAN_ID      = 1
-	IFLA_NET_NS_FD    = 28
-	IFLA_ADDRESS      = 1
-	IFLA_BRPORT_MODE  = 4
-	SIOC_BRADDBR      = 0x89a0
-	SIOC_BRDELBR      = 0x89a1
-	SIOC_BRADDIF      = 0x89a2
-)
-
-const (
-	MACVLAN_MODE_PRIVATE = 1 << iota
-	MACVLAN_MODE_VEPA
-	MACVLAN_MODE_BRIDGE
-	MACVLAN_MODE_PASSTHRU
-)
-
-var nextSeqNr uint32
-
-type ifreqHwaddr struct {
-	IfrnName   [IFNAMSIZ]byte
-	IfruHwaddr syscall.RawSockaddr
-}
-
-type ifreqIndex struct {
-	IfrnName  [IFNAMSIZ]byte
-	IfruIndex int32
-}
-
-type ifreqFlags struct {
-	IfrnName  [IFNAMSIZ]byte
-	Ifruflags uint16
-}
-
-var native binary.ByteOrder
-
-func init() {
-	var x uint32 = 0x01020304
-	if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
-		native = binary.BigEndian
-	} else {
-		native = binary.LittleEndian
-	}
-}
-
-func getIpFamily(ip net.IP) int {
-	if len(ip) <= net.IPv4len {
-		return syscall.AF_INET
-	}
-	if ip.To4() != nil {
-		return syscall.AF_INET
-	}
-	return syscall.AF_INET6
-}
-
-type NetlinkRequestData interface {
-	Len() int
-	ToWireFormat() []byte
-}
-
-type IfInfomsg struct {
-	syscall.IfInfomsg
-}
-
-func newIfInfomsg(family int) *IfInfomsg {
-	return &IfInfomsg{
-		IfInfomsg: syscall.IfInfomsg{
-			Family: uint8(family),
-		},
-	}
-}
-
-func newIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
-	msg := newIfInfomsg(family)
-	parent.children = append(parent.children, msg)
-	return msg
-}
-
-func (msg *IfInfomsg) ToWireFormat() []byte {
-	length := syscall.SizeofIfInfomsg
-	b := make([]byte, length)
-	b[0] = msg.Family
-	b[1] = 0
-	native.PutUint16(b[2:4], msg.Type)
-	native.PutUint32(b[4:8], uint32(msg.Index))
-	native.PutUint32(b[8:12], msg.Flags)
-	native.PutUint32(b[12:16], msg.Change)
-	return b
-}
-
-func (msg *IfInfomsg) Len() int {
-	return syscall.SizeofIfInfomsg
-}
-
-type IfAddrmsg struct {
-	syscall.IfAddrmsg
-}
-
-func newIfAddrmsg(family int) *IfAddrmsg {
-	return &IfAddrmsg{
-		IfAddrmsg: syscall.IfAddrmsg{
-			Family: uint8(family),
-		},
-	}
-}
-
-func (msg *IfAddrmsg) ToWireFormat() []byte {
-	length := syscall.SizeofIfAddrmsg
-	b := make([]byte, length)
-	b[0] = msg.Family
-	b[1] = msg.Prefixlen
-	b[2] = msg.Flags
-	b[3] = msg.Scope
-	native.PutUint32(b[4:8], msg.Index)
-	return b
-}
-
-func (msg *IfAddrmsg) Len() int {
-	return syscall.SizeofIfAddrmsg
-}
-
-type RtMsg struct {
-	syscall.RtMsg
-}
-
-func newRtMsg() *RtMsg {
-	return &RtMsg{
-		RtMsg: syscall.RtMsg{
-			Table:    syscall.RT_TABLE_MAIN,
-			Scope:    syscall.RT_SCOPE_UNIVERSE,
-			Protocol: syscall.RTPROT_BOOT,
-			Type:     syscall.RTN_UNICAST,
-		},
-	}
-}
-
-func (msg *RtMsg) ToWireFormat() []byte {
-	length := syscall.SizeofRtMsg
-	b := make([]byte, length)
-	b[0] = msg.Family
-	b[1] = msg.Dst_len
-	b[2] = msg.Src_len
-	b[3] = msg.Tos
-	b[4] = msg.Table
-	b[5] = msg.Protocol
-	b[6] = msg.Scope
-	b[7] = msg.Type
-	native.PutUint32(b[8:12], msg.Flags)
-	return b
-}
-
-func (msg *RtMsg) Len() int {
-	return syscall.SizeofRtMsg
-}
-
-func rtaAlignOf(attrlen int) int {
-	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
-}
-
-type RtAttr struct {
-	syscall.RtAttr
-	Data     []byte
-	children []NetlinkRequestData
-}
-
-func newRtAttr(attrType int, data []byte) *RtAttr {
-	return &RtAttr{
-		RtAttr: syscall.RtAttr{
-			Type: uint16(attrType),
-		},
-		children: []NetlinkRequestData{},
-		Data:     data,
-	}
-}
-
-func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
-	attr := newRtAttr(attrType, data)
-	parent.children = append(parent.children, attr)
-	return attr
-}
-
-func (a *RtAttr) Len() int {
-	if len(a.children) == 0 {
-		return (syscall.SizeofRtAttr + len(a.Data))
-	}
-
-	l := 0
-	for _, child := range a.children {
-		l += child.Len()
-	}
-	l += syscall.SizeofRtAttr
-	return rtaAlignOf(l + len(a.Data))
-}
-
-func (a *RtAttr) ToWireFormat() []byte {
-	length := a.Len()
-	buf := make([]byte, rtaAlignOf(length))
-
-	if a.Data != nil {
-		copy(buf[4:], a.Data)
-	} else {
-		next := 4
-		for _, child := range a.children {
-			childBuf := child.ToWireFormat()
-			copy(buf[next:], childBuf)
-			next += rtaAlignOf(len(childBuf))
-		}
-	}
-
-	if l := uint16(length); l != 0 {
-		native.PutUint16(buf[0:2], l)
-	}
-	native.PutUint16(buf[2:4], a.Type)
-	return buf
-}
-
-func uint32Attr(t int, n uint32) *RtAttr {
-	buf := make([]byte, 4)
-	native.PutUint32(buf, n)
-	return newRtAttr(t, buf)
-}
-
-type NetlinkRequest struct {
-	syscall.NlMsghdr
-	Data []NetlinkRequestData
-}
-
-func (rr *NetlinkRequest) ToWireFormat() []byte {
-	length := rr.Len
-	dataBytes := make([][]byte, len(rr.Data))
-	for i, data := range rr.Data {
-		dataBytes[i] = data.ToWireFormat()
-		length += uint32(len(dataBytes[i]))
-	}
-	b := make([]byte, length)
-	native.PutUint32(b[0:4], length)
-	native.PutUint16(b[4:6], rr.Type)
-	native.PutUint16(b[6:8], rr.Flags)
-	native.PutUint32(b[8:12], rr.Seq)
-	native.PutUint32(b[12:16], rr.Pid)
-
-	next := 16
-	for _, data := range dataBytes {
-		copy(b[next:], data)
-		next += len(data)
-	}
-	return b
-}
-
-func (rr *NetlinkRequest) AddData(data NetlinkRequestData) {
-	if data != nil {
-		rr.Data = append(rr.Data, data)
-	}
-}
-
-func newNetlinkRequest(proto, flags int) *NetlinkRequest {
-	return &NetlinkRequest{
-		NlMsghdr: syscall.NlMsghdr{
-			Len:   uint32(syscall.NLMSG_HDRLEN),
-			Type:  uint16(proto),
-			Flags: syscall.NLM_F_REQUEST | uint16(flags),
-			Seq:   atomic.AddUint32(&nextSeqNr, 1),
-		},
-	}
-}
-
-type NetlinkSocket struct {
-	fd  int
-	lsa syscall.SockaddrNetlink
-}
-
-func getNetlinkSocket() (*NetlinkSocket, error) {
-	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_ROUTE)
-	if err != nil {
-		return nil, err
-	}
-	s := &NetlinkSocket{
-		fd: fd,
-	}
-	s.lsa.Family = syscall.AF_NETLINK
-	if err := syscall.Bind(fd, &s.lsa); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	return s, nil
-}
-
-func (s *NetlinkSocket) Close() {
-	syscall.Close(s.fd)
-}
-
-func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
-	if err := syscall.Sendto(s.fd, request.ToWireFormat(), 0, &s.lsa); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
-	rb := make([]byte, syscall.Getpagesize())
-	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
-	if err != nil {
-		return nil, err
-	}
-	if nr < syscall.NLMSG_HDRLEN {
-		return nil, ErrShortResponse
-	}
-	rb = rb[:nr]
-	return syscall.ParseNetlinkMessage(rb)
-}
-
-func (s *NetlinkSocket) GetPid() (uint32, error) {
-	lsa, err := syscall.Getsockname(s.fd)
-	if err != nil {
-		return 0, err
-	}
-	switch v := lsa.(type) {
-	case *syscall.SockaddrNetlink:
-		return v.Pid, nil
-	}
-	return 0, ErrWrongSockType
-}
-
-func (s *NetlinkSocket) CheckMessage(m syscall.NetlinkMessage, seq, pid uint32) error {
-	if m.Header.Seq != seq {
-		return fmt.Errorf("netlink: invalid seq %d, expected %d", m.Header.Seq, seq)
-	}
-	if m.Header.Pid != pid {
-		return fmt.Errorf("netlink: wrong pid %d, expected %d", m.Header.Pid, pid)
-	}
-	if m.Header.Type == syscall.NLMSG_DONE {
-		return io.EOF
-	}
-	if m.Header.Type == syscall.NLMSG_ERROR {
-		e := int32(native.Uint32(m.Data[0:4]))
-		if e == 0 {
-			return io.EOF
-		}
-		return syscall.Errno(-e)
-	}
-	return nil
-}
-
-func (s *NetlinkSocket) HandleAck(seq uint32) error {
-	pid, err := s.GetPid()
-	if err != nil {
-		return err
-	}
-
-outer:
-	for {
-		msgs, err := s.Receive()
-		if err != nil {
-			return err
-		}
-		for _, m := range msgs {
-			if err := s.CheckMessage(m, seq, pid); err != nil {
-				if err == io.EOF {
-					break outer
-				}
-				return err
-			}
-		}
-	}
-
-	return nil
-}
-
-func zeroTerminated(s string) []byte {
-	return []byte(s + "\000")
-}
-
-func nonZeroTerminated(s string) []byte {
-	return []byte(s)
-}
-
-// Add a new network link of a specified type.
-// This is identical to running: ip link add $name type $linkType
-func NetworkLinkAdd(name string, linkType string) error {
-	if name == "" || linkType == "" {
-		return fmt.Errorf("Neither link name nor link type can be empty!")
-	}
-
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	wb.AddData(msg)
-
-	linkInfo := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(linkInfo, IFLA_INFO_KIND, nonZeroTerminated(linkType))
-	wb.AddData(linkInfo)
-
-	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
-	wb.AddData(nameData)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Delete a network link.
-// This is identical to running: ip link del $name
-func NetworkLinkDel(name string) error {
-	if name == "" {
-		return fmt.Errorf("Network link name can not be empty!")
-	}
-
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	iface, err := net.InterfaceByName(name)
-	if err != nil {
-		return err
-	}
-
-	wb := newNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	wb.AddData(msg)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Bring up a particular network interface.
-// This is identical to running: ip link set dev $name up
-func NetworkLinkUp(iface *net.Interface) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	msg.Flags = syscall.IFF_UP
-	msg.Change = syscall.IFF_UP
-	wb.AddData(msg)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Bring down a particular network interface.
-// This is identical to running: ip link set $name down
-func NetworkLinkDown(iface *net.Interface) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	msg.Flags = 0 & ^syscall.IFF_UP
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Set link layer address ie. MAC Address.
-// This is identical to running: ip link set dev $name address $macaddress
-func NetworkSetMacAddress(iface *net.Interface, macaddr string) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	hwaddr, err := net.ParseMAC(macaddr)
-	if err != nil {
-		return err
-	}
-
-	var (
-		MULTICAST byte = 0x1
-	)
-
-	if hwaddr[0]&0x1 == MULTICAST {
-		return fmt.Errorf("Multicast MAC Address is not supported: %s", macaddr)
-	}
-
-	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-
-	macdata := make([]byte, 6)
-	copy(macdata, hwaddr)
-	data := newRtAttr(IFLA_ADDRESS, macdata)
-	wb.AddData(data)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-// Set link Maximum Transmission Unit
-// This is identical to running: ip link set dev $name mtu $MTU
-// bridge is a bitch here https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=292088
-// https://bugzilla.redhat.com/show_bug.cgi?id=697021
-// There is a discussion about how to deal with ifcs joining bridge with MTU > 1500
-// Regular network nterfaces do seem to work though!
-func NetworkSetMTU(iface *net.Interface, mtu int) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-	wb.AddData(uint32Attr(syscall.IFLA_MTU, uint32(mtu)))
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-// Set link queue length
-// This is identical to running: ip link set dev $name txqueuelen $QLEN
-func NetworkSetTxQueueLen(iface *net.Interface, txQueueLen int) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-	wb.AddData(uint32Attr(syscall.IFLA_TXQLEN, uint32(txQueueLen)))
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-func networkMasterAction(iface *net.Interface, rtattr *RtAttr) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-	wb.AddData(rtattr)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Add an interface to bridge.
-// This is identical to running: ip link set $name master $master
-func NetworkSetMaster(iface, master *net.Interface) error {
-	data := uint32Attr(syscall.IFLA_MASTER, uint32(master.Index))
-	return networkMasterAction(iface, data)
-}
-
-// Remove an interface from the bridge
-// This is is identical to to running: ip link $name set nomaster
-func NetworkSetNoMaster(iface *net.Interface) error {
-	data := uint32Attr(syscall.IFLA_MASTER, 0)
-	return networkMasterAction(iface, data)
-}
-
-func networkSetNsAction(iface *net.Interface, rtattr *RtAttr) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	wb.AddData(msg)
-	wb.AddData(rtattr)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Move a particular network interface to a particular network namespace
-// specified by PID. This is idential to running: ip link set dev $name netns $pid
-func NetworkSetNsPid(iface *net.Interface, nspid int) error {
-	data := uint32Attr(syscall.IFLA_NET_NS_PID, uint32(nspid))
-	return networkSetNsAction(iface, data)
-}
-
-// Move a particular network interface to a particular mounted
-// network namespace specified by file descriptor.
-// This is idential to running: ip link set dev $name netns $fd
-func NetworkSetNsFd(iface *net.Interface, fd int) error {
-	data := uint32Attr(IFLA_NET_NS_FD, uint32(fd))
-	return networkSetNsAction(iface, data)
-}
-
-// Rname a particular interface to a different name
-// !!! Note that you can't rename an active interface. You need to bring it down before renaming it.
-// This is identical to running: ip link set dev ${oldName} name ${newName}
-func NetworkChangeName(iface *net.Interface, newName string) error {
-	if len(newName) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", newName)
-	}
-
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	wb.AddData(msg)
-
-	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(newName))
-	wb.AddData(nameData)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Add a new VETH pair link on the host
-// This is identical to running: ip link add name $name type veth peer name $peername
-func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	wb.AddData(msg)
-
-	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name1))
-	wb.AddData(nameData)
-
-	txqLen := make([]byte, 4)
-	native.PutUint32(txqLen, uint32(txQueueLen))
-	txqData := newRtAttr(syscall.IFLA_TXQLEN, txqLen)
-	wb.AddData(txqData)
-
-	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth"))
-	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
-	nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
-
-	newIfInfomsgChild(nest3, syscall.AF_UNSPEC)
-	newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
-
-	txqLen2 := make([]byte, 4)
-	native.PutUint32(txqLen2, uint32(txQueueLen))
-	newRtAttrChild(nest3, syscall.IFLA_TXQLEN, txqLen2)
-
-	wb.AddData(nest1)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	if err := s.HandleAck(wb.Seq); err != nil {
-		if os.IsExist(err) {
-			return ErrInterfaceExists
-		}
-
-		return err
-	}
-
-	return nil
-}
-
-// Add a new VLAN interface with masterDev as its upper device
-// This is identical to running:
-// ip link add name $name link $masterdev type vlan id $id
-func NetworkLinkAddVlan(masterDev, vlanDev string, vlanId uint16) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-
-	masterDevIfc, err := net.InterfaceByName(masterDev)
-	if err != nil {
-		return err
-	}
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	wb.AddData(msg)
-
-	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("vlan"))
-
-	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
-	vlanData := make([]byte, 2)
-	native.PutUint16(vlanData, vlanId)
-	newRtAttrChild(nest2, IFLA_VLAN_ID, vlanData)
-	wb.AddData(nest1)
-
-	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
-	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(vlanDev)))
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-// MacVlan link has LowerDev, UpperDev and operates in Mode mode
-// This simplifies the code when creating MacVlan or MacVtap interface
-type MacVlanLink struct {
-	MasterDev string
-	SlaveDev  string
-	mode      string
-}
-
-func (m MacVlanLink) Mode() uint32 {
-	modeMap := map[string]uint32{
-		"private":  MACVLAN_MODE_PRIVATE,
-		"vepa":     MACVLAN_MODE_VEPA,
-		"bridge":   MACVLAN_MODE_BRIDGE,
-		"passthru": MACVLAN_MODE_PASSTHRU,
-	}
-
-	return modeMap[m.mode]
-}
-
-// Add MAC VLAN network interface with masterDev as its upper device
-// This is identical to running:
-// ip link add name $name link $masterdev type macvlan mode $mode
-func networkLinkMacVlan(dev_type string, mcvln *MacVlanLink) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-
-	masterDevIfc, err := net.InterfaceByName(mcvln.MasterDev)
-	if err != nil {
-		return err
-	}
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	wb.AddData(msg)
-
-	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated(dev_type))
-
-	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
-	macVlanData := make([]byte, 4)
-	native.PutUint32(macVlanData, mcvln.Mode())
-	newRtAttrChild(nest2, IFLA_MACVLAN_MODE, macVlanData)
-	wb.AddData(nest1)
-
-	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
-	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(mcvln.SlaveDev)))
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-func NetworkLinkAddMacVlan(masterDev, macVlanDev string, mode string) error {
-	return networkLinkMacVlan("macvlan", &MacVlanLink{
-		MasterDev: masterDev,
-		SlaveDev:  macVlanDev,
-		mode:      mode,
-	})
-}
-
-func NetworkLinkAddMacVtap(masterDev, macVlanDev string, mode string) error {
-	return networkLinkMacVlan("macvtap", &MacVlanLink{
-		MasterDev: masterDev,
-		SlaveDev:  macVlanDev,
-		mode:      mode,
-	})
-}
-
-func networkLinkIpAction(action, flags int, ifa IfAddr) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	family := getIpFamily(ifa.IP)
-
-	wb := newNetlinkRequest(action, flags)
-
-	msg := newIfAddrmsg(family)
-	msg.Index = uint32(ifa.Iface.Index)
-	prefixLen, _ := ifa.IPNet.Mask.Size()
-	msg.Prefixlen = uint8(prefixLen)
-	wb.AddData(msg)
-
-	var ipData []byte
-	if family == syscall.AF_INET {
-		ipData = ifa.IP.To4()
-	} else {
-		ipData = ifa.IP.To16()
-	}
-
-	localData := newRtAttr(syscall.IFA_LOCAL, ipData)
-	wb.AddData(localData)
-
-	addrData := newRtAttr(syscall.IFA_ADDRESS, ipData)
-	wb.AddData(addrData)
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-
-	return s.HandleAck(wb.Seq)
-}
-
-// Delete an IP address from an interface. This is identical to:
-// ip addr del $ip/$ipNet dev $iface
-func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return networkLinkIpAction(
-		syscall.RTM_DELADDR,
-		syscall.NLM_F_ACK,
-		IfAddr{iface, ip, ipNet},
-	)
-}
-
-// Add an Ip address to an interface. This is identical to:
-// ip addr add $ip/$ipNet dev $iface
-func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return networkLinkIpAction(
-		syscall.RTM_NEWADDR,
-		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK,
-		IfAddr{iface, ip, ipNet},
-	)
-}
-
-// Returns an array of IPNet for all the currently routed subnets on ipv4
-// This is similar to the first column of "ip route" output
-func NetworkGetRoutes() ([]Route, error) {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return nil, err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
-
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	wb.AddData(msg)
-
-	if err := s.Send(wb); err != nil {
-		return nil, err
-	}
-
-	pid, err := s.GetPid()
-	if err != nil {
-		return nil, err
-	}
-
-	res := make([]Route, 0)
-
-outer:
-	for {
-		msgs, err := s.Receive()
-		if err != nil {
-			return nil, err
-		}
-		for _, m := range msgs {
-			if err := s.CheckMessage(m, wb.Seq, pid); err != nil {
-				if err == io.EOF {
-					break outer
-				}
-				return nil, err
-			}
-			if m.Header.Type != syscall.RTM_NEWROUTE {
-				continue
-			}
-
-			var r Route
-
-			msg := (*RtMsg)(unsafe.Pointer(&m.Data[0:syscall.SizeofRtMsg][0]))
-
-			if msg.Flags&syscall.RTM_F_CLONED != 0 {
-				// Ignore cloned routes
-				continue
-			}
-
-			if msg.Table != syscall.RT_TABLE_MAIN {
-				// Ignore non-main tables
-				continue
-			}
-
-			if msg.Family != syscall.AF_INET {
-				// Ignore non-ipv4 routes
-				continue
-			}
-
-			if msg.Dst_len == 0 {
-				// Default routes
-				r.Default = true
-			}
-
-			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
-			if err != nil {
-				return nil, err
-			}
-			for _, attr := range attrs {
-				switch attr.Attr.Type {
-				case syscall.RTA_DST:
-					ip := attr.Value
-					r.IPNet = &net.IPNet{
-						IP:   ip,
-						Mask: net.CIDRMask(int(msg.Dst_len), 8*len(ip)),
-					}
-				case syscall.RTA_OIF:
-					index := int(native.Uint32(attr.Value[0:4]))
-					r.Iface, _ = net.InterfaceByIndex(index)
-				}
-			}
-			if r.Default || r.IPNet != nil {
-				res = append(res, r)
-			}
-		}
-	}
-
-	return res, nil
-}
-
-// Add a new route table entry.
-func AddRoute(destination, source, gateway, device string) error {
-	if destination == "" && source == "" && gateway == "" {
-		return fmt.Errorf("one of destination, source or gateway must not be blank")
-	}
-
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-
-	wb := newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-	msg := newRtMsg()
-	currentFamily := -1
-	var rtAttrs []*RtAttr
-
-	if destination != "" {
-		destIP, destNet, err := net.ParseCIDR(destination)
-		if err != nil {
-			return fmt.Errorf("destination CIDR %s couldn't be parsed", destination)
-		}
-		destFamily := getIpFamily(destIP)
-		currentFamily = destFamily
-		destLen, bits := destNet.Mask.Size()
-		if destLen == 0 && bits == 0 {
-			return fmt.Errorf("destination CIDR %s generated a non-canonical Mask", destination)
-		}
-		msg.Family = uint8(destFamily)
-		msg.Dst_len = uint8(destLen)
-		var destData []byte
-		if destFamily == syscall.AF_INET {
-			destData = destIP.To4()
-		} else {
-			destData = destIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_DST, destData))
-	}
-
-	if source != "" {
-		srcIP := net.ParseIP(source)
-		if srcIP == nil {
-			return fmt.Errorf("source IP %s couldn't be parsed", source)
-		}
-		srcFamily := getIpFamily(srcIP)
-		if currentFamily != -1 && currentFamily != srcFamily {
-			return fmt.Errorf("source and destination ip were not the same IP family")
-		}
-		currentFamily = srcFamily
-		msg.Family = uint8(srcFamily)
-		var srcData []byte
-		if srcFamily == syscall.AF_INET {
-			srcData = srcIP.To4()
-		} else {
-			srcData = srcIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_PREFSRC, srcData))
-	}
-
-	if gateway != "" {
-		gwIP := net.ParseIP(gateway)
-		if gwIP == nil {
-			return fmt.Errorf("gateway IP %s couldn't be parsed", gateway)
-		}
-		gwFamily := getIpFamily(gwIP)
-		if currentFamily != -1 && currentFamily != gwFamily {
-			return fmt.Errorf("gateway, source, and destination ip were not the same IP family")
-		}
-		msg.Family = uint8(gwFamily)
-		var gwData []byte
-		if gwFamily == syscall.AF_INET {
-			gwData = gwIP.To4()
-		} else {
-			gwData = gwIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_GATEWAY, gwData))
-	}
-
-	wb.AddData(msg)
-	for _, attr := range rtAttrs {
-		wb.AddData(attr)
-	}
-
-	iface, err := net.InterfaceByName(device)
-	if err != nil {
-		return err
-	}
-	wb.AddData(uint32Attr(syscall.RTA_OIF, uint32(iface.Index)))
-
-	if err := s.Send(wb); err != nil {
-		return err
-	}
-	return s.HandleAck(wb.Seq)
-}
-
-// Add a new default gateway. Identical to:
-// ip route add default via $ip
-func AddDefaultGw(ip, device string) error {
-	return AddRoute("", "", ip, device)
-}
-
-// THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
-// IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
-// WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
-func getIfSocket() (fd int, err error) {
-	for _, socket := range []int{
-		syscall.AF_INET,
-		syscall.AF_PACKET,
-		syscall.AF_INET6,
-	} {
-		if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
-			break
-		}
-	}
-	if err == nil {
-		return fd, nil
-	}
-	return -1, err
-}
-
-// Create the actual bridge device.  This is more backward-compatible than
-// netlink.NetworkLinkAdd and works on RHEL 6.
-func CreateBridge(name string, setMacAddr bool) error {
-	if len(name) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", name)
-	}
-
-	s, err := getIfSocket()
-	if err != nil {
-		return err
-	}
-	defer syscall.Close(s)
-
-	nameBytePtr, err := syscall.BytePtrFromString(name)
-	if err != nil {
-		return err
-	}
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDBR, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
-		return err
-	}
-	if setMacAddr {
-		return SetMacAddress(name, randMacAddr())
-	}
-	return nil
-}
-
-// Delete the actual bridge device.
-func DeleteBridge(name string) error {
-	s, err := getIfSocket()
-	if err != nil {
-		return err
-	}
-	defer syscall.Close(s)
-
-	nameBytePtr, err := syscall.BytePtrFromString(name)
-	if err != nil {
-		return err
-	}
-
-	var ifr ifreqFlags
-	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], []byte(name))
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s),
-		syscall.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifr))); err != 0 {
-		return err
-	}
-
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s),
-		SIOC_BRDELBR, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
-		return err
-	}
-	return nil
-}
-
-// Add a slave to abridge device.  This is more backward-compatible than
-// netlink.NetworkSetMaster and works on RHEL 6.
-func AddToBridge(iface, master *net.Interface) error {
-	if len(master.Name) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", master.Name)
-	}
-
-	s, err := getIfSocket()
-	if err != nil {
-		return err
-	}
-	defer syscall.Close(s)
-
-	ifr := ifreqIndex{}
-	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
-	ifr.IfruIndex = int32(iface.Index)
-
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDIF, uintptr(unsafe.Pointer(&ifr))); err != 0 {
-		return err
-	}
-
-	return nil
-}
-
-func randMacAddr() string {
-	hw := make(net.HardwareAddr, 6)
-	for i := 0; i < 6; i++ {
-		hw[i] = byte(rand.Intn(255))
-	}
-	hw[0] &^= 0x1 // clear multicast bit
-	hw[0] |= 0x2  // set local assignment bit (IEEE802)
-	return hw.String()
-}
-
-func SetMacAddress(name, addr string) error {
-	if len(name) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", name)
-	}
-
-	hw, err := net.ParseMAC(addr)
-	if err != nil {
-		return err
-	}
-
-	s, err := getIfSocket()
-	if err != nil {
-		return err
-	}
-	defer syscall.Close(s)
-
-	ifr := ifreqHwaddr{}
-	ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
-	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
-
-	for i := 0; i < 6; i++ {
-		ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
-	}
-
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
-		return err
-	}
-	return nil
-}
-
-func SetHairpinMode(iface *net.Interface, enabled bool) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
-	}
-	defer s.Close()
-	req := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
-
-	msg := newIfInfomsg(syscall.AF_BRIDGE)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
-	msg.Index = int32(iface.Index)
-	msg.Change = DEFAULT_CHANGE
-	req.AddData(msg)
-
-	mode := []byte{0}
-	if enabled {
-		mode[0] = byte(1)
-	}
-
-	br := newRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil)
-	newRtAttrChild(br, IFLA_BRPORT_MODE, mode)
-	req.AddData(br)
-	if err := s.Send(req); err != nil {
-		return err
-	}
-
-	return s.HandleAck(req.Seq)
-}
-
-func ChangeName(iface *net.Interface, newName string) error {
-	if len(newName) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", newName)
-	}
-
-	fd, err := getIfSocket()
-	if err != nil {
-		return err
-	}
-	defer syscall.Close(fd)
-
-	data := [IFNAMSIZ * 2]byte{}
-	// the "-1"s here are very important for ensuring we get proper null
-	// termination of our new C strings
-	copy(data[:IFNAMSIZ-1], iface.Name)
-	copy(data[IFNAMSIZ:IFNAMSIZ*2-1], newName)
-
-	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 {
-		return errno
-	}
-
-	return nil
-}

+ 0 - 5
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_arm.go

@@ -1,5 +0,0 @@
-package netlink
-
-func ifrDataByte(b byte) uint8 {
-	return uint8(b)
-}

+ 0 - 7
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_notarm.go

@@ -1,7 +0,0 @@
-// +build !arm
-
-package netlink
-
-func ifrDataByte(b byte) int8 {
-	return int8(b)
-}

+ 0 - 408
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go

@@ -1,408 +0,0 @@
-package netlink
-
-import (
-	"net"
-	"strings"
-	"syscall"
-	"testing"
-)
-
-type testLink struct {
-	name     string
-	linkType string
-}
-
-func addLink(t *testing.T, name string, linkType string) {
-	if err := NetworkLinkAdd(name, linkType); err != nil {
-		t.Fatalf("Unable to create %s link: %s", name, err)
-	}
-}
-
-func readLink(t *testing.T, name string) *net.Interface {
-	iface, err := net.InterfaceByName(name)
-	if err != nil {
-		t.Fatalf("Could not find %s interface: %s", name, err)
-	}
-
-	return iface
-}
-
-func deleteLink(t *testing.T, name string) {
-	if err := NetworkLinkDel(name); err != nil {
-		t.Fatalf("Unable to delete %s link: %s", name, err)
-	}
-}
-
-func upLink(t *testing.T, name string) {
-	iface := readLink(t, name)
-	if err := NetworkLinkUp(iface); err != nil {
-		t.Fatalf("Could not bring UP %#v interface: %s", iface, err)
-	}
-}
-
-func downLink(t *testing.T, name string) {
-	iface := readLink(t, name)
-	if err := NetworkLinkDown(iface); err != nil {
-		t.Fatalf("Could not bring DOWN %#v interface: %s", iface, err)
-	}
-}
-
-func ipAssigned(iface *net.Interface, ip net.IP) bool {
-	addrs, _ := iface.Addrs()
-
-	for _, addr := range addrs {
-		args := strings.SplitN(addr.String(), "/", 2)
-		if args[0] == ip.String() {
-			return true
-		}
-	}
-
-	return false
-}
-
-func TestNetworkLinkAddDel(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	testLinks := []testLink{
-		{"tstEth", "dummy"},
-		{"tstBr", "bridge"},
-	}
-
-	for _, tl := range testLinks {
-		addLink(t, tl.name, tl.linkType)
-		defer deleteLink(t, tl.name)
-		readLink(t, tl.name)
-	}
-}
-
-func TestNetworkLinkUpDown(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := testLink{name: "tstEth", linkType: "dummy"}
-
-	addLink(t, tl.name, tl.linkType)
-	defer deleteLink(t, tl.name)
-
-	upLink(t, tl.name)
-	ifcAfterUp := readLink(t, tl.name)
-
-	if (ifcAfterUp.Flags & syscall.IFF_UP) != syscall.IFF_UP {
-		t.Fatalf("Could not bring UP %#v initerface", tl)
-	}
-
-	downLink(t, tl.name)
-	ifcAfterDown := readLink(t, tl.name)
-
-	if (ifcAfterDown.Flags & syscall.IFF_UP) == syscall.IFF_UP {
-		t.Fatalf("Could not bring DOWN %#v initerface", tl)
-	}
-}
-
-func TestNetworkSetMacAddress(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := testLink{name: "tstEth", linkType: "dummy"}
-	macaddr := "22:ce:e0:99:63:6f"
-
-	addLink(t, tl.name, tl.linkType)
-	defer deleteLink(t, tl.name)
-
-	ifcBeforeSet := readLink(t, tl.name)
-
-	if err := NetworkSetMacAddress(ifcBeforeSet, macaddr); err != nil {
-		t.Fatalf("Could not set %s MAC address on %#v interface: %s", macaddr, tl, err)
-	}
-
-	ifcAfterSet := readLink(t, tl.name)
-
-	if ifcAfterSet.HardwareAddr.String() != macaddr {
-		t.Fatalf("Could not set %s MAC address on %#v interface", macaddr, tl)
-	}
-}
-
-func TestNetworkSetMTU(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := testLink{name: "tstEth", linkType: "dummy"}
-	mtu := 1400
-
-	addLink(t, tl.name, tl.linkType)
-	defer deleteLink(t, tl.name)
-
-	ifcBeforeSet := readLink(t, tl.name)
-
-	if err := NetworkSetMTU(ifcBeforeSet, mtu); err != nil {
-		t.Fatalf("Could not set %d MTU on %#v interface: %s", mtu, tl, err)
-	}
-
-	ifcAfterSet := readLink(t, tl.name)
-
-	if ifcAfterSet.MTU != mtu {
-		t.Fatalf("Could not set %d MTU on %#v interface", mtu, tl)
-	}
-}
-
-func TestNetworkSetMasterNoMaster(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	master := testLink{"tstBr", "bridge"}
-	slave := testLink{"tstEth", "dummy"}
-	testLinks := []testLink{master, slave}
-
-	for _, tl := range testLinks {
-		addLink(t, tl.name, tl.linkType)
-		defer deleteLink(t, tl.name)
-		upLink(t, tl.name)
-	}
-
-	masterIfc := readLink(t, master.name)
-	slaveIfc := readLink(t, slave.name)
-	if err := NetworkSetMaster(slaveIfc, masterIfc); err != nil {
-		t.Fatalf("Could not set %#v to be the master of %#v: %s", master, slave, err)
-	}
-
-	// Trying to figure out a way to test which will not break on RHEL6.
-	// We could check for existence of /sys/class/net/tstEth/upper_tstBr
-	// which should point to the ../tstBr which is the UPPER device i.e. network bridge
-
-	if err := NetworkSetNoMaster(slaveIfc); err != nil {
-		t.Fatalf("Could not UNset %#v master of %#v: %s", master, slave, err)
-	}
-}
-
-func TestNetworkChangeName(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := testLink{"tstEth", "dummy"}
-	newName := "newTst"
-
-	addLink(t, tl.name, tl.linkType)
-
-	linkIfc := readLink(t, tl.name)
-	if err := NetworkChangeName(linkIfc, newName); err != nil {
-		deleteLink(t, tl.name)
-		t.Fatalf("Could not change %#v interface name to %s: %s", tl, newName, err)
-	}
-
-	readLink(t, newName)
-	deleteLink(t, newName)
-}
-
-func TestNetworkLinkAddVlan(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := struct {
-		name string
-		id   uint16
-	}{
-		name: "tstVlan",
-		id:   32,
-	}
-	masterLink := testLink{"tstEth", "dummy"}
-
-	addLink(t, masterLink.name, masterLink.linkType)
-	defer deleteLink(t, masterLink.name)
-
-	if err := NetworkLinkAddVlan(masterLink.name, tl.name, tl.id); err != nil {
-		t.Fatalf("Unable to create %#v VLAN interface: %s", tl, err)
-	}
-
-	readLink(t, tl.name)
-}
-
-func TestNetworkLinkAddMacVlan(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := struct {
-		name string
-		mode string
-	}{
-		name: "tstVlan",
-		mode: "private",
-	}
-	masterLink := testLink{"tstEth", "dummy"}
-
-	addLink(t, masterLink.name, masterLink.linkType)
-	defer deleteLink(t, masterLink.name)
-
-	if err := NetworkLinkAddMacVlan(masterLink.name, tl.name, tl.mode); err != nil {
-		t.Fatalf("Unable to create %#v MAC VLAN interface: %s", tl, err)
-	}
-
-	readLink(t, tl.name)
-}
-
-func TestNetworkLinkAddMacVtap(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	tl := struct {
-		name string
-		mode string
-	}{
-		name: "tstVtap",
-		mode: "private",
-	}
-	masterLink := testLink{"tstEth", "dummy"}
-
-	addLink(t, masterLink.name, masterLink.linkType)
-	defer deleteLink(t, masterLink.name)
-
-	if err := NetworkLinkAddMacVtap(masterLink.name, tl.name, tl.mode); err != nil {
-		t.Fatalf("Unable to create %#v MAC VTAP interface: %s", tl, err)
-	}
-
-	readLink(t, tl.name)
-}
-
-func TestAddDelNetworkIp(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	ifaceName := "lo"
-	ip := net.ParseIP("127.0.1.1")
-	mask := net.IPv4Mask(255, 255, 255, 255)
-	ipNet := &net.IPNet{IP: ip, Mask: mask}
-
-	iface, err := net.InterfaceByName(ifaceName)
-	if err != nil {
-		t.Skip("No 'lo' interface; skipping tests")
-	}
-
-	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
-		t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
-	}
-
-	if !ipAssigned(iface, ip) {
-		t.Fatalf("Could not locate address '%s' in lo address list.", ip.String())
-	}
-
-	if err := NetworkLinkDelIp(iface, ip, ipNet); err != nil {
-		t.Fatalf("Could not delete IP address %s from interface %#v: %s", ip.String(), iface, err)
-	}
-
-	if ipAssigned(iface, ip) {
-		t.Fatalf("Located address '%s' in lo address list after removal.", ip.String())
-	}
-}
-
-func TestAddRouteSourceSelection(t *testing.T) {
-	tstIp := "127.1.1.1"
-	tl := testLink{name: "tstEth", linkType: "dummy"}
-
-	addLink(t, tl.name, tl.linkType)
-	defer deleteLink(t, tl.name)
-
-	ip := net.ParseIP(tstIp)
-	mask := net.IPv4Mask(255, 255, 255, 255)
-	ipNet := &net.IPNet{IP: ip, Mask: mask}
-
-	iface, err := net.InterfaceByName(tl.name)
-	if err != nil {
-		t.Fatalf("Lost created link %#v", tl)
-	}
-
-	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
-		t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
-	}
-
-	upLink(t, tl.name)
-	defer downLink(t, tl.name)
-
-	if err := AddRoute("127.0.0.0/8", tstIp, "", tl.name); err != nil {
-		t.Fatalf("Failed to add route with source address")
-	}
-}
-
-func TestCreateVethPair(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	var (
-		name1 = "veth1"
-		name2 = "veth2"
-	)
-
-	if err := NetworkCreateVethPair(name1, name2, 0); err != nil {
-		t.Fatalf("Could not create veth pair %s %s: %s", name1, name2, err)
-	}
-	defer NetworkLinkDel(name1)
-
-	readLink(t, name1)
-	readLink(t, name2)
-}
-
-//
-// netlink package tests which do not use RTNETLINK
-//
-func TestCreateBridgeWithMac(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	name := "testbridge"
-
-	if err := CreateBridge(name, true); err != nil {
-		t.Fatal(err)
-	}
-
-	if _, err := net.InterfaceByName(name); err != nil {
-		t.Fatal(err)
-	}
-
-	// cleanup and tests
-
-	if err := DeleteBridge(name); err != nil {
-		t.Fatal(err)
-	}
-
-	if _, err := net.InterfaceByName(name); err == nil {
-		t.Fatalf("expected error getting interface because %s bridge was deleted", name)
-	}
-}
-
-func TestSetMacAddress(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	name := "testmac"
-	mac := randMacAddr()
-
-	if err := NetworkLinkAdd(name, "bridge"); err != nil {
-		t.Fatal(err)
-	}
-	defer NetworkLinkDel(name)
-
-	if err := SetMacAddress(name, mac); err != nil {
-		t.Fatal(err)
-	}
-
-	iface, err := net.InterfaceByName(name)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if iface.HardwareAddr.String() != mac {
-		t.Fatalf("mac address %q does not match %q", iface.HardwareAddr, mac)
-	}
-}

+ 0 - 88
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_unsupported.go

@@ -1,88 +0,0 @@
-// +build !linux
-
-package netlink
-
-import (
-	"errors"
-	"net"
-)
-
-var (
-	ErrNotImplemented = errors.New("not implemented")
-)
-
-func NetworkGetRoutes() ([]Route, error) {
-	return nil, ErrNotImplemented
-}
-
-func NetworkLinkAdd(name string, linkType string) error {
-	return ErrNotImplemented
-}
-
-func NetworkLinkDel(name string) error {
-	return ErrNotImplemented
-}
-
-func NetworkLinkUp(iface *net.Interface) error {
-	return ErrNotImplemented
-}
-
-func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return ErrNotImplemented
-}
-
-func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return ErrNotImplemented
-}
-
-func AddRoute(destination, source, gateway, device string) error {
-	return ErrNotImplemented
-}
-
-func AddDefaultGw(ip, device string) error {
-	return ErrNotImplemented
-}
-
-func NetworkSetMTU(iface *net.Interface, mtu int) error {
-	return ErrNotImplemented
-}
-
-func NetworkSetTxQueueLen(iface *net.Interface, txQueueLen int) error {
-	return ErrNotImplemented
-}
-
-func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error {
-	return ErrNotImplemented
-}
-
-func NetworkChangeName(iface *net.Interface, newName string) error {
-	return ErrNotImplemented
-}
-
-func NetworkSetNsFd(iface *net.Interface, fd int) error {
-	return ErrNotImplemented
-}
-
-func NetworkSetNsPid(iface *net.Interface, nspid int) error {
-	return ErrNotImplemented
-}
-
-func NetworkSetMaster(iface, master *net.Interface) error {
-	return ErrNotImplemented
-}
-
-func NetworkLinkDown(iface *net.Interface) error {
-	return ErrNotImplemented
-}
-
-func CreateBridge(name string, setMacAddr bool) error {
-	return ErrNotImplemented
-}
-
-func DeleteBridge(name string) error {
-	return ErrNotImplemented
-}
-
-func AddToBridge(iface, master *net.Interface) error {
-	return ErrNotImplemented
-}

+ 17 - 0
libnetwork/drivers/bridge/bridge.go

@@ -2,8 +2,11 @@ package bridge
 
 import (
 	"net"
+	"sync"
 
 	"github.com/docker/libnetwork"
+	"github.com/docker/libnetwork/ipallocator"
+	"github.com/docker/libnetwork/portmapper"
 )
 
 const (
@@ -11,6 +14,18 @@ const (
 	vethPrefix  = "veth"
 )
 
+var (
+	once        sync.Once
+	ipAllocator *ipallocator.IPAllocator
+	portMapper  *portmapper.PortMapper
+)
+
+func initPortMapper() {
+	once.Do(func() {
+		portMapper = portmapper.New()
+	})
+}
+
 // Configuration info for the "simplebridge" driver.
 type Configuration struct {
 	BridgeName         string
@@ -27,6 +42,8 @@ type Configuration struct {
 type driver struct{}
 
 func init() {
+	ipAllocator = ipallocator.New()
+	initPortMapper()
 	libnetwork.RegisterNetworkType(networkType, &driver{}, &Configuration{})
 }
 

+ 2 - 3
libnetwork/drivers/bridge/network.go

@@ -7,7 +7,6 @@ import (
 
 	"github.com/docker/libcontainer/utils"
 	"github.com/docker/libnetwork"
-	"github.com/docker/libnetwork/ipallocator"
 	"github.com/vishvananda/netlink"
 )
 
@@ -78,14 +77,14 @@ func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) {
 		return nil, err
 	}
 
-	ip4, err := ipallocator.RequestIP(b.bridge.bridgeIPv4, nil)
+	ip4, err := ipAllocator.RequestIP(b.bridge.bridgeIPv4, nil)
 	if err != nil {
 		return nil, err
 	}
 	ipv4Addr := net.IPNet{IP: ip4, Mask: b.bridge.bridgeIPv4.Mask}
 
 	if b.bridge.Config.EnableIPv6 {
-		ip6, err := ipallocator.RequestIP(b.bridge.bridgeIPv6, nil)
+		ip6, err := ipAllocator.RequestIP(b.bridge.bridgeIPv6, nil)
 		if err != nil {
 			return nil, err
 		}

+ 1 - 2
libnetwork/drivers/bridge/setup_fixedcidrv4.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 
 	log "github.com/Sirupsen/logrus"
-	"github.com/docker/libnetwork/ipallocator"
 )
 
 func setupFixedCIDRv4(i *bridgeInterface) error {
@@ -14,7 +13,7 @@ func setupFixedCIDRv4(i *bridgeInterface) error {
 	}
 
 	log.Debugf("Using IPv4 subnet: %v", i.Config.FixedCIDR)
-	if err := ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR); err != nil {
+	if err := ipAllocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR); err != nil {
 		return fmt.Errorf("Setup FixedCIDRv4 failed for subnet %s in %s: %v", i.Config.FixedCIDR, addrv4.IPNet, err)
 	}
 

+ 1 - 2
libnetwork/drivers/bridge/setup_fixedcidrv4_test.go

@@ -5,7 +5,6 @@ import (
 	"testing"
 
 	"github.com/docker/libnetwork"
-	"github.com/docker/libnetwork/ipallocator"
 )
 
 func TestSetupFixedCIDRv4(t *testing.T) {
@@ -29,7 +28,7 @@ func TestSetupFixedCIDRv4(t *testing.T) {
 		t.Fatalf("Failed to setup bridge FixedCIDRv4: %v", err)
 	}
 
-	if ip, err := ipallocator.RequestIP(br.Config.FixedCIDR, nil); err != nil {
+	if ip, err := ipAllocator.RequestIP(br.Config.FixedCIDR, nil); err != nil {
 		t.Fatalf("Failed to request IP to allocator: %v", err)
 	} else if expected := "192.168.2.1"; ip.String() != expected {
 		t.Fatalf("Expected allocated IP %s, got %s", expected, ip)

+ 1 - 2
libnetwork/drivers/bridge/setup_fixedcidrv6.go

@@ -4,12 +4,11 @@ import (
 	"fmt"
 
 	log "github.com/Sirupsen/logrus"
-	"github.com/docker/libnetwork/ipallocator"
 )
 
 func setupFixedCIDRv6(i *bridgeInterface) error {
 	log.Debugf("Using IPv6 subnet: %v", i.Config.FixedCIDRv6)
-	if err := ipallocator.RegisterSubnet(i.Config.FixedCIDRv6, i.Config.FixedCIDRv6); err != nil {
+	if err := ipAllocator.RegisterSubnet(i.Config.FixedCIDRv6, i.Config.FixedCIDRv6); err != nil {
 		return fmt.Errorf("Setup FixedCIDRv6 failed for subnet %s in %s: %v", i.Config.FixedCIDRv6, i.Config.FixedCIDRv6, err)
 	}
 

+ 1 - 2
libnetwork/drivers/bridge/setup_fixedcidrv6_test.go

@@ -5,7 +5,6 @@ import (
 	"testing"
 
 	"github.com/docker/libnetwork"
-	"github.com/docker/libnetwork/ipallocator"
 )
 
 func TestSetupFixedCIDRv6(t *testing.T) {
@@ -29,7 +28,7 @@ func TestSetupFixedCIDRv6(t *testing.T) {
 		t.Fatalf("Failed to setup bridge FixedCIDRv6: %v", err)
 	}
 
-	if ip, err := ipallocator.RequestIP(br.Config.FixedCIDRv6, nil); err != nil {
+	if ip, err := ipAllocator.RequestIP(br.Config.FixedCIDRv6, nil); err != nil {
 		t.Fatalf("Failed to request IP to allocator: %v", err)
 	} else if expected := "2002:db8::1"; ip.String() != expected {
 		t.Fatalf("Expected allocated IP %s, got %s", expected, ip)

+ 36 - 23
libnetwork/drivers/bridge/setup_ip_tables.go

@@ -6,7 +6,6 @@ import (
 
 	"github.com/docker/docker/pkg/iptables"
 	"github.com/docker/libnetwork"
-	"github.com/docker/libnetwork/portmapper"
 )
 
 // DockerChain: DOCKER iptable chain name
@@ -38,17 +37,25 @@ func setupIPTables(i *bridgeInterface) error {
 		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
 	}
 
-	portmapper.SetIptablesChain(chain)
+	portMapper.SetIptablesChain(chain)
 
 	return nil
 }
 
+type iptRule struct {
+	table   iptables.Table
+	chain   string
+	preArgs []string
+	args    []string
+}
+
 func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, enable bool) error {
+
 	var (
 		address = addr.String()
-		natRule = []string{"POSTROUTING", "-t", "nat", "-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}
-		outRule = []string{"FORWARD", "-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}
-		inRule  = []string{"FORWARD", "-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
+		natRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}}
+		outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
+		inRule  = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}
 	)
 
 	// Set NAT.
@@ -76,28 +83,32 @@ func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, enabl
 	return nil
 }
 
-func programChainRule(ruleArgs []string, ruleDescr string, insert bool) error {
+func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
 	var (
 		prefix    []string
 		operation string
 		condition bool
+		doesExist = iptables.Exists(rule.table, rule.chain, rule.args...)
 	)
 
 	if insert {
-		condition = !iptables.Exists(ruleArgs...)
-		prefix = []string{"-I"}
+		condition = !doesExist
+		prefix = []string{"-I", rule.chain}
 		operation = "enable"
 	} else {
-		condition = iptables.Exists(ruleArgs...)
-		prefix = []string{"-D"}
+		condition = doesExist
+		prefix = []string{"-D", rule.chain}
 		operation = "disable"
 	}
+	if rule.preArgs != nil {
+		prefix = append(rule.preArgs, prefix...)
+	}
 
 	if condition {
-		if output, err := iptables.Raw(append(prefix, ruleArgs...)...); err != nil {
+		if output, err := iptables.Raw(append(prefix, rule.args...)...); err != nil {
 			return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
 		} else if len(output) != 0 {
-			return &iptables.ChainError{Chain: ruleDescr, Output: output}
+			return &iptables.ChainError{Chain: rule.chain, Output: output}
 		}
 	}
 
@@ -106,27 +117,29 @@ func programChainRule(ruleArgs []string, ruleDescr string, insert bool) error {
 
 func setIcc(bridgeIface string, iccEnable, insert bool) error {
 	var (
-		args       = []string{"FORWARD", "-i", bridgeIface, "-o", bridgeIface, "-j"}
+		table      = iptables.Filter
+		chain      = "FORWARD"
+		args       = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
 		acceptArgs = append(args, "ACCEPT")
 		dropArgs   = append(args, "DROP")
 	)
 
 	if insert {
 		if !iccEnable {
-			iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
+			iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
 
-			if !iptables.Exists(dropArgs...) {
-				if output, err := iptables.Raw(append([]string{"-I"}, dropArgs...)...); err != nil {
+			if !iptables.Exists(table, chain, dropArgs...) {
+				if output, err := iptables.Raw(append([]string{"-I", chain}, dropArgs...)...); err != nil {
 					return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
 				} else if len(output) != 0 {
 					return fmt.Errorf("Error disabling intercontainer communication: %s", output)
 				}
 			}
 		} else {
-			iptables.Raw(append([]string{"-D"}, dropArgs...)...)
+			iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
 
-			if !iptables.Exists(acceptArgs...) {
-				if output, err := iptables.Raw(append([]string{"-I"}, acceptArgs...)...); err != nil {
+			if !iptables.Exists(table, chain, acceptArgs...) {
+				if output, err := iptables.Raw(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
 					return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
 				} else if len(output) != 0 {
 					return fmt.Errorf("Error enabling intercontainer communication: %s", output)
@@ -136,12 +149,12 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
 	} else {
 		// Remove any ICC rule.
 		if !iccEnable {
-			if iptables.Exists(dropArgs...) {
-				iptables.Raw(append([]string{"-D"}, dropArgs...)...)
+			if iptables.Exists(table, chain, dropArgs...) {
+				iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
 			}
 		} else {
-			if iptables.Exists(acceptArgs...) {
-				iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
+			if iptables.Exists(table, chain, acceptArgs...) {
+				iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
 			}
 		}
 	}

+ 15 - 14
libnetwork/drivers/bridge/setup_ip_tables_test.go

@@ -19,19 +19,20 @@ func TestProgramIPTable(t *testing.T) {
 
 	// Store various iptables chain rules we care for.
 	rules := []struct {
-		ruleArgs []string
-		descr    string
-	}{{[]string{"FORWARD", "-d", "127.1.2.3", "-i", "lo", "-o", "lo", "-j", "DROP"}, "Test Loopback"},
-		{[]string{"POSTROUTING", "-t", "nat", "-s", iptablesTestBridgeIP, "!", "-o", DefaultBridgeName, "-j", "MASQUERADE"}, "NAT Test"},
-		{[]string{"FORWARD", "-i", DefaultBridgeName, "!", "-o", DefaultBridgeName, "-j", "ACCEPT"}, "Test ACCEPT NON_ICC OUTGOING"},
-		{[]string{"FORWARD", "-o", DefaultBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}, "Test ACCEPT INCOMING"},
-		{[]string{"FORWARD", "-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "ACCEPT"}, "Test enable ICC"},
-		{[]string{"FORWARD", "-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "DROP"}, "Test disable ICC"},
+		rule  iptRule
+		descr string
+	}{
+		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-d", "127.1.2.3", "-i", "lo", "-o", "lo", "-j", "DROP"}}, "Test Loopback"},
+		{iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", iptablesTestBridgeIP, "!", "-o", DefaultBridgeName, "-j", "MASQUERADE"}}, "NAT Test"},
+		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "!", "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test ACCEPT NON_ICC OUTGOING"},
+		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", DefaultBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}, "Test ACCEPT INCOMING"},
+		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test enable ICC"},
+		{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "DROP"}}, "Test disable ICC"},
 	}
 
 	// Assert the chain rules' insertion and removal.
 	for _, c := range rules {
-		assertIPTableChainProgramming(c.ruleArgs, c.descr, t)
+		assertIPTableChainProgramming(c.rule, c.descr, t)
 	}
 }
 
@@ -74,20 +75,20 @@ func createTestBridge(br *bridgeInterface, t *testing.T) {
 }
 
 // Assert base function which pushes iptables chain rules on insertion and removal.
-func assertIPTableChainProgramming(args []string, descr string, t *testing.T) {
+func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
 	// Add
-	if err := programChainRule(args, descr, true); err != nil {
+	if err := programChainRule(rule, descr, true); err != nil {
 		t.Fatalf("Failed to program iptable rule %s: %s", descr, err.Error())
 	}
-	if iptables.Exists(args...) == false {
+	if iptables.Exists(rule.table, rule.chain, rule.args...) == false {
 		t.Fatalf("Failed to effectively program iptable rule: %s", descr)
 	}
 
 	// Remove
-	if err := programChainRule(args, descr, false); err != nil {
+	if err := programChainRule(rule, descr, false); err != nil {
 		t.Fatalf("Failed to remove iptable rule %s: %s", descr, err.Error())
 	}
-	if iptables.Exists(args...) == true {
+	if iptables.Exists(rule.table, rule.chain, rule.args...) == true {
 		t.Fatalf("Failed to effectively remove iptable rule: %s", descr)
 	}
 }

+ 30 - 21
libnetwork/ipallocator/allocator.go

@@ -8,7 +8,7 @@ import (
 	"net"
 	"sync"
 
-	log "github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork"
 )
 
@@ -48,19 +48,26 @@ var (
 	ErrBadSubnet = errors.New("network does not contain specified subnet")
 )
 
-var (
-	lock         = sync.Mutex{}
-	allocatedIPs = networkSet{}
-)
+// IPAllocator manages the ipam
+type IPAllocator struct {
+	allocatedIPs networkSet
+	mutex        sync.Mutex
+}
+
+// New returns a new instance of IPAllocator
+func New() *IPAllocator {
+	return &IPAllocator{networkSet{}, sync.Mutex{}}
+}
 
 // RegisterSubnet registers network in global allocator with bounds
 // defined by subnet. If you want to use network range you must call
 // this method before first RequestIP, otherwise full network range will be used
-func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
-	lock.Lock()
-	defer lock.Unlock()
+func (a *IPAllocator) RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
+	a.mutex.Lock()
+	defer a.mutex.Unlock()
+
 	key := network.String()
-	if _, ok := allocatedIPs[key]; ok {
+	if _, ok := a.allocatedIPs[key]; ok {
 		return ErrNetworkAlreadyRegistered
 	}
 	n := newAllocatedMap(network)
@@ -75,7 +82,7 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
 	n.begin.Set(begin)
 	n.end.Set(end)
 	n.last.Sub(begin, big.NewInt(1))
-	allocatedIPs[key] = n
+	a.allocatedIPs[key] = n
 	return nil
 }
 
@@ -83,14 +90,15 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
 // will return the next available ip if the ip provided is nil.  If the
 // ip provided is not nil it will validate that the provided ip is available
 // for use or return an error
-func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
-	lock.Lock()
-	defer lock.Unlock()
+func (a *IPAllocator) RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
+	a.mutex.Lock()
+	defer a.mutex.Unlock()
+
 	key := network.String()
-	allocated, ok := allocatedIPs[key]
+	allocated, ok := a.allocatedIPs[key]
 	if !ok {
 		allocated = newAllocatedMap(network)
-		allocatedIPs[key] = allocated
+		a.allocatedIPs[key] = allocated
 	}
 
 	if ip == nil {
@@ -101,10 +109,11 @@ func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
 
 // ReleaseIP adds the provided ip back into the pool of
 // available ips to be returned for use.
-func ReleaseIP(network *net.IPNet, ip net.IP) error {
-	lock.Lock()
-	defer lock.Unlock()
-	if allocated, exists := allocatedIPs[network.String()]; exists {
+func (a *IPAllocator) ReleaseIP(network *net.IPNet, ip net.IP) error {
+	a.mutex.Lock()
+	defer a.mutex.Unlock()
+
+	if allocated, exists := a.allocatedIPs[network.String()]; exists {
 		delete(allocated.p, ip.String())
 	}
 	return nil
@@ -128,7 +137,7 @@ func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
 }
 
 // return an available ip if one is currently available.  If not,
-// return the next available ip for the nextwork
+// return the next available ip for the network
 func (allocated *allocatedMap) getNextIP() (net.IP, error) {
 	pos := big.NewInt(0).Set(allocated.last)
 	allRange := big.NewInt(0).Sub(allocated.end, allocated.begin)
@@ -157,7 +166,7 @@ func ipToBigInt(ip net.IP) *big.Int {
 		return x.SetBytes(ip6)
 	}
 
-	log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
+	logrus.Errorf("ipToBigInt: Wrong IP length! %s", ip)
 	return nil
 }
 

+ 95 - 86
libnetwork/ipallocator/allocator_test.go

@@ -7,10 +7,6 @@ import (
 	"testing"
 )
 
-func reset() {
-	allocatedIPs = networkSet{}
-}
-
 func TestConversion(t *testing.T) {
 	ip := net.ParseIP("127.0.0.1")
 	i := ipToBigInt(ip)
@@ -52,7 +48,8 @@ func TestConversionIPv6(t *testing.T) {
 }
 
 func TestRequestNewIps(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -62,7 +59,7 @@ func TestRequestNewIps(t *testing.T) {
 	var err error
 
 	for i := 1; i < 10; i++ {
-		ip, err = RequestIP(network, nil)
+		ip, err = a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -72,10 +69,10 @@ func TestRequestNewIps(t *testing.T) {
 		}
 	}
 	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
-	ip, err = RequestIP(network, nil)
+	ip, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -85,7 +82,8 @@ func TestRequestNewIps(t *testing.T) {
 }
 
 func TestRequestNewIpV6(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
 		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
@@ -94,7 +92,7 @@ func TestRequestNewIpV6(t *testing.T) {
 	var ip net.IP
 	var err error
 	for i := 1; i < 10; i++ {
-		ip, err = RequestIP(network, nil)
+		ip, err = a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -104,10 +102,10 @@ func TestRequestNewIpV6(t *testing.T) {
 		}
 	}
 	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
-	ip, err = RequestIP(network, nil)
+	ip, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -117,68 +115,70 @@ func TestRequestNewIpV6(t *testing.T) {
 }
 
 func TestReleaseIp(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
 	}
 
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestReleaseIpV6(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
 		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
 	}
 
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestGetReleasedIp(t *testing.T) {
-	defer reset()
+	a := New()
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
 	}
 
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	value := ip.String()
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 
 	for i := 0; i < 253; i++ {
-		_, err = RequestIP(network, nil)
+		_, err = a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
-		err = ReleaseIP(network, ip)
+		err = a.ReleaseIP(network, ip)
 		if err != nil {
 			t.Fatal(err)
 		}
 	}
 
-	ip, err = RequestIP(network, nil)
+	ip, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -189,34 +189,35 @@ func TestGetReleasedIp(t *testing.T) {
 }
 
 func TestGetReleasedIpV6(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
 		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
 	}
 
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	value := ip.String()
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 
 	for i := 0; i < 253; i++ {
-		_, err = RequestIP(network, nil)
+		_, err = a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
-		err = ReleaseIP(network, ip)
+		err = a.ReleaseIP(network, ip)
 		if err != nil {
 			t.Fatal(err)
 		}
 	}
 
-	ip, err = RequestIP(network, nil)
+	ip, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -227,7 +228,8 @@ func TestGetReleasedIpV6(t *testing.T) {
 }
 
 func TestRequestSpecificIp(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 224},
@@ -236,23 +238,24 @@ func TestRequestSpecificIp(t *testing.T) {
 	ip := net.ParseIP("192.168.0.5")
 
 	// Request a "good" IP.
-	if _, err := RequestIP(network, ip); err != nil {
+	if _, err := a.RequestIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 
 	// Request the same IP again.
-	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
+	if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
 		t.Fatalf("Got the same IP twice: %#v", err)
 	}
 
 	// Request an out of range IP.
-	if _, err := RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
+	if _, err := a.RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
 		t.Fatalf("Got an out of range IP: %#v", err)
 	}
 }
 
 func TestRequestSpecificIpV6(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
 		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
@@ -261,22 +264,24 @@ func TestRequestSpecificIpV6(t *testing.T) {
 	ip := net.ParseIP("2a00:1450::5")
 
 	// Request a "good" IP.
-	if _, err := RequestIP(network, ip); err != nil {
+	if _, err := a.RequestIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 
 	// Request the same IP again.
-	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
+	if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
 		t.Fatalf("Got the same IP twice: %#v", err)
 	}
 
 	// Request an out of range IP.
-	if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
+	if _, err := a.RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
 		t.Fatalf("Got an out of range IP: %#v", err)
 	}
 }
 
 func TestIPAllocator(t *testing.T) {
+	a := New()
+
 	expectedIPs := []net.IP{
 		0: net.IPv4(127, 0, 0, 1),
 		1: net.IPv4(127, 0, 0, 2),
@@ -296,7 +301,7 @@ func TestIPAllocator(t *testing.T) {
 	// Check that we get 6 IPs, from 127.0.0.1–127.0.0.6, in that
 	// order.
 	for i := 0; i < 6; i++ {
-		ip, err := RequestIP(network, nil)
+		ip, err := a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -332,25 +337,25 @@ func TestIPAllocator(t *testing.T) {
 	//  ↑
 
 	// Check that there are no more IPs
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err == nil {
 		t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
 	}
 
 	// Release some IPs in non-sequential order
-	if err := ReleaseIP(network, expectedIPs[3]); err != nil {
+	if err := a.ReleaseIP(network, expectedIPs[3]); err != nil {
 		t.Fatal(err)
 	}
 	// 1(u) - 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
 	//                       ↑
 
-	if err := ReleaseIP(network, expectedIPs[2]); err != nil {
+	if err := a.ReleaseIP(network, expectedIPs[2]); err != nil {
 		t.Fatal(err)
 	}
 	// 1(u) - 2(u) - 3(f) - 4(f) - 5(u) - 6(u)
 	//                ↑
 
-	if err := ReleaseIP(network, expectedIPs[4]); err != nil {
+	if err := a.ReleaseIP(network, expectedIPs[4]); err != nil {
 		t.Fatal(err)
 	}
 	// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(u)
@@ -360,7 +365,7 @@ func TestIPAllocator(t *testing.T) {
 	// with the first released IP
 	newIPs := make([]net.IP, 3)
 	for i := 0; i < 3; i++ {
-		ip, err := RequestIP(network, nil)
+		ip, err := a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -371,14 +376,15 @@ func TestIPAllocator(t *testing.T) {
 	assertIPEquals(t, expectedIPs[3], newIPs[1])
 	assertIPEquals(t, expectedIPs[4], newIPs[2])
 
-	_, err = RequestIP(network, nil)
+	_, err = a.RequestIP(network, nil)
 	if err == nil {
 		t.Fatal("There shouldn't be any IP addresses at this point")
 	}
 }
 
 func TestAllocateFirstIP(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 0},
 		Mask: []byte{255, 255, 255, 0},
@@ -387,7 +393,7 @@ func TestAllocateFirstIP(t *testing.T) {
 	firstIP := network.IP.To4().Mask(network.Mask)
 	first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
 
-	ip, err := RequestIP(network, nil)
+	ip, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -399,7 +405,8 @@ func TestAllocateFirstIP(t *testing.T) {
 }
 
 func TestAllocateAllIps(t *testing.T) {
-	defer reset()
+	a := New()
+
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -412,7 +419,7 @@ func TestAllocateAllIps(t *testing.T) {
 	)
 
 	for err == nil {
-		current, err = RequestIP(network, nil)
+		current, err = a.RequestIP(network, nil)
 		if isFirst {
 			first = current
 			isFirst = false
@@ -423,15 +430,15 @@ func TestAllocateAllIps(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+	if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
 		t.Fatal(err)
 	}
 
-	if err := ReleaseIP(network, first); err != nil {
+	if err := a.ReleaseIP(network, first); err != nil {
 		t.Fatal(err)
 	}
 
-	again, err := RequestIP(network, nil)
+	again, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -439,17 +446,17 @@ func TestAllocateAllIps(t *testing.T) {
 	assertIPEquals(t, first, again)
 
 	// ensure that alloc.last == alloc.begin won't result in dead loop
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+	if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
 		t.Fatal(err)
 	}
 
 	// Test by making alloc.last the only free ip and ensure we get it back
 	// #1. first of the range, (alloc.last == ipToInt(first) already)
-	if err := ReleaseIP(network, first); err != nil {
+	if err := a.ReleaseIP(network, first); err != nil {
 		t.Fatal(err)
 	}
 
-	ret, err := RequestIP(network, nil)
+	ret, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -458,9 +465,9 @@ func TestAllocateAllIps(t *testing.T) {
 
 	// #2. last of the range, note that current is the last one
 	last := net.IPv4(192, 168, 0, 254)
-	setLastTo(t, network, last)
+	setLastTo(t, a, network, last)
 
-	ret, err = RequestIP(network, nil)
+	ret, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -469,9 +476,9 @@ func TestAllocateAllIps(t *testing.T) {
 
 	// #3. middle of the range
 	mid := net.IPv4(192, 168, 0, 7)
-	setLastTo(t, network, mid)
+	setLastTo(t, a, network, mid)
 
-	ret, err = RequestIP(network, nil)
+	ret, err = a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -481,25 +488,25 @@ func TestAllocateAllIps(t *testing.T) {
 
 // make sure the pool is full when calling setLastTo.
 // we don't cheat here
-func setLastTo(t *testing.T, network *net.IPNet, ip net.IP) {
-	if err := ReleaseIP(network, ip); err != nil {
+func setLastTo(t *testing.T, a *IPAllocator, network *net.IPNet, ip net.IP) {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 
-	ret, err := RequestIP(network, nil)
+	ret, err := a.RequestIP(network, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	assertIPEquals(t, ip, ret)
 
-	if err := ReleaseIP(network, ip); err != nil {
+	if err := a.ReleaseIP(network, ip); err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestAllocateDifferentSubnets(t *testing.T) {
-	defer reset()
+	a := New()
 	network1 := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -528,39 +535,39 @@ func TestAllocateDifferentSubnets(t *testing.T) {
 		8: net.ParseIP("2a00:1632::2"),
 	}
 
-	ip11, err := RequestIP(network1, nil)
+	ip11, err := a.RequestIP(network1, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip12, err := RequestIP(network1, nil)
+	ip12, err := a.RequestIP(network1, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip21, err := RequestIP(network2, nil)
+	ip21, err := a.RequestIP(network2, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip22, err := RequestIP(network2, nil)
+	ip22, err := a.RequestIP(network2, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip31, err := RequestIP(network3, nil)
+	ip31, err := a.RequestIP(network3, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip32, err := RequestIP(network3, nil)
+	ip32, err := a.RequestIP(network3, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip33, err := RequestIP(network3, nil)
+	ip33, err := a.RequestIP(network3, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip41, err := RequestIP(network4, nil)
+	ip41, err := a.RequestIP(network4, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	ip42, err := RequestIP(network4, nil)
+	ip42, err := a.RequestIP(network4, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -576,7 +583,7 @@ func TestAllocateDifferentSubnets(t *testing.T) {
 }
 
 func TestRegisterBadTwice(t *testing.T) {
-	defer reset()
+	a := New()
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 1, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -586,20 +593,20 @@ func TestRegisterBadTwice(t *testing.T) {
 		Mask: []byte{255, 255, 255, 248},
 	}
 
-	if err := RegisterSubnet(network, subnet); err != nil {
+	if err := a.RegisterSubnet(network, subnet); err != nil {
 		t.Fatal(err)
 	}
 	subnet = &net.IPNet{
 		IP:   []byte{192, 168, 1, 16},
 		Mask: []byte{255, 255, 255, 248},
 	}
-	if err := RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
+	if err := a.RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
 		t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err)
 	}
 }
 
 func TestRegisterBadRange(t *testing.T) {
-	defer reset()
+	a := New()
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 1, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -608,13 +615,13 @@ func TestRegisterBadRange(t *testing.T) {
 		IP:   []byte{192, 168, 1, 1},
 		Mask: []byte{255, 255, 0, 0},
 	}
-	if err := RegisterSubnet(network, subnet); err != ErrBadSubnet {
+	if err := a.RegisterSubnet(network, subnet); err != ErrBadSubnet {
 		t.Fatalf("Expected ErrBadSubnet error, got %v", err)
 	}
 }
 
 func TestAllocateFromRange(t *testing.T) {
-	defer reset()
+	a := New()
 	network := &net.IPNet{
 		IP:   []byte{192, 168, 0, 1},
 		Mask: []byte{255, 255, 255, 0},
@@ -625,7 +632,7 @@ func TestAllocateFromRange(t *testing.T) {
 		Mask: []byte{255, 255, 255, 248},
 	}
 
-	if err := RegisterSubnet(network, subnet); err != nil {
+	if err := a.RegisterSubnet(network, subnet); err != nil {
 		t.Fatal(err)
 	}
 	expectedIPs := []net.IP{
@@ -637,19 +644,19 @@ func TestAllocateFromRange(t *testing.T) {
 		5: net.IPv4(192, 168, 0, 14),
 	}
 	for _, ip := range expectedIPs {
-		rip, err := RequestIP(network, nil)
+		rip, err := a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
 		assertIPEquals(t, ip, rip)
 	}
 
-	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+	if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
 		t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err)
 	}
 	for _, ip := range expectedIPs {
-		ReleaseIP(network, ip)
-		rip, err := RequestIP(network, nil)
+		a.ReleaseIP(network, ip)
+		rip, err := a.RequestIP(network, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -669,13 +676,15 @@ func BenchmarkRequestIP(b *testing.B) {
 		Mask: []byte{255, 255, 255, 0},
 	}
 	b.ResetTimer()
+
 	for i := 0; i < b.N; i++ {
+		a := New()
+
 		for j := 0; j < 253; j++ {
-			_, err := RequestIP(network, nil)
+			_, err := a.RequestIP(network, nil)
 			if err != nil {
 				b.Fatal(err)
 			}
 		}
-		reset()
 	}
 }

+ 88 - 51
libnetwork/portallocator/portallocator.go

@@ -1,54 +1,31 @@
 package portallocator
 
 import (
+	"bufio"
 	"errors"
 	"fmt"
 	"net"
+	"os"
 	"sync"
-)
-
-type portMap struct {
-	p    map[int]struct{}
-	last int
-}
-
-func newPortMap() *portMap {
-	return &portMap{
-		p:    map[int]struct{}{},
-		last: EndPortRange,
-	}
-}
-
-type protoMap map[string]*portMap
-
-func newProtoMap() protoMap {
-	return protoMap{
-		"tcp": newPortMap(),
-		"udp": newPortMap(),
-	}
-}
 
-type ipMapping map[string]protoMap
+	"github.com/Sirupsen/logrus"
+)
 
 const (
-	// BeginPortRange indicates the first port in port range
-	BeginPortRange = 49153
-	// EndPortRange indicates the last port in port range
-	EndPortRange = 65535
+	// DefaultPortRangeStart indicates the first port in port range
+	DefaultPortRangeStart = 49153
+	// DefaultPortRangeEnd indicates the last port in port range
+	DefaultPortRangeEnd = 65535
 )
 
+type ipMapping map[string]protoMap
+
 var (
 	// ErrAllPortsAllocated is returned when no more ports are available
 	ErrAllPortsAllocated = errors.New("all ports are allocated")
 	// ErrUnknownProtocol is returned when an unknown protocol was specified
 	ErrUnknownProtocol = errors.New("unknown protocol")
-)
-
-var (
-	mutex sync.Mutex
-
-	defaultIP = net.ParseIP("0.0.0.0")
-	globalMap = ipMapping{}
+	defaultIP          = net.ParseIP("0.0.0.0")
 )
 
 // ErrPortAlreadyAllocated is the returned error information when a requested port is already being used
@@ -84,12 +61,59 @@ func (e ErrPortAlreadyAllocated) Error() string {
 	return fmt.Sprintf("Bind for %s:%d failed: port is already allocated", e.ip, e.port)
 }
 
+type (
+	// PortAllocator manages the transport ports database
+	PortAllocator struct {
+		mutex sync.Mutex
+		ipMap ipMapping
+		Begin int
+		End   int
+	}
+	portMap struct {
+		p          map[int]struct{}
+		begin, end int
+		last       int
+	}
+	protoMap map[string]*portMap
+)
+
+// New returns a new instance of PortAllocator
+func New() *PortAllocator {
+	start, end, err := getDynamicPortRange()
+	if err != nil {
+		logrus.Warn(err)
+		start, end = DefaultPortRangeStart, DefaultPortRangeEnd
+	}
+	return &PortAllocator{
+		ipMap: ipMapping{},
+		Begin: start,
+		End:   end,
+	}
+}
+
+func getDynamicPortRange() (start int, end int, err error) {
+	const portRangeKernelParam = "/proc/sys/net/ipv4/ip_local_port_range"
+	portRangeFallback := fmt.Sprintf("using fallback port range %d-%d", DefaultPortRangeStart, DefaultPortRangeEnd)
+	file, err := os.Open(portRangeKernelParam)
+	if err != nil {
+		return 0, 0, fmt.Errorf("port allocator - %s due to error: %v", portRangeFallback, err)
+	}
+	n, err := fmt.Fscanf(bufio.NewReader(file), "%d\t%d", &start, &end)
+	if n != 2 || err != nil {
+		if err == nil {
+			err = fmt.Errorf("unexpected count of parsed numbers (%d)", n)
+		}
+		return 0, 0, fmt.Errorf("port allocator - failed to parse system ephemeral port range from %s - %s: %v", portRangeKernelParam, portRangeFallback, err)
+	}
+	return start, end, nil
+}
+
 // RequestPort requests new port from global ports pool for specified ip and proto.
 // If port is 0 it returns first free port. Otherwise it cheks port availability
 // in pool and return that port or error if port is already busy.
-func RequestPort(ip net.IP, proto string, port int) (int, error) {
-	mutex.Lock()
-	defer mutex.Unlock()
+func (p *PortAllocator) RequestPort(ip net.IP, proto string, port int) (int, error) {
+	p.mutex.Lock()
+	defer p.mutex.Unlock()
 
 	if proto != "tcp" && proto != "udp" {
 		return 0, ErrUnknownProtocol
@@ -99,10 +123,14 @@ func RequestPort(ip net.IP, proto string, port int) (int, error) {
 		ip = defaultIP
 	}
 	ipstr := ip.String()
-	protomap, ok := globalMap[ipstr]
+	protomap, ok := p.ipMap[ipstr]
 	if !ok {
-		protomap = newProtoMap()
-		globalMap[ipstr] = protomap
+		protomap = protoMap{
+			"tcp": p.newPortMap(),
+			"udp": p.newPortMap(),
+		}
+
+		p.ipMap[ipstr] = protomap
 	}
 	mapping := protomap[proto]
 	if port > 0 {
@@ -121,14 +149,14 @@ func RequestPort(ip net.IP, proto string, port int) (int, error) {
 }
 
 // ReleasePort releases port from global ports pool for specified ip and proto.
-func ReleasePort(ip net.IP, proto string, port int) error {
-	mutex.Lock()
-	defer mutex.Unlock()
+func (p *PortAllocator) ReleasePort(ip net.IP, proto string, port int) error {
+	p.mutex.Lock()
+	defer p.mutex.Unlock()
 
 	if ip == nil {
 		ip = defaultIP
 	}
-	protomap, ok := globalMap[ip.String()]
+	protomap, ok := p.ipMap[ip.String()]
 	if !ok {
 		return nil
 	}
@@ -136,20 +164,29 @@ func ReleasePort(ip net.IP, proto string, port int) error {
 	return nil
 }
 
+func (p *PortAllocator) newPortMap() *portMap {
+	return &portMap{
+		p:     map[int]struct{}{},
+		begin: p.Begin,
+		end:   p.End,
+		last:  p.End,
+	}
+}
+
 // ReleaseAll releases all ports for all ips.
-func ReleaseAll() error {
-	mutex.Lock()
-	globalMap = ipMapping{}
-	mutex.Unlock()
+func (p *PortAllocator) ReleaseAll() error {
+	p.mutex.Lock()
+	p.ipMap = ipMapping{}
+	p.mutex.Unlock()
 	return nil
 }
 
 func (pm *portMap) findPort() (int, error) {
 	port := pm.last
-	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
+	for i := 0; i <= pm.end-pm.begin; i++ {
 		port++
-		if port > EndPortRange {
-			port = BeginPortRange
+		if port > pm.end {
+			port = pm.begin
 		}
 
 		if _, ok := pm.p[port]; !ok {

+ 51 - 57
libnetwork/portallocator/portallocator_test.go

@@ -5,27 +5,23 @@ import (
 	"testing"
 )
 
-func reset() {
-	ReleaseAll()
-}
-
 func TestRequestNewPort(t *testing.T) {
-	defer reset()
+	p := New()
 
-	port, err := RequestPort(defaultIP, "tcp", 0)
+	port, err := p.RequestPort(defaultIP, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if expected := BeginPortRange; port != expected {
+	if expected := p.Begin; port != expected {
 		t.Fatalf("Expected port %d got %d", expected, port)
 	}
 }
 
 func TestRequestSpecificPort(t *testing.T) {
-	defer reset()
+	p := New()
 
-	port, err := RequestPort(defaultIP, "tcp", 5000)
+	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -35,9 +31,9 @@ func TestRequestSpecificPort(t *testing.T) {
 }
 
 func TestReleasePort(t *testing.T) {
-	defer reset()
+	p := New()
 
-	port, err := RequestPort(defaultIP, "tcp", 5000)
+	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -45,15 +41,15 @@ func TestReleasePort(t *testing.T) {
 		t.Fatalf("Expected port 5000 got %d", port)
 	}
 
-	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
+	if err := p.ReleasePort(defaultIP, "tcp", 5000); err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestReuseReleasedPort(t *testing.T) {
-	defer reset()
+	p := New()
 
-	port, err := RequestPort(defaultIP, "tcp", 5000)
+	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -61,20 +57,20 @@ func TestReuseReleasedPort(t *testing.T) {
 		t.Fatalf("Expected port 5000 got %d", port)
 	}
 
-	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
+	if err := p.ReleasePort(defaultIP, "tcp", 5000); err != nil {
 		t.Fatal(err)
 	}
 
-	port, err = RequestPort(defaultIP, "tcp", 5000)
+	port, err = p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestReleaseUnreadledPort(t *testing.T) {
-	defer reset()
+	p := New()
 
-	port, err := RequestPort(defaultIP, "tcp", 5000)
+	port, err := p.RequestPort(defaultIP, "tcp", 5000)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -82,7 +78,7 @@ func TestReleaseUnreadledPort(t *testing.T) {
 		t.Fatalf("Expected port 5000 got %d", port)
 	}
 
-	port, err = RequestPort(defaultIP, "tcp", 5000)
+	port, err = p.RequestPort(defaultIP, "tcp", 5000)
 
 	switch err.(type) {
 	case ErrPortAlreadyAllocated:
@@ -92,42 +88,40 @@ func TestReleaseUnreadledPort(t *testing.T) {
 }
 
 func TestUnknowProtocol(t *testing.T) {
-	defer reset()
-
-	if _, err := RequestPort(defaultIP, "tcpp", 0); err != ErrUnknownProtocol {
+	if _, err := New().RequestPort(defaultIP, "tcpp", 0); err != ErrUnknownProtocol {
 		t.Fatalf("Expected error %s got %s", ErrUnknownProtocol, err)
 	}
 }
 
 func TestAllocateAllPorts(t *testing.T) {
-	defer reset()
+	p := New()
 
-	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
-		port, err := RequestPort(defaultIP, "tcp", 0)
+	for i := 0; i <= p.End-p.Begin; i++ {
+		port, err := p.RequestPort(defaultIP, "tcp", 0)
 		if err != nil {
 			t.Fatal(err)
 		}
 
-		if expected := BeginPortRange + i; port != expected {
+		if expected := p.Begin + i; port != expected {
 			t.Fatalf("Expected port %d got %d", expected, port)
 		}
 	}
 
-	if _, err := RequestPort(defaultIP, "tcp", 0); err != ErrAllPortsAllocated {
+	if _, err := p.RequestPort(defaultIP, "tcp", 0); err != ErrAllPortsAllocated {
 		t.Fatalf("Expected error %s got %s", ErrAllPortsAllocated, err)
 	}
 
-	_, err := RequestPort(defaultIP, "udp", 0)
+	_, err := p.RequestPort(defaultIP, "udp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	// release a port in the middle and ensure we get another tcp port
-	port := BeginPortRange + 5
-	if err := ReleasePort(defaultIP, "tcp", port); err != nil {
+	port := p.Begin + 5
+	if err := p.ReleasePort(defaultIP, "tcp", port); err != nil {
 		t.Fatal(err)
 	}
-	newPort, err := RequestPort(defaultIP, "tcp", 0)
+	newPort, err := p.RequestPort(defaultIP, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -137,10 +131,10 @@ func TestAllocateAllPorts(t *testing.T) {
 
 	// now pm.last == newPort, release it so that it's the only free port of
 	// the range, and ensure we get it back
-	if err := ReleasePort(defaultIP, "tcp", newPort); err != nil {
+	if err := p.ReleasePort(defaultIP, "tcp", newPort); err != nil {
 		t.Fatal(err)
 	}
-	port, err = RequestPort(defaultIP, "tcp", 0)
+	port, err = p.RequestPort(defaultIP, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -150,34 +144,34 @@ func TestAllocateAllPorts(t *testing.T) {
 }
 
 func BenchmarkAllocatePorts(b *testing.B) {
-	defer reset()
+	p := New()
 
 	for i := 0; i < b.N; i++ {
-		for i := 0; i <= EndPortRange-BeginPortRange; i++ {
-			port, err := RequestPort(defaultIP, "tcp", 0)
+		for i := 0; i <= p.End-p.Begin; i++ {
+			port, err := p.RequestPort(defaultIP, "tcp", 0)
 			if err != nil {
 				b.Fatal(err)
 			}
 
-			if expected := BeginPortRange + i; port != expected {
+			if expected := p.Begin + i; port != expected {
 				b.Fatalf("Expected port %d got %d", expected, port)
 			}
 		}
-		reset()
+		p.ReleaseAll()
 	}
 }
 
 func TestPortAllocation(t *testing.T) {
-	defer reset()
+	p := New()
 
 	ip := net.ParseIP("192.168.0.1")
 	ip2 := net.ParseIP("192.168.0.2")
-	if port, err := RequestPort(ip, "tcp", 80); err != nil {
+	if port, err := p.RequestPort(ip, "tcp", 80); err != nil {
 		t.Fatal(err)
 	} else if port != 80 {
 		t.Fatalf("Acquire(80) should return 80, not %d", port)
 	}
-	port, err := RequestPort(ip, "tcp", 0)
+	port, err := p.RequestPort(ip, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -185,41 +179,41 @@ func TestPortAllocation(t *testing.T) {
 		t.Fatalf("Acquire(0) should return a non-zero port")
 	}
 
-	if _, err := RequestPort(ip, "tcp", port); err == nil {
+	if _, err := p.RequestPort(ip, "tcp", port); err == nil {
 		t.Fatalf("Acquiring a port already in use should return an error")
 	}
 
-	if newPort, err := RequestPort(ip, "tcp", 0); err != nil {
+	if newPort, err := p.RequestPort(ip, "tcp", 0); err != nil {
 		t.Fatal(err)
 	} else if newPort == port {
 		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
 	}
 
-	if _, err := RequestPort(ip, "tcp", 80); err == nil {
+	if _, err := p.RequestPort(ip, "tcp", 80); err == nil {
 		t.Fatalf("Acquiring a port already in use should return an error")
 	}
-	if _, err := RequestPort(ip2, "tcp", 80); err != nil {
+	if _, err := p.RequestPort(ip2, "tcp", 80); err != nil {
 		t.Fatalf("It should be possible to allocate the same port on a different interface")
 	}
-	if _, err := RequestPort(ip2, "tcp", 80); err == nil {
+	if _, err := p.RequestPort(ip2, "tcp", 80); err == nil {
 		t.Fatalf("Acquiring a port already in use should return an error")
 	}
-	if err := ReleasePort(ip, "tcp", 80); err != nil {
+	if err := p.ReleasePort(ip, "tcp", 80); err != nil {
 		t.Fatal(err)
 	}
-	if _, err := RequestPort(ip, "tcp", 80); err != nil {
+	if _, err := p.RequestPort(ip, "tcp", 80); err != nil {
 		t.Fatal(err)
 	}
 
-	port, err = RequestPort(ip, "tcp", 0)
+	port, err = p.RequestPort(ip, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
-	port2, err := RequestPort(ip, "tcp", port+1)
+	port2, err := p.RequestPort(ip, "tcp", port+1)
 	if err != nil {
 		t.Fatal(err)
 	}
-	port3, err := RequestPort(ip, "tcp", 0)
+	port3, err := p.RequestPort(ip, "tcp", 0)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -229,17 +223,17 @@ func TestPortAllocation(t *testing.T) {
 }
 
 func TestNoDuplicateBPR(t *testing.T) {
-	defer reset()
+	p := New()
 
-	if port, err := RequestPort(defaultIP, "tcp", BeginPortRange); err != nil {
+	if port, err := p.RequestPort(defaultIP, "tcp", p.Begin); err != nil {
 		t.Fatal(err)
-	} else if port != BeginPortRange {
-		t.Fatalf("Expected port %d got %d", BeginPortRange, port)
+	} else if port != p.Begin {
+		t.Fatalf("Expected port %d got %d", p.Begin, port)
 	}
 
-	if port, err := RequestPort(defaultIP, "tcp", 0); err != nil {
+	if port, err := p.RequestPort(defaultIP, "tcp", 0); err != nil {
 		t.Fatal(err)
-	} else if port == BeginPortRange {
+	} else if port == p.Begin {
 		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
 	}
 }

+ 51 - 35
libnetwork/portmapper/mapper.go

@@ -6,7 +6,7 @@ import (
 	"net"
 	"sync"
 
-	log "github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/iptables"
 	"github.com/docker/libnetwork/portallocator"
 )
@@ -18,15 +18,7 @@ type mapping struct {
 	container     net.Addr
 }
 
-var (
-	chain *iptables.Chain
-	lock  sync.Mutex
-
-	// udp:ip:port
-	currentMappings = make(map[string]*mapping)
-
-	newProxy = newProxyCommand
-)
+var newProxy = newProxyCommand
 
 var (
 	// ErrUnknownBackendAddressType refers to an unknown container or unsupported address type
@@ -37,15 +29,39 @@ var (
 	ErrPortNotMapped = errors.New("port is not mapped")
 )
 
+// PortMapper manages the network address translation
+type PortMapper struct {
+	chain *iptables.Chain
+
+	// udp:ip:port
+	currentMappings map[string]*mapping
+	lock            sync.Mutex
+
+	Allocator *portallocator.PortAllocator
+}
+
+// New returns a new instance of PortMapper
+func New() *PortMapper {
+	return NewWithPortAllocator(portallocator.New())
+}
+
+// NewWithPortAllocator returns a new instance of PortMapper wich will use the specified PortAllocator
+func NewWithPortAllocator(allocator *portallocator.PortAllocator) *PortMapper {
+	return &PortMapper{
+		currentMappings: make(map[string]*mapping),
+		Allocator:       allocator,
+	}
+}
+
 // SetIptablesChain sets the specified chain into portmapper
-func SetIptablesChain(c *iptables.Chain) {
-	chain = c
+func (pm *PortMapper) SetIptablesChain(c *iptables.Chain) {
+	pm.chain = c
 }
 
 // Map maps the specified container transport address to the host's network address and transport port
-func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err error) {
-	lock.Lock()
-	defer lock.Unlock()
+func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err error) {
+	pm.lock.Lock()
+	defer pm.lock.Unlock()
 
 	var (
 		m                 *mapping
@@ -57,7 +73,7 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
 	switch container.(type) {
 	case *net.TCPAddr:
 		proto = "tcp"
-		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
+		if allocatedHostPort, err = pm.Allocator.RequestPort(hostIP, proto, hostPort); err != nil {
 			return nil, err
 		}
 
@@ -70,7 +86,7 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
 		proxy = newProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port)
 	case *net.UDPAddr:
 		proto = "udp"
-		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
+		if allocatedHostPort, err = pm.Allocator.RequestPort(hostIP, proto, hostPort); err != nil {
 			return nil, err
 		}
 
@@ -88,25 +104,25 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
 	// release the allocated port on any further error during return.
 	defer func() {
 		if err != nil {
-			portallocator.ReleasePort(hostIP, proto, allocatedHostPort)
+			pm.Allocator.ReleasePort(hostIP, proto, allocatedHostPort)
 		}
 	}()
 
 	key := getKey(m.host)
-	if _, exists := currentMappings[key]; exists {
+	if _, exists := pm.currentMappings[key]; exists {
 		return nil, ErrPortMappedForIP
 	}
 
 	containerIP, containerPort := getIPAndPort(m.container)
-	if err := forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
+	if err := pm.forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
 		return nil, err
 	}
 
 	cleanup := func() error {
 		// need to undo the iptables rules before we return
 		proxy.Stop()
-		forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
-		if err := portallocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
+		pm.forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
+		if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
 			return err
 		}
 
@@ -120,36 +136,36 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
 		return nil, err
 	}
 	m.userlandProxy = proxy
-	currentMappings[key] = m
+	pm.currentMappings[key] = m
 	return m.host, nil
 }
 
 // Unmap removes stored mapping for the specified host transport address
-func Unmap(host net.Addr) error {
-	lock.Lock()
-	defer lock.Unlock()
+func (pm *PortMapper) Unmap(host net.Addr) error {
+	pm.lock.Lock()
+	defer pm.lock.Unlock()
 
 	key := getKey(host)
-	data, exists := currentMappings[key]
+	data, exists := pm.currentMappings[key]
 	if !exists {
 		return ErrPortNotMapped
 	}
 
 	data.userlandProxy.Stop()
 
-	delete(currentMappings, key)
+	delete(pm.currentMappings, key)
 
 	containerIP, containerPort := getIPAndPort(data.container)
 	hostIP, hostPort := getIPAndPort(data.host)
-	if err := forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
-		log.Errorf("Error on iptables delete: %s", err)
+	if err := pm.forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
+		logrus.Errorf("Error on iptables delete: %s", err)
 	}
 
 	switch a := host.(type) {
 	case *net.TCPAddr:
-		return portallocator.ReleasePort(a.IP, "tcp", a.Port)
+		return pm.Allocator.ReleasePort(a.IP, "tcp", a.Port)
 	case *net.UDPAddr:
-		return portallocator.ReleasePort(a.IP, "udp", a.Port)
+		return pm.Allocator.ReleasePort(a.IP, "udp", a.Port)
 	}
 	return nil
 }
@@ -174,9 +190,9 @@ func getIPAndPort(a net.Addr) (net.IP, int) {
 	return nil, 0
 }
 
-func forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
-	if chain == nil {
+func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
+	if pm.chain == nil {
 		return nil
 	}
-	return chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
+	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
 }

+ 20 - 23
libnetwork/portmapper/mapper_test.go

@@ -5,7 +5,6 @@ import (
 	"testing"
 
 	"github.com/docker/docker/pkg/iptables"
-	"github.com/docker/libnetwork/portallocator"
 )
 
 func init() {
@@ -13,30 +12,26 @@ func init() {
 	newProxy = newMockProxyCommand
 }
 
-func reset() {
-	chain = nil
-	currentMappings = make(map[string]*mapping)
-}
-
 func TestSetIptablesChain(t *testing.T) {
-	defer reset()
+	pm := New()
 
 	c := &iptables.Chain{
 		Name:   "TEST",
 		Bridge: "192.168.1.1",
 	}
 
-	if chain != nil {
+	if pm.chain != nil {
 		t.Fatal("chain should be nil at init")
 	}
 
-	SetIptablesChain(c)
-	if chain == nil {
+	pm.SetIptablesChain(c)
+	if pm.chain == nil {
 		t.Fatal("chain should not be nil after set")
 	}
 }
 
 func TestMapPorts(t *testing.T) {
+	pm := New()
 	dstIP1 := net.ParseIP("192.168.0.1")
 	dstIP2 := net.ParseIP("192.168.0.2")
 	dstAddr1 := &net.TCPAddr{IP: dstIP1, Port: 80}
@@ -49,34 +44,34 @@ func TestMapPorts(t *testing.T) {
 		return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String())
 	}
 
-	if host, err := Map(srcAddr1, dstIP1, 80); err != nil {
+	if host, err := pm.Map(srcAddr1, dstIP1, 80); err != nil {
 		t.Fatalf("Failed to allocate port: %s", err)
 	} else if !addrEqual(dstAddr1, host) {
 		t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s",
 			dstAddr1.String(), dstAddr1.Network(), host.String(), host.Network())
 	}
 
-	if _, err := Map(srcAddr1, dstIP1, 80); err == nil {
+	if _, err := pm.Map(srcAddr1, dstIP1, 80); err == nil {
 		t.Fatalf("Port is in use - mapping should have failed")
 	}
 
-	if _, err := Map(srcAddr2, dstIP1, 80); err == nil {
+	if _, err := pm.Map(srcAddr2, dstIP1, 80); err == nil {
 		t.Fatalf("Port is in use - mapping should have failed")
 	}
 
-	if _, err := Map(srcAddr2, dstIP2, 80); err != nil {
+	if _, err := pm.Map(srcAddr2, dstIP2, 80); err != nil {
 		t.Fatalf("Failed to allocate port: %s", err)
 	}
 
-	if Unmap(dstAddr1) != nil {
+	if pm.Unmap(dstAddr1) != nil {
 		t.Fatalf("Failed to release port")
 	}
 
-	if Unmap(dstAddr2) != nil {
+	if pm.Unmap(dstAddr2) != nil {
 		t.Fatalf("Failed to release port")
 	}
 
-	if Unmap(dstAddr2) == nil {
+	if pm.Unmap(dstAddr2) == nil {
 		t.Fatalf("Port already released, but no error reported")
 	}
 }
@@ -115,6 +110,7 @@ func TestGetUDPIPAndPort(t *testing.T) {
 }
 
 func TestMapAllPortsSingleInterface(t *testing.T) {
+	pm := New()
 	dstIP1 := net.ParseIP("0.0.0.0")
 	srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
 
@@ -124,25 +120,26 @@ func TestMapAllPortsSingleInterface(t *testing.T) {
 
 	defer func() {
 		for _, val := range hosts {
-			Unmap(val)
+			pm.Unmap(val)
 		}
 	}()
 
 	for i := 0; i < 10; i++ {
-		for i := portallocator.BeginPortRange; i < portallocator.EndPortRange; i++ {
-			if host, err = Map(srcAddr1, dstIP1, 0); err != nil {
+		start, end := pm.Allocator.Begin, pm.Allocator.End
+		for i := start; i < end; i++ {
+			if host, err = pm.Map(srcAddr1, dstIP1, 0); err != nil {
 				t.Fatal(err)
 			}
 
 			hosts = append(hosts, host)
 		}
 
-		if _, err := Map(srcAddr1, dstIP1, portallocator.BeginPortRange); err == nil {
-			t.Fatalf("Port %d should be bound but is not", portallocator.BeginPortRange)
+		if _, err := pm.Map(srcAddr1, dstIP1, start); err == nil {
+			t.Fatalf("Port %d should be bound but is not", start)
 		}
 
 		for _, val := range hosts {
-			if err := Unmap(val); err != nil {
+			if err := pm.Unmap(val); err != nil {
 				t.Fatal(err)
 			}
 		}