Pārlūkot izejas kodu

Merge pull request #1095 from mrjana/ipam

Remove all netlink/osl deps from ipam/ipamutils
Alessandro Boch 9 gadi atpakaļ
vecāks
revīzija
c891a47cb3

+ 2 - 2
libnetwork/cmd/dnet/dnet.go

@@ -29,8 +29,8 @@ import (
 	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/driverapi"
-	"github.com/docker/libnetwork/ipamutils"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
 	"github.com/gorilla/mux"
@@ -429,7 +429,7 @@ func encodeData(data interface{}) (*bytes.Buffer, error) {
 }
 
 func ipamOption(bridgeName string) libnetwork.NetworkOption {
-	if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil {
+	if nw, _, err := netutils.ElectInterfaceAddresses(bridgeName); err == nil {
 		ipamV4Conf := &libnetwork.IpamConf{PreferredPool: nw.String()}
 		hip, _ := types.GetHostPartIP(nw.IP, nw.Mask)
 		if hip.IsGlobalUnicast() {

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

@@ -10,6 +10,7 @@ import (
 	"github.com/docker/libnetwork/ipamutils"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/testutils"
 	"github.com/docker/libnetwork/types"
@@ -21,7 +22,7 @@ func init() {
 
 func getIPv4Data(t *testing.T) []driverapi.IPAMData {
 	ipd := driverapi.IPAMData{AddressSpace: "full"}
-	nw, _, err := ipamutils.ElectInterfaceAddresses("")
+	nw, _, err := netutils.ElectInterfaceAddresses("")
 	if err != nil {
 		t.Fatal(err)
 	}

+ 0 - 7
libnetwork/ipam/allocator.go

@@ -401,13 +401,6 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
 		}
 
 		if !aSpace.contains(as, nw) {
-			if as == localAddressSpace {
-				// Check if nw overlap with system routes, name servers
-				if _, err := ipamutils.FindAvailableNetwork([]*net.IPNet{nw}); err == nil {
-					return nw, nil
-				}
-				continue
-			}
 			return nw, nil
 		}
 	}

+ 1 - 25
libnetwork/ipam/allocator_test.go

@@ -453,27 +453,11 @@ func TestPredefinedPool(t *testing.T) {
 		t.Fatalf("Expected failure for non default addr space")
 	}
 
-	exp, err := ipamutils.FindAvailableNetwork(a.predefined[localAddressSpace])
+	pid, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	nw, err := a.getPredefinedPool(localAddressSpace, false)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(nw, exp) {
-		t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp)
-	}
-
-	pid, nw, _, err := a.RequestPool(localAddressSpace, exp.String(), "", nil, false)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(nw, exp) {
-		t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp)
-	}
-
 	nw2, err := a.getPredefinedPool(localAddressSpace, false)
 	if err != nil {
 		t.Fatal(err)
@@ -485,14 +469,6 @@ func TestPredefinedPool(t *testing.T) {
 	if err := a.ReleasePool(pid); err != nil {
 		t.Fatal(err)
 	}
-
-	nw, err = a.getPredefinedPool(localAddressSpace, false)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(nw, exp) {
-		t.Fatalf("Unexpected default network returned: %s. Expected %s", nw, exp)
-	}
 }
 
 func TestRemoveSubnet(t *testing.T) {

+ 0 - 76
libnetwork/ipamutils/utils_linux.go

@@ -1,76 +0,0 @@
-// Package ipamutils provides utililty functions for ipam management
-package ipamutils
-
-import (
-	"fmt"
-	"net"
-
-	"github.com/docker/libnetwork/netutils"
-	"github.com/docker/libnetwork/osl"
-	"github.com/docker/libnetwork/resolvconf"
-	"github.com/vishvananda/netlink"
-)
-
-// ElectInterfaceAddresses looks for an interface on the OS with the specified name
-// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
-// it chooses from a predifined list the first IPv4 address which does not conflict
-// with other interfaces on the system.
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
-	var (
-		v4Net  *net.IPNet
-		v6Nets []*net.IPNet
-		err    error
-	)
-
-	InitNetworks()
-
-	defer osl.InitOSContext()()
-
-	link, _ := netlink.LinkByName(name)
-	if link != nil {
-		v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
-		if err != nil {
-			return nil, nil, err
-		}
-		v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
-		if err != nil {
-			return nil, nil, err
-		}
-		if len(v4addr) > 0 {
-			v4Net = v4addr[0].IPNet
-		}
-		for _, nlAddr := range v6addr {
-			v6Nets = append(v6Nets, nlAddr.IPNet)
-		}
-	}
-
-	if link == nil || v4Net == nil {
-		// Choose from predifined broad networks
-		v4Net, err = FindAvailableNetwork(PredefinedBroadNetworks)
-		if err != nil {
-			return nil, nil, err
-		}
-	}
-
-	return v4Net, v6Nets, nil
-}
-
-// FindAvailableNetwork returns a network from the passed list which does not
-// overlap with existing interfaces in the system
-func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
-	// 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.
-	var nameservers []string
-	if rc, err := resolvconf.Get(); err == nil {
-		nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
-	}
-	for _, nw := range list {
-		if err := netutils.CheckNameserverOverlaps(nameservers, nw); err == nil {
-			if err := netutils.CheckRouteOverlaps(nw); err == nil {
-				return nw, nil
-			}
-		}
-	}
-	return nil, fmt.Errorf("no available network")
-}

+ 1 - 92
libnetwork/ipamutils/utils_test.go

@@ -1,12 +1,9 @@
 package ipamutils
 
 import (
-	"net"
 	"testing"
 
-	"github.com/docker/libnetwork/testutils"
-	"github.com/docker/libnetwork/types"
-	"github.com/vishvananda/netlink"
+	_ "github.com/docker/libnetwork/testutils"
 )
 
 func init() {
@@ -27,91 +24,3 @@ func TestGranularPredefined(t *testing.T) {
 	}
 
 }
-
-func TestNetworkRequest(t *testing.T) {
-	defer testutils.SetupTestOSContext(t)()
-	_, exp, err := net.ParseCIDR("172.17.0.0/16")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	nw, err := FindAvailableNetwork(PredefinedBroadNetworks)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(exp, nw) {
-		t.Fatalf("exected %s. got %s", exp, nw)
-	}
-
-	_, exp, err = net.ParseCIDR("10.0.0.0/24")
-	if err != nil {
-		t.Fatal(err)
-	}
-	nw, err = FindAvailableNetwork(PredefinedGranularNetworks)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(exp, nw) {
-		t.Fatalf("exected %s. got %s", exp, nw)
-	}
-
-	// Add iface and ssert returned address on request
-	createInterface(t, "test", "172.17.42.1/16")
-
-	_, exp, err = net.ParseCIDR("172.18.0.0/16")
-	if err != nil {
-		t.Fatal(err)
-	}
-	nw, err = FindAvailableNetwork(PredefinedBroadNetworks)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !types.CompareIPNet(exp, nw) {
-		t.Fatalf("exected %s. got %s", exp, nw)
-	}
-}
-
-func TestElectInterfaceAddress(t *testing.T) {
-	defer testutils.SetupTestOSContext(t)()
-	nws := "172.101.202.254/16"
-	createInterface(t, "test", nws)
-
-	ipv4Nw, ipv6Nw, err := ElectInterfaceAddresses("test")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if ipv4Nw == nil {
-		t.Fatalf("unexpected empty ipv4 network addresses")
-	}
-
-	if len(ipv6Nw) == 0 {
-		t.Fatalf("unexpected empty ipv4 network addresses")
-	}
-
-	if nws != ipv4Nw.String() {
-		t.Fatalf("expected %s. got %s", nws, ipv4Nw)
-	}
-}
-
-func createInterface(t *testing.T, name, nw string) {
-	// Add interface
-	link := &netlink.Bridge{
-		LinkAttrs: netlink.LinkAttrs{
-			Name: "test",
-		},
-	}
-	bip, err := types.ParseCIDR(nw)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err = netlink.LinkAdd(link); err != nil {
-		t.Fatalf("Failed to create interface via netlink: %v", err)
-	}
-	if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: bip}); err != nil {
-		t.Fatal(err)
-	}
-	if err = netlink.LinkSetUp(link); err != nil {
-		t.Fatal(err)
-	}
-}

+ 0 - 7
libnetwork/netutils/utils.go

@@ -14,13 +14,6 @@ import (
 	"github.com/docker/libnetwork/types"
 )
 
-// constants for the IP address type
-const (
-	IP = iota // IPv4 and IPv6
-	IPv4
-	IPv6
-)
-
 var (
 	// ErrNetworkOverlapsWithNameservers preformatted error
 	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")

+ 1 - 2
libnetwork/ipamutils/utils_freebsd.go → libnetwork/netutils/utils_freebsd.go

@@ -1,5 +1,4 @@
-// Package ipamutils provides utililty functions for ipam management
-package ipamutils
+package netutils
 
 import (
 	"net"

+ 67 - 0
libnetwork/netutils/utils_linux.go

@@ -4,9 +4,13 @@
 package netutils
 
 import (
+	"fmt"
 	"net"
 	"strings"
 
+	"github.com/docker/libnetwork/ipamutils"
+	"github.com/docker/libnetwork/osl"
+	"github.com/docker/libnetwork/resolvconf"
 	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
 )
@@ -48,3 +52,66 @@ func GenerateIfaceName(prefix string, len int) (string, error) {
 	}
 	return "", types.InternalErrorf("could not generate interface name")
 }
+
+// ElectInterfaceAddresses looks for an interface on the OS with the
+// specified name and returns its IPv4 and IPv6 addresses in CIDR
+// form. If the interface does not exist, it chooses from a predifined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
+	var (
+		v4Net  *net.IPNet
+		v6Nets []*net.IPNet
+		err    error
+	)
+
+	defer osl.InitOSContext()()
+
+	link, _ := netlink.LinkByName(name)
+	if link != nil {
+		v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
+		if err != nil {
+			return nil, nil, err
+		}
+		v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
+		if err != nil {
+			return nil, nil, err
+		}
+		if len(v4addr) > 0 {
+			v4Net = v4addr[0].IPNet
+		}
+		for _, nlAddr := range v6addr {
+			v6Nets = append(v6Nets, nlAddr.IPNet)
+		}
+	}
+
+	if link == nil || v4Net == nil {
+		// Choose from predifined broad networks
+		v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+
+	return v4Net, v6Nets, nil
+}
+
+// FindAvailableNetwork returns a network from the passed list which does not
+// overlap with existing interfaces in the system
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
+	// 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.
+	var nameservers []string
+	if rc, err := resolvconf.Get(); err == nil {
+		nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
+	}
+	for _, nw := range list {
+		if err := CheckNameserverOverlaps(nameservers, nw); err == nil {
+			if err := CheckRouteOverlaps(nw); err == nil {
+				return nw, nil
+			}
+		}
+	}
+	return nil, fmt.Errorf("no available network")
+}

+ 95 - 1
libnetwork/netutils/utils_test.go

@@ -5,7 +5,9 @@ import (
 	"net"
 	"testing"
 
-	_ "github.com/docker/libnetwork/testutils"
+	"github.com/docker/libnetwork/ipamutils"
+	"github.com/docker/libnetwork/testutils"
+	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
 )
 
@@ -210,3 +212,95 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
 		t.Fatalf("mac1 %s should not equal mac2 %s", mac1, mac2)
 	}
 }
+
+func TestNetworkRequest(t *testing.T) {
+	defer testutils.SetupTestOSContext(t)()
+	ipamutils.InitNetworks()
+
+	_, exp, err := net.ParseCIDR("172.17.0.0/16")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !types.CompareIPNet(exp, nw) {
+		t.Fatalf("exected %s. got %s", exp, nw)
+	}
+
+	_, exp, err = net.ParseCIDR("10.0.0.0/24")
+	if err != nil {
+		t.Fatal(err)
+	}
+	nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !types.CompareIPNet(exp, nw) {
+		t.Fatalf("exected %s. got %s", exp, nw)
+	}
+
+	// Add iface and ssert returned address on request
+	createInterface(t, "test", "172.17.42.1/16")
+
+	_, exp, err = net.ParseCIDR("172.18.0.0/16")
+	if err != nil {
+		t.Fatal(err)
+	}
+	nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !types.CompareIPNet(exp, nw) {
+		t.Fatalf("exected %s. got %s", exp, nw)
+	}
+}
+
+func TestElectInterfaceAddress(t *testing.T) {
+	defer testutils.SetupTestOSContext(t)()
+	ipamutils.InitNetworks()
+
+	nws := "172.101.202.254/16"
+	createInterface(t, "test", nws)
+
+	ipv4Nw, ipv6Nw, err := ElectInterfaceAddresses("test")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if ipv4Nw == nil {
+		t.Fatalf("unexpected empty ipv4 network addresses")
+	}
+
+	if len(ipv6Nw) == 0 {
+		t.Fatalf("unexpected empty ipv4 network addresses")
+	}
+
+	if nws != ipv4Nw.String() {
+		t.Fatalf("expected %s. got %s", nws, ipv4Nw)
+	}
+}
+
+func createInterface(t *testing.T, name, nw string) {
+	// Add interface
+	link := &netlink.Bridge{
+		LinkAttrs: netlink.LinkAttrs{
+			Name: "test",
+		},
+	}
+	bip, err := types.ParseCIDR(nw)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = netlink.LinkAdd(link); err != nil {
+		t.Fatalf("Failed to create interface via netlink: %v", err)
+	}
+	if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: bip}); err != nil {
+		t.Fatal(err)
+	}
+	if err = netlink.LinkSetUp(link); err != nil {
+		t.Fatal(err)
+	}
+}

+ 1 - 2
libnetwork/ipamutils/utils_windows.go → libnetwork/netutils/utils_windows.go

@@ -1,5 +1,4 @@
-// Package ipamutils provides utililty functions for ipam management
-package ipamutils
+package netutils
 
 import (
 	"net"

+ 43 - 1
libnetwork/network.go

@@ -1097,6 +1097,48 @@ func (n *network) ipamAllocate() error {
 	return n.ipamAllocateVersion(6, ipam)
 }
 
+func (n *network) requestPoolHelper(ipam ipamapi.Ipam, addressSpace, preferredPool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
+	for {
+		poolID, pool, meta, err := ipam.RequestPool(addressSpace, preferredPool, subPool, options, v6)
+		if err != nil {
+			return "", nil, nil, err
+		}
+
+		// If the network belongs to global scope or the pool
+		// returned is invalid, no need to perform overlap
+		// check.
+		if n.Scope() == datastore.GlobalScope || !types.IsIPNetValid(pool) {
+			return poolID, pool, meta, nil
+		}
+
+		// Check for overlap and if none found, we have found the right pool.
+		if _, err := netutils.FindAvailableNetwork([]*net.IPNet{pool}); err == nil {
+			return poolID, pool, meta, nil
+		}
+
+		// Pool obtained in this iteration is
+		// overlapping. Hold onto the pool and don't release
+		// it yet, because we don't want ipam to give us back
+		// the same pool over again. But make sure we still do
+		// a deferred release when we have either obtained a
+		// non-overlapping pool or ran out of pre-defined
+		// pools.
+		defer func() {
+			if err := ipam.ReleasePool(poolID); err != nil {
+				log.Warnf("Failed to release overlapping pool %s while returning from pool request helper for network %s", pool, n.Name())
+			}
+		}()
+
+		// If this is a preferred pool request and the network
+		// is local scope and there is a overlap, we fail the
+		// network creation right here. The pool will be
+		// released in the defer.
+		if preferredPool != "" {
+			return "", nil, nil, fmt.Errorf("requested subnet %s overlaps in the host", preferredPool)
+		}
+	}
+}
+
 func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
 	var (
 		cfgList  *[]*IpamConf
@@ -1133,7 +1175,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
 		d := &IpamInfo{}
 		(*infoList)[i] = d
 
-		d.PoolID, d.Pool, d.Meta, err = ipam.RequestPool(n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6)
+		d.PoolID, d.Pool, d.Meta, err = n.requestPoolHelper(ipam, n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6)
 		if err != nil {
 			return err
 		}

+ 12 - 2
libnetwork/osl/sandbox_linux_test.go

@@ -1,6 +1,9 @@
 package osl
 
 import (
+	"crypto/rand"
+	"encoding/hex"
+	"io"
 	"net"
 	"os"
 	"path/filepath"
@@ -9,7 +12,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/testutils"
 	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
@@ -25,8 +27,16 @@ const (
 	sboxIfaceName = "containername"
 )
 
+func generateRandomName(prefix string, size int) (string, error) {
+	id := make([]byte, 32)
+	if _, err := io.ReadFull(rand.Reader, id); err != nil {
+		return "", err
+	}
+	return prefix + hex.EncodeToString(id)[:size], nil
+}
+
 func newKey(t *testing.T) (string, error) {
-	name, err := netutils.GenerateRandomName("netns", 12)
+	name, err := generateRandomName("netns", 12)
 	if err != nil {
 		return "", err
 	}

+ 6 - 6
libnetwork/resolvconf/resolvconf.go

@@ -10,8 +10,8 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/ioutils"
-	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/resolvconf/dns"
+	"github.com/docker/libnetwork/types"
 )
 
 var (
@@ -122,7 +122,7 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
 	}
 	// if the resulting resolvConf has no more nameservers defined, add appropriate
 	// default DNS servers for IPv4 and (optionally) IPv6
-	if len(GetNameservers(cleanedResolvConf, netutils.IP)) == 0 {
+	if len(GetNameservers(cleanedResolvConf, types.IP)) == 0 {
 		logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
 		dns := defaultIPv4Dns
 		if ipv6Enabled {
@@ -158,11 +158,11 @@ func GetNameservers(resolvConf []byte, kind int) []string {
 	nameservers := []string{}
 	for _, line := range getLines(resolvConf, []byte("#")) {
 		var ns [][]byte
-		if kind == netutils.IP {
+		if kind == types.IP {
 			ns = nsRegexp.FindSubmatch(line)
-		} else if kind == netutils.IPv4 {
+		} else if kind == types.IPv4 {
 			ns = nsIPv4Regexpmatch.FindSubmatch(line)
-		} else if kind == netutils.IPv6 {
+		} else if kind == types.IPv6 {
 			ns = nsIPv6Regexpmatch.FindSubmatch(line)
 		}
 		if len(ns) > 0 {
@@ -177,7 +177,7 @@ func GetNameservers(resolvConf []byte, kind int) []string {
 // This function's output is intended for net.ParseCIDR
 func GetNameserversAsCIDR(resolvConf []byte) []string {
 	nameservers := []string{}
-	for _, nameserver := range GetNameservers(resolvConf, netutils.IP) {
+	for _, nameserver := range GetNameservers(resolvConf, types.IP) {
 		nameservers = append(nameservers, nameserver+"/32")
 	}
 	return nameservers

+ 10 - 10
libnetwork/resolvconf/resolvconf_test.go

@@ -7,8 +7,8 @@ import (
 	"testing"
 
 	"github.com/docker/docker/pkg/ioutils"
-	"github.com/docker/libnetwork/netutils"
 	_ "github.com/docker/libnetwork/testutils"
+	"github.com/docker/libnetwork/types"
 )
 
 func TestGet(t *testing.T) {
@@ -49,7 +49,7 @@ nameserver 1.2.3.4
 		`search example.com
 nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4"},
 	} {
-		test := GetNameservers([]byte(resolv), netutils.IP)
+		test := GetNameservers([]byte(resolv), types.IP)
 		if !strSlicesEqual(test, result) {
 			t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv)
 		}
@@ -84,11 +84,11 @@ func TestGetSearchDomains(t *testing.T) {
 	for resolv, result := range map[string][]string{
 		`search example.com`:           {"example.com"},
 		`search example.com # ignored`: {"example.com"},
-		` 	  search 	 example.com 	  `: {"example.com"},
-		` 	  search 	 example.com 	  # ignored`: {"example.com"},
+		`	  search	 example.com	  `: {"example.com"},
+		`	  search	 example.com	  # ignored`: {"example.com"},
 		`search foo.example.com example.com`: {"foo.example.com", "example.com"},
-		`	   search   	   foo.example.com 	 example.com 	`: {"foo.example.com", "example.com"},
-		`	   search   	   foo.example.com 	 example.com 	# ignored`: {"foo.example.com", "example.com"},
+		`	   search	   foo.example.com	 example.com	`: {"foo.example.com", "example.com"},
+		`	   search	   foo.example.com	 example.com	# ignored`: {"foo.example.com", "example.com"},
 		``:          {},
 		`# ignored`: {},
 		`nameserver 1.2.3.4
@@ -111,12 +111,12 @@ func TestGetOptions(t *testing.T) {
 	for resolv, result := range map[string][]string{
 		`options opt1`:           {"opt1"},
 		`options opt1 # ignored`: {"opt1"},
-		` 	  options 	 opt1 	  `: {"opt1"},
-		` 	  options 	 opt1 	  # ignored`: {"opt1"},
+		`	  options	 opt1	  `: {"opt1"},
+		`	  options	 opt1	  # ignored`: {"opt1"},
 		`options opt1 opt2 opt3`:           {"opt1", "opt2", "opt3"},
 		`options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
-		`	   options 	 opt1 	 opt2 	 opt3 	`: {"opt1", "opt2", "opt3"},
-		`	   options 	 opt1 	 opt2 	 opt3 	# ignored`: {"opt1", "opt2", "opt3"},
+		`	   options	 opt1	 opt2	 opt3	`: {"opt1", "opt2", "opt3"},
+		`	   options	 opt1	 opt2	 opt3	# ignored`: {"opt1", "opt2", "opt3"},
 		``:                   {},
 		`# ignored`:          {},
 		`nameserver 1.2.3.4`: {},

+ 4 - 4
libnetwork/resolver.go

@@ -10,7 +10,7 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/iptables"
-	"github.com/docker/libnetwork/netutils"
+	"github.com/docker/libnetwork/types"
 	"github.com/miekg/dns"
 )
 
@@ -240,7 +240,7 @@ func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.
 	if len(addr) > 1 {
 		addr = shuffleAddr(addr)
 	}
-	if ipType == netutils.IPv4 {
+	if ipType == types.IPv4 {
 		for _, ip := range addr {
 			rr := new(dns.A)
 			rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
@@ -312,9 +312,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
 	}
 	name := query.Question[0].Name
 	if query.Question[0].Qtype == dns.TypeA {
-		resp, err = r.handleIPQuery(name, query, netutils.IPv4)
+		resp, err = r.handleIPQuery(name, query, types.IPv4)
 	} else if query.Question[0].Qtype == dns.TypeAAAA {
-		resp, err = r.handleIPQuery(name, query, netutils.IPv6)
+		resp, err = r.handleIPQuery(name, query, types.IPv6)
 	} else if query.Question[0].Qtype == dns.TypePTR {
 		resp, err = r.handlePTRQuery(name, query)
 	}

+ 1 - 2
libnetwork/sandbox.go

@@ -12,7 +12,6 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/etchosts"
 	"github.com/docker/libnetwork/netlabel"
-	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/types"
 )
@@ -522,7 +521,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
 		n.Lock()
 		ip, ok = sr.svcMap[name]
 
-		if ipType == netutils.IPv6 {
+		if ipType == types.IPv6 {
 			// If the name resolved to v4 address then its a valid name in
 			// the docker network domain. If the network is not v6 enabled
 			// set ipv6Miss to filter the DNS query from going to external

+ 3 - 4
libnetwork/sandbox_dns_unix.go

@@ -11,7 +11,6 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/etchosts"
-	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/resolvconf"
 	"github.com/docker/libnetwork/types"
 )
@@ -166,7 +165,7 @@ func (sb *sandbox) setupDNS() error {
 	if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
 		var (
 			err            error
-			dnsList        = resolvconf.GetNameservers(currRC.Content, netutils.IP)
+			dnsList        = resolvconf.GetNameservers(currRC.Content, types.IP)
 			dnsSearchList  = resolvconf.GetSearchDomains(currRC.Content)
 			dnsOptionsList = resolvconf.GetOptions(currRC.Content)
 		)
@@ -275,7 +274,7 @@ func (sb *sandbox) rebuildDNS() error {
 
 	// localhost entries have already been filtered out from the list
 	// retain only the v4 servers in sb for forwarding the DNS queries
-	sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
+	sb.extDNS = resolvconf.GetNameservers(currRC.Content, types.IPv4)
 
 	var (
 		dnsList        = []string{sb.resolver.NameServer()}
@@ -284,7 +283,7 @@ func (sb *sandbox) rebuildDNS() error {
 	)
 
 	// external v6 DNS servers has to be listed in resolv.conf
-	dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
+	dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, types.IPv6)...)
 
 	// Resolver returns the options in the format resolv.conf expects
 	dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)

+ 2 - 2
libnetwork/test/integration/dnet/bridge.bats

@@ -291,12 +291,12 @@ function test_single_network_connectivity() {
     dnet_cmd $(inst_id2port 1) container create container_1
     # connects to internal network, confirm it can't conmunicate with outside world
     net_connect 1 container_1 internal
-    run runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 www.google.com"
+    run runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 8.8.8.8"
     [[ "$output" == *"1 packets transmitted, 0 packets received, 100% packet loss"* ]]
     net_disconnect 1 container_1 internal
     # connects to bridge network, confirm it can conmunicate with outside world
     net_connect 1 container_1 bridge
-    runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 www.google.com"
+    runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 8.8.8.8"
     net_disconnect 1 container_1 bridge
     dnet_cmd $(inst_id2port 1) container rm container_1
     # test conmunications within internal network

+ 8 - 8
libnetwork/test/integration/dnet/overlay-consul.bats

@@ -25,6 +25,11 @@ load helpers
     test_overlay consul skip_add
 }
 
+@test "Test overlay network internal network with consul" {
+    skip_for_circleci
+    test_overlay consul internal
+}
+
 @test "Test overlay network with dnet ungraceful shutdown" {
     skip_for_circleci
     dnet_cmd $(inst_id2port 1) network create -d overlay multihost
@@ -32,8 +37,8 @@ load helpers
     end=3
     for i in `seq ${start} ${end}`;
     do
-        dnet_cmd $(inst_id2port $i) container create container_${i}
-        net_connect ${i} container_${i} multihost
+	dnet_cmd $(inst_id2port $i) container create container_${i}
+	net_connect ${i} container_${i} multihost
     done
 
     hrun runc $(dnet_container_name 1 consul) $(get_sbox_id 1 container_1) "ifconfig eth0"
@@ -51,11 +56,6 @@ load helpers
     container_1_new_ip=$(echo ${output} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')
 
     if [ "$container_1_ip" != "$container_1_new_ip" ]; then
-        exit 1
+	exit 1
     fi
 }
-
-@test "Test overlay network internal network with consul" {
-    skip_for_circleci
-    test_overlay consul internal
-}

+ 13 - 0
libnetwork/types/types.go

@@ -9,6 +9,13 @@ import (
 	"strings"
 )
 
+// constants for the IP address type
+const (
+	IP = iota // IPv4 and IPv6
+	IPv4
+	IPv6
+)
+
 // UUID represents a globally unique ID of various resources like network and endpoint
 type UUID string
 
@@ -323,6 +330,12 @@ func GetMinimalIPNet(nw *net.IPNet) *net.IPNet {
 	return nw
 }
 
+// IsIPNetValid returns true if the ipnet is a valid network/mask
+// combination. Otherwise returns false.
+func IsIPNetValid(nw *net.IPNet) bool {
+	return nw.String() != "0.0.0.0/0"
+}
+
 var v4inV6MaskPrefix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
 
 // compareIPMask checks if the passed ip and mask are semantically compatible.