فهرست منبع

Vendor libnetwork to f4338b6f1085ccfe5972e655cca8a1d15d73439d

This fix updates libnetwork to f4338b6f1085ccfe5972e655cca8a1d15d73439d.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Yong Tang 8 سال پیش
والد
کامیت
fc62ad6b95

+ 1 - 1
hack/vendor.sh

@@ -70,7 +70,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
 clone git github.com/imdario/mergo 0.2.1
 clone git github.com/imdario/mergo 0.2.1
 
 
 #get libnetwork packages
 #get libnetwork packages
-clone git github.com/docker/libnetwork 9fbb4ecbb45af655c4ac3c2f3a849b2294cb447a
+clone git github.com/docker/libnetwork f4338b6f1085ccfe5972e655cca8a1d15d73439d
 clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
 clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec

+ 17 - 4
vendor/src/github.com/docker/libnetwork/controller.go

@@ -1062,9 +1062,14 @@ func SandboxKeyWalker(out *Sandbox, key string) SandboxWalker {
 }
 }
 
 
 func (c *controller) loadDriver(networkType string) error {
 func (c *controller) loadDriver(networkType string) error {
-	// Plugins pkg performs lazy loading of plugins that acts as remote drivers.
-	// As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available.
-	_, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType)
+	var err error
+
+	if pg := c.GetPluginGetter(); pg != nil {
+		_, err = pg.Get(networkType, driverapi.NetworkPluginEndpointType, plugingetter.LOOKUP)
+	} else {
+		_, err = plugins.Get(networkType, driverapi.NetworkPluginEndpointType)
+	}
+
 	if err != nil {
 	if err != nil {
 		if err == plugins.ErrNotFound {
 		if err == plugins.ErrNotFound {
 			return types.NotFoundErrorf(err.Error())
 			return types.NotFoundErrorf(err.Error())
@@ -1076,7 +1081,15 @@ func (c *controller) loadDriver(networkType string) error {
 }
 }
 
 
 func (c *controller) loadIPAMDriver(name string) error {
 func (c *controller) loadIPAMDriver(name string) error {
-	if _, err := c.GetPluginGetter().Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP); err != nil {
+	var err error
+
+	if pg := c.GetPluginGetter(); pg != nil {
+		_, err = pg.Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP)
+	} else {
+		_, err = plugins.Get(name, ipamapi.PluginEndpointType)
+	}
+
+	if err != nil {
 		if err == plugins.ErrNotFound {
 		if err == plugins.ErrNotFound {
 			return types.NotFoundErrorf(err.Error())
 			return types.NotFoundErrorf(err.Error())
 		}
 		}

+ 14 - 0
vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go

@@ -779,6 +779,20 @@ func (d *driver) DeleteNetwork(nid string) error {
 	config := n.config
 	config := n.config
 	n.Unlock()
 	n.Unlock()
 
 
+	// delele endpoints belong to this network
+	for _, ep := range n.endpoints {
+		if err := n.releasePorts(ep); err != nil {
+			logrus.Warn(err)
+		}
+		if link, err := d.nlh.LinkByName(ep.srcName); err == nil {
+			d.nlh.LinkDel(link)
+		}
+
+		if err := d.storeDelete(ep); err != nil {
+			logrus.Warnf("Failed to remove bridge endpoint %s from store: %v", ep.id[0:7], err)
+		}
+	}
+
 	d.Lock()
 	d.Lock()
 	delete(d.networks, nid)
 	delete(d.networks, nid)
 	d.Unlock()
 	d.Unlock()

+ 6 - 7
vendor/src/github.com/docker/libnetwork/drivers/bridge/interface.go

@@ -52,23 +52,22 @@ func (i *bridgeInterface) exists() bool {
 	return i.Link != nil
 	return i.Link != nil
 }
 }
 
 
-// addresses returns a single IPv4 address and all IPv6 addresses for the
-// bridge interface.
-func (i *bridgeInterface) addresses() (netlink.Addr, []netlink.Addr, error) {
+// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface.
+func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
 	v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
 	v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
 	if err != nil {
 	if err != nil {
-		return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
+		return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
 	}
 	}
 
 
 	v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
 	v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
 	if err != nil {
 	if err != nil {
-		return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
+		return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
 	}
 	}
 
 
 	if len(v4addr) == 0 {
 	if len(v4addr) == 0 {
-		return netlink.Addr{}, v6addr, nil
+		return nil, v6addr, nil
 	}
 	}
-	return v4addr[0], v6addr, nil
+	return v4addr, v6addr, nil
 }
 }
 
 
 func (i *bridgeInterface) programIPv6Address() error {
 func (i *bridgeInterface) programIPv6Address() error {

+ 18 - 1
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go

@@ -3,6 +3,7 @@ package bridge
 import (
 import (
 	"fmt"
 	"fmt"
 	"io/ioutil"
 	"io/ioutil"
+	"net"
 	"path/filepath"
 	"path/filepath"
 
 
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
@@ -10,12 +11,28 @@ import (
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
 
 
+func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) {
+	if len(addresses) == 0 {
+		return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty")
+	}
+	if selector != nil {
+		for _, addr := range addresses {
+			if selector.Contains(addr.IP) {
+				return addr, nil
+			}
+		}
+	}
+	return addresses[0], nil
+}
+
 func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
 func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
-	addrv4, _, err := i.addresses()
+	addrv4List, _, err := i.addresses()
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
 		return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
 	}
 	}
 
 
+	addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4)
+
 	if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
 	if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
 		if addrv4.IPNet != nil {
 		if addrv4.IPNet != nil {
 			if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {
 			if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {

+ 4 - 2
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_verify.go

@@ -11,12 +11,14 @@ import (
 )
 )
 
 
 func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
 func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
-	// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
-	addrv4, addrsv6, err := i.addresses()
+	// Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge.
+	addrsv4, addrsv6, err := i.addresses()
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Failed to verify ip addresses: %v", err)
 		return fmt.Errorf("Failed to verify ip addresses: %v", err)
 	}
 	}
 
 
+	addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4)
+
 	// Verify that the bridge does have an IPv4 address.
 	// Verify that the bridge does have an IPv4 address.
 	if addrv4.IPNet == nil {
 	if addrv4.IPNet == nil {
 		return &ErrNoIPAddr{}
 		return &ErrNoIPAddr{}

+ 10 - 0
vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go

@@ -8,6 +8,7 @@ import (
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/ns"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
@@ -147,6 +148,15 @@ func (d *driver) DeleteNetwork(nid string) error {
 			}
 			}
 		}
 		}
 	}
 	}
+	for _, ep := range n.endpoints {
+		if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
+			ns.NlHandle().LinkDel(link)
+		}
+
+		if err := d.storeDelete(ep); err != nil {
+			logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err)
+		}
+	}
 	// delete the *network
 	// delete the *network
 	d.deleteNetwork(nid)
 	d.deleteNetwork(nid)
 	// delete the network record from persistent cache
 	// delete the network record from persistent cache

+ 10 - 0
vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go

@@ -8,6 +8,7 @@ import (
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/ns"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
@@ -151,6 +152,15 @@ func (d *driver) DeleteNetwork(nid string) error {
 			}
 			}
 		}
 		}
 	}
 	}
+	for _, ep := range n.endpoints {
+		if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
+			ns.NlHandle().LinkDel(link)
+		}
+
+		if err := d.storeDelete(ep); err != nil {
+			logrus.Warnf("Failed to remove macvlan endpoint %s from store: %v", ep.id[0:7], err)
+		}
+	}
 	// delete the *network
 	// delete the *network
 	d.deleteNetwork(nid)
 	d.deleteNetwork(nid)
 	// delete the network record from persistent cache
 	// delete the network record from persistent cache

+ 12 - 0
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go

@@ -182,6 +182,18 @@ func (d *driver) DeleteNetwork(nid string) error {
 		return fmt.Errorf("could not find network with id %s", nid)
 		return fmt.Errorf("could not find network with id %s", nid)
 	}
 	}
 
 
+	for _, ep := range n.endpoints {
+		if ep.ifName != "" {
+			if link, err := ns.NlHandle().LinkByName(ep.ifName); err != nil {
+				ns.NlHandle().LinkDel(link)
+			}
+		}
+
+		if err := d.deleteEndpointFromStore(ep); err != nil {
+			logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
+		}
+
+	}
 	d.deleteNetwork(nid)
 	d.deleteNetwork(nid)
 
 
 	vnis, err := n.releaseVxlanID()
 	vnis, err := n.releaseVxlanID()

+ 19 - 3
vendor/src/github.com/docker/libnetwork/endpoint.go

@@ -513,14 +513,22 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
 	if moveExtConn {
 	if moveExtConn {
 		if extEp != nil {
 		if extEp != nil {
 			log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
 			log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
-			if err = d.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
+			extN, err := extEp.getNetworkFromStore()
+			if err != nil {
+				return fmt.Errorf("failed to get network from store during join: %v", err)
+			}
+			extD, err := extN.driver(true)
+			if err != nil {
+				return fmt.Errorf("failed to join endpoint: %v", err)
+			}
+			if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
 				return types.InternalErrorf(
 				return types.InternalErrorf(
 					"driver failed revoking external connectivity on endpoint %s (%s): %v",
 					"driver failed revoking external connectivity on endpoint %s (%s): %v",
 					extEp.Name(), extEp.ID(), err)
 					extEp.Name(), extEp.ID(), err)
 			}
 			}
 			defer func() {
 			defer func() {
 				if err != nil {
 				if err != nil {
-					if e := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
+					if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
 						log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
 						log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
 							extEp.Name(), extEp.ID(), e)
 							extEp.Name(), extEp.ID(), e)
 					}
 					}
@@ -699,7 +707,15 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption)
 	extEp = sb.getGatewayEndpoint()
 	extEp = sb.getGatewayEndpoint()
 	if moveExtConn && extEp != nil {
 	if moveExtConn && extEp != nil {
 		log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
 		log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
-		if err := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
+		extN, err := extEp.getNetworkFromStore()
+		if err != nil {
+			return fmt.Errorf("failed to get network from store during leave: %v", err)
+		}
+		extD, err := extN.driver(true)
+		if err != nil {
+			return fmt.Errorf("failed to leave endpoint: %v", err)
+		}
+		if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
 			log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
 			log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
 				extEp.Name(), extEp.ID(), err)
 				extEp.Name(), extEp.ID(), err)
 		}
 		}

+ 28 - 21
vendor/src/github.com/docker/libnetwork/ipam/allocator.go

@@ -199,12 +199,22 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
 // RequestPool returns an address pool along with its unique id.
 // RequestPool returns an address pool along with its unique id.
 func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
 func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
 	log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
 	log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
-retry:
-	k, nw, ipr, pdf, err := a.parsePoolRequest(addressSpace, pool, subPool, v6)
+
+	k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6)
 	if err != nil {
 	if err != nil {
 		return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err)
 		return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err)
 	}
 	}
 
 
+	pdf := k == nil
+
+retry:
+	if pdf {
+		if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
+			return "", nil, nil, err
+		}
+		k = &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String()}
+	}
+
 	if err := a.refresh(addressSpace); err != nil {
 	if err := a.refresh(addressSpace); err != nil {
 		return "", nil, nil, err
 		return "", nil, nil, err
 	}
 	}
@@ -279,39 +289,36 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
 	return aSpace, nil
 	return aSpace, nil
 }
 }
 
 
-func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, bool, error) {
+func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) {
 	var (
 	var (
 		nw  *net.IPNet
 		nw  *net.IPNet
 		ipr *AddressRange
 		ipr *AddressRange
 		err error
 		err error
-		pdf = false
 	)
 	)
 
 
 	if addressSpace == "" {
 	if addressSpace == "" {
-		return nil, nil, nil, false, ipamapi.ErrInvalidAddressSpace
+		return nil, nil, nil, ipamapi.ErrInvalidAddressSpace
 	}
 	}
 
 
 	if pool == "" && subPool != "" {
 	if pool == "" && subPool != "" {
-		return nil, nil, nil, false, ipamapi.ErrInvalidSubPool
+		return nil, nil, nil, ipamapi.ErrInvalidSubPool
 	}
 	}
 
 
-	if pool != "" {
-		if _, nw, err = net.ParseCIDR(pool); err != nil {
-			return nil, nil, nil, false, ipamapi.ErrInvalidPool
-		}
-		if subPool != "" {
-			if ipr, err = getAddressRange(subPool, nw); err != nil {
-				return nil, nil, nil, false, err
-			}
-		}
-	} else {
-		if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
-			return nil, nil, nil, false, err
+	if pool == "" {
+		return nil, nil, nil, nil
+	}
+
+	if _, nw, err = net.ParseCIDR(pool); err != nil {
+		return nil, nil, nil, ipamapi.ErrInvalidPool
+	}
+
+	if subPool != "" {
+		if ipr, err = getAddressRange(subPool, nw); err != nil {
+			return nil, nil, nil, err
 		}
 		}
-		pdf = true
 	}
 	}
 
 
-	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, pdf, nil
+	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil
 }
 }
 
 
 func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
 func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
@@ -406,7 +413,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
 		}
 		}
 	}
 	}
 
 
-	return nil, types.NotFoundErrorf("could not find an available predefined network")
+	return nil, types.NotFoundErrorf("could not find an available non-overlapping address pool among the defaults to auto assign to the network")
 }
 }
 
 
 // RequestAddress returns an address from the specified pool ID
 // RequestAddress returns an address from the specified pool ID

+ 6 - 4
vendor/src/github.com/docker/libnetwork/netutils/utils_freebsd.go

@@ -7,10 +7,12 @@ import (
 )
 )
 
 
 // ElectInterfaceAddresses looks for an interface on the OS with the specified 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) {
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
 	return nil, nil, types.NotImplementedErrorf("not supported on freebsd")
 	return nil, nil, types.NotImplementedErrorf("not supported on freebsd")
 }
 }
 
 

+ 11 - 10
vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go

@@ -62,15 +62,15 @@ func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, err
 }
 }
 
 
 // ElectInterfaceAddresses looks for an interface on the OS with the
 // 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 predefined
+// specified name and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
 // list the first IPv4 address which does not conflict with other
 // list the first IPv4 address which does not conflict with other
 // interfaces on the system.
 // interfaces on the system.
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
 	var (
 	var (
-		v4Net  *net.IPNet
+		v4Nets []*net.IPNet
 		v6Nets []*net.IPNet
 		v6Nets []*net.IPNet
-		err    error
 	)
 	)
 
 
 	defer osl.InitOSContext()()
 	defer osl.InitOSContext()()
@@ -85,23 +85,24 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
 		if err != nil {
 		if err != nil {
 			return nil, nil, err
 			return nil, nil, err
 		}
 		}
-		if len(v4addr) > 0 {
-			v4Net = v4addr[0].IPNet
+		for _, nlAddr := range v4addr {
+			v4Nets = append(v4Nets, nlAddr.IPNet)
 		}
 		}
 		for _, nlAddr := range v6addr {
 		for _, nlAddr := range v6addr {
 			v6Nets = append(v6Nets, nlAddr.IPNet)
 			v6Nets = append(v6Nets, nlAddr.IPNet)
 		}
 		}
 	}
 	}
 
 
-	if link == nil || v4Net == nil {
+	if link == nil || len(v4Nets) == 0 {
 		// Choose from predefined broad networks
 		// Choose from predefined broad networks
-		v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
+		v4Net, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
 		if err != nil {
 		if err != nil {
 			return nil, nil, err
 			return nil, nil, err
 		}
 		}
+		v4Nets = append(v4Nets, v4Net)
 	}
 	}
 
 
-	return v4Net, v6Nets, nil
+	return v4Nets, v6Nets, nil
 }
 }
 
 
 // FindAvailableNetwork returns a network from the passed list which does not
 // FindAvailableNetwork returns a network from the passed list which does not

+ 7 - 5
vendor/src/github.com/docker/libnetwork/netutils/utils_solaris.go

@@ -22,10 +22,12 @@ func CheckRouteOverlaps(toCheck *net.IPNet) error {
 }
 }
 
 
 // ElectInterfaceAddresses looks for an interface on the OS with the specified 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) {
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// 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 (
 	var (
 		v4Net *net.IPNet
 		v4Net *net.IPNet
 	)
 	)
@@ -63,7 +65,7 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
 			return nil, nil, err
 			return nil, nil, err
 		}
 		}
 	}
 	}
-	return v4Net, nil, nil
+	return []*net.IPNet{v4Net}, nil, nil
 }
 }
 
 
 // FindAvailableNetwork returns a network from the passed list which does not
 // FindAvailableNetwork returns a network from the passed list which does not

+ 6 - 4
vendor/src/github.com/docker/libnetwork/netutils/utils_windows.go

@@ -7,10 +7,12 @@ import (
 )
 )
 
 
 // ElectInterfaceAddresses looks for an interface on the OS with the specified 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) {
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation.
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned.
+// If the interface does not exist, it chooses from a predefined
+// list the first IPv4 address which does not conflict with other
+// interfaces on the system.
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
 	return nil, nil, types.NotImplementedErrorf("not supported on windows")
 	return nil, nil, types.NotImplementedErrorf("not supported on windows")
 }
 }
 
 

+ 19 - 3
vendor/src/github.com/docker/libnetwork/networkdb/cluster.go

@@ -16,9 +16,11 @@ import (
 )
 )
 
 
 const (
 const (
-	reapInterval  = 60 * time.Second
-	reapPeriod    = 5 * time.Second
-	retryInterval = 1 * time.Second
+	reapInterval     = 60 * time.Second
+	reapPeriod       = 5 * time.Second
+	retryInterval    = 1 * time.Second
+	nodeReapInterval = 24 * time.Hour
+	nodeReapPeriod   = 2 * time.Hour
 )
 )
 
 
 type logWriter struct{}
 type logWriter struct{}
@@ -147,6 +149,7 @@ func (nDB *NetworkDB) clusterInit() error {
 		{config.GossipInterval, nDB.gossip},
 		{config.GossipInterval, nDB.gossip},
 		{config.PushPullInterval, nDB.bulkSyncTables},
 		{config.PushPullInterval, nDB.bulkSyncTables},
 		{retryInterval, nDB.reconnectNode},
 		{retryInterval, nDB.reconnectNode},
+		{nodeReapPeriod, nDB.reapDeadNode},
 	} {
 	} {
 		t := time.NewTicker(trigger.interval)
 		t := time.NewTicker(trigger.interval)
 		go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn)
 		go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn)
@@ -234,6 +237,19 @@ func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, sto
 	}
 	}
 }
 }
 
 
+func (nDB *NetworkDB) reapDeadNode() {
+	nDB.Lock()
+	defer nDB.Unlock()
+	for id, n := range nDB.failedNodes {
+		if n.reapTime > 0 {
+			n.reapTime -= reapPeriod
+			continue
+		}
+		logrus.Debugf("Removing failed node %v from gossip cluster", n.Name)
+		delete(nDB.failedNodes, id)
+	}
+}
+
 func (nDB *NetworkDB) reconnectNode() {
 func (nDB *NetworkDB) reconnectNode() {
 	nDB.RLock()
 	nDB.RLock()
 	if len(nDB.failedNodes) == 0 {
 	if len(nDB.failedNodes) == 0 {

+ 2 - 0
vendor/src/github.com/docker/libnetwork/networkdb/event_delegate.go

@@ -29,6 +29,8 @@ func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) {
 	e.nDB.Lock()
 	e.nDB.Lock()
 	if n, ok := e.nDB.nodes[mn.Name]; ok {
 	if n, ok := e.nDB.nodes[mn.Name]; ok {
 		delete(e.nDB.nodes, mn.Name)
 		delete(e.nDB.nodes, mn.Name)
+
+		n.reapTime = reapInterval
 		e.nDB.failedNodes[mn.Name] = n
 		e.nDB.failedNodes[mn.Name] = n
 	}
 	}
 	e.nDB.Unlock()
 	e.nDB.Unlock()

+ 2 - 0
vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go

@@ -94,6 +94,8 @@ type NetworkDB struct {
 type node struct {
 type node struct {
 	memberlist.Node
 	memberlist.Node
 	ltime serf.LamportTime
 	ltime serf.LamportTime
+	// Number of hours left before the reaper removes the node
+	reapTime time.Duration
 }
 }
 
 
 // network describes the node/network attachment.
 // network describes the node/network attachment.