瀏覽代碼

Merge pull request #15584 from mavenugo/ln-vendor-in

Vendoring in libnetwork 22dc04d06067b40a9e7ef575aee6d1bb69d4dcc3
Alexander Morozov 10 年之前
父節點
當前提交
d1fada4bf7
共有 29 個文件被更改,包括 657 次插入440 次删除
  1. 7 7
      daemon/daemon_unix.go
  2. 2 2
      hack/vendor.sh
  3. 1 1
      vendor/src/github.com/docker/libnetwork/README.md
  4. 24 35
      vendor/src/github.com/docker/libnetwork/api/api.go
  5. 61 58
      vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go
  6. 0 11
      vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go
  7. 2 2
      vendor/src/github.com/docker/libnetwork/drivers/bridge/link.go
  8. 3 11
      vendor/src/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go
  9. 7 2
      vendor/src/github.com/docker/libnetwork/drivers/bridge/port_mapping.go
  10. 6 1
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go
  11. 11 7
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go
  12. 53 8
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
  13. 9 3
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go
  14. 35 10
      vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go
  15. 33 3
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go
  16. 2 1
      vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go
  17. 144 0
      vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go
  18. 85 19
      vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go
  19. 0 178
      vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go
  20. 1 6
      vendor/src/github.com/docker/libnetwork/endpoint.go
  21. 34 25
      vendor/src/github.com/docker/libnetwork/iptables/iptables.go
  22. 17 7
      vendor/src/github.com/docker/libnetwork/netutils/utils.go
  23. 79 21
      vendor/src/github.com/docker/libnetwork/portallocator/portallocator.go
  24. 12 5
      vendor/src/github.com/docker/libnetwork/portmapper/mapper.go
  25. 1 1
      vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go
  26. 14 11
      vendor/src/github.com/docker/libnetwork/types/types.go
  27. 2 1
      vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go
  28. 9 0
      vendor/src/github.com/vishvananda/netlink/nl/route_linux.go
  29. 3 4
      vendor/src/github.com/vishvananda/netlink/route_linux.go

+ 7 - 7
daemon/daemon_unix.go

@@ -392,19 +392,19 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
 
 func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
 	option := options.Generic{
-		"EnableIPForwarding": config.Bridge.EnableIPForward}
+		"EnableIPForwarding":  config.Bridge.EnableIPForward,
+		"EnableIPTables":      config.Bridge.EnableIPTables,
+		"EnableUserlandProxy": config.Bridge.EnableUserlandProxy}
 
 	if err := controller.ConfigureNetworkDriver("bridge", options.Generic{netlabel.GenericData: option}); err != nil {
 		return fmt.Errorf("Error initializing bridge driver: %v", err)
 	}
 
 	netOption := options.Generic{
-		"BridgeName":          config.Bridge.Iface,
-		"Mtu":                 config.Mtu,
-		"EnableIPTables":      config.Bridge.EnableIPTables,
-		"EnableIPMasquerade":  config.Bridge.EnableIPMasq,
-		"EnableICC":           config.Bridge.InterContainerCommunication,
-		"EnableUserlandProxy": config.Bridge.EnableUserlandProxy,
+		"BridgeName":         config.Bridge.Iface,
+		"Mtu":                config.Mtu,
+		"EnableIPMasquerade": config.Bridge.EnableIPMasq,
+		"EnableICC":          config.Bridge.InterContainerCommunication,
 	}
 
 	if config.Bridge.IP != "" {

+ 2 - 2
hack/vendor.sh

@@ -21,14 +21,14 @@ clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://gith
 clone hg code.google.com/p/gosqlite 74691fb6f837
 
 #get libnetwork packages
-clone git github.com/docker/libnetwork bd3eecc96f3c05a4acef1bedcf74397bc6850d22
+clone git github.com/docker/libnetwork 22dc04d06067b40a9e7ef575aee6d1bb69d4dcc3
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
 clone git github.com/hashicorp/serf 7151adcef72687bf95f451a2e0ba15cb19412bf2
 clone git github.com/docker/libkv 60c7c881345b3c67defc7f93a8297debf041d43c
 clone git github.com/vishvananda/netns 493029407eeb434d0c2d44e02ea072ff2488d322
-clone git github.com/vishvananda/netlink 20397a138846e4d6590e01783ed023ed7e1c38a6
+clone git github.com/vishvananda/netlink 329b40d4e308deb2abe80dbb1f74078e5ab13164
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
 clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
 clone git github.com/coreos/go-etcd v2.0.0

+ 1 - 1
vendor/src/github.com/docker/libnetwork/README.md

@@ -64,7 +64,7 @@ There are many networking solutions available to suit a broad range of use-cases
 		epInfo, err := ep.DriverInfo()
 		mapData, ok := epInfo[netlabel.PortMap]
 		if ok {
-			portMapping, ok := mapData.([]netutils.PortBinding)
+			portMapping, ok := mapData.([]types.PortBinding)
 			if ok {
 				fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
 			}

+ 24 - 35
vendor/src/github.com/docker/libnetwork/api/api.go

@@ -22,20 +22,24 @@ var (
 
 const (
 	// Resource name regex
+	// Gorilla mux encloses the passed pattern with '^' and '$'. So we need to do some tricks
+	// to have mux eventually build a query regex which matches empty or word string (`^$|[\w]+`)
 	regex = "[a-zA-Z_0-9-]+"
+	qregx = "$|" + regex
 	// Router URL variable definition
-	nwName = "{" + urlNwName + ":" + regex + "}"
-	nwID   = "{" + urlNwID + ":" + regex + "}"
-	nwPID  = "{" + urlNwPID + ":" + regex + "}"
-	epName = "{" + urlEpName + ":" + regex + "}"
-	epID   = "{" + urlEpID + ":" + regex + "}"
-	epPID  = "{" + urlEpPID + ":" + regex + "}"
-	cnID   = "{" + urlCnID + ":" + regex + "}"
-
-	// Though this name can be anything, in order to support default network,
-	// we will keep it as name
-	urlNwName = "name"
-	// Internal URL variable name, they can be anything
+	nwName   = "{" + urlNwName + ":" + regex + "}"
+	nwNameQr = "{" + urlNwName + ":" + qregx + "}"
+	nwID     = "{" + urlNwID + ":" + regex + "}"
+	nwPIDQr  = "{" + urlNwPID + ":" + qregx + "}"
+	epName   = "{" + urlEpName + ":" + regex + "}"
+	epNameQr = "{" + urlEpName + ":" + qregx + "}"
+	epID     = "{" + urlEpID + ":" + regex + "}"
+	epPIDQr  = "{" + urlEpPID + ":" + qregx + "}"
+	cnID     = "{" + urlCnID + ":" + regex + "}"
+
+	// Internal URL variable name.They can be anything as
+	// long as they do not collide with query fields.
+	urlNwName = "network-name"
 	urlNwID   = "network-id"
 	urlNwPID  = "network-partial-id"
 	urlEpName = "endpoint-name"
@@ -89,17 +93,17 @@ func (h *httpHandler) initRouter() {
 	}{
 		"GET": {
 			// Order matters
-			{"/networks", []string{"name", nwName}, procGetNetworks},
-			{"/networks", []string{"partial-id", nwPID}, procGetNetworks},
+			{"/networks", []string{"name", nwNameQr}, procGetNetworks},
+			{"/networks", []string{"partial-id", nwPIDQr}, procGetNetworks},
 			{"/networks", nil, procGetNetworks},
 			{"/networks/" + nwID, nil, procGetNetwork},
-			{"/networks/" + nwID + "/endpoints", []string{"name", epName}, procGetEndpoints},
-			{"/networks/" + nwID + "/endpoints", []string{"partial-id", epPID}, procGetEndpoints},
+			{"/networks/" + nwID + "/endpoints", []string{"name", epNameQr}, procGetEndpoints},
+			{"/networks/" + nwID + "/endpoints", []string{"partial-id", epPIDQr}, procGetEndpoints},
 			{"/networks/" + nwID + "/endpoints", nil, procGetEndpoints},
 			{"/networks/" + nwID + "/endpoints/" + epID, nil, procGetEndpoint},
-			{"/services", []string{"network", nwName}, procGetServices},
-			{"/services", []string{"name", epName}, procGetServices},
-			{"/services", []string{"partial-id", epPID}, procGetServices},
+			{"/services", []string{"network", nwNameQr}, procGetServices},
+			{"/services", []string{"name", epNameQr}, procGetServices},
+			{"/services", []string{"partial-id", epPIDQr}, procGetServices},
 			{"/services", nil, procGetServices},
 			{"/services/" + epID, nil, procGetService},
 			{"/services/" + epID + "/backend", nil, procGetContainers},
@@ -150,22 +154,7 @@ func makeHandler(ctrl libnetwork.NetworkController, fct processor) http.HandlerF
 			}
 		}
 
-		mvars := mux.Vars(req)
-		rvars := req.URL.Query()
-		// workaround a mux issue which filters out valid queries with empty value
-		for k := range rvars {
-			if _, ok := mvars[k]; !ok {
-				if rvars.Get(k) == "" {
-					mvars[k] = ""
-				}
-			}
-		}
-
-		res, rsp := fct(ctrl, mvars, body)
-		if !rsp.isOK() {
-			http.Error(w, rsp.Status, rsp.StatusCode)
-			return
-		}
+		res, rsp := fct(ctrl, mux.Vars(req), body)
 		if res != nil {
 			writeJSON(w, rsp.StatusCode, res)
 		}

+ 61 - 58
vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go

@@ -5,9 +5,11 @@ import (
 	"fmt"
 	"io/ioutil"
 	"net"
+	"os"
 	"os/exec"
 	"path/filepath"
 	"strconv"
+	"strings"
 	"sync"
 	"syscall"
 
@@ -38,7 +40,9 @@ var (
 
 // configuration info for the "bridge" driver.
 type configuration struct {
-	EnableIPForwarding bool
+	EnableIPForwarding  bool
+	EnableIPTables      bool
+	EnableUserlandProxy bool
 }
 
 // networkConfiguration for network specific configuration
@@ -48,7 +52,6 @@ type networkConfiguration struct {
 	FixedCIDR             *net.IPNet
 	FixedCIDRv6           *net.IPNet
 	EnableIPv6            bool
-	EnableIPTables        bool
 	EnableIPMasquerade    bool
 	EnableICC             bool
 	Mtu                   int
@@ -56,7 +59,6 @@ type networkConfiguration struct {
 	DefaultGatewayIPv6    net.IP
 	DefaultBindingIP      net.IP
 	AllowNonDefaultBridge bool
-	EnableUserlandProxy   bool
 }
 
 // endpointConfiguration represents the user specified configuration for the sandbox endpoint
@@ -89,13 +91,16 @@ type bridgeNetwork struct {
 	config     *networkConfiguration
 	endpoints  map[types.UUID]*bridgeEndpoint // key: endpoint id
 	portMapper *portmapper.PortMapper
+	driver     *driver // The network's driver
 	sync.Mutex
 }
 
 type driver struct {
-	config   *configuration
-	network  *bridgeNetwork
-	networks map[types.UUID]*bridgeNetwork
+	config      *configuration
+	network     *bridgeNetwork
+	natChain    *iptables.ChainInfo
+	filterChain *iptables.ChainInfo
+	networks    map[types.UUID]*bridgeNetwork
 	sync.Mutex
 }
 
@@ -110,10 +115,13 @@ func newDriver() driverapi.Driver {
 
 // Init registers a new instance of bridge driver
 func Init(dc driverapi.DriverCallback) error {
-	// try to modprobe bridge first
-	// see gh#12177
-	if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat", "br_netfilter").CombinedOutput(); err != nil {
-		logrus.Warnf("Running modprobe bridge nf_nat br_netfilter failed with message: %s, error: %v", out, err)
+	if _, err := os.Stat("/proc/sys/net/bridge"); err != nil {
+		if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil {
+			logrus.Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err)
+		}
+	}
+	if out, err := exec.Command("modprobe", "-va", "nf_nat").CombinedOutput(); err != nil {
+		logrus.Warnf("Running modprobe nf_nat failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
 	}
 	if err := iptables.FirewalldInit(); err != nil {
 		logrus.Debugf("Fail to initialize firewalld: %v, using raw iptables instead", err)
@@ -218,16 +226,6 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
 		}
 	}
 
-	if i, ok := data["EnableIPTables"]; ok && i != nil {
-		if s, ok := i.(string); ok {
-			if c.EnableIPTables, err = strconv.ParseBool(s); err != nil {
-				return types.BadRequestErrorf("failed to parse EnableIPTables value: %s", err.Error())
-			}
-		} else {
-			return types.BadRequestErrorf("invalid type for EnableIPTables value")
-		}
-	}
-
 	if i, ok := data["EnableIPMasquerade"]; ok && i != nil {
 		if s, ok := i.(string); ok {
 			if c.EnableIPMasquerade, err = strconv.ParseBool(s); err != nil {
@@ -329,6 +327,25 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
 	return nil
 }
 
+func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
+	n.Lock()
+	defer n.Unlock()
+
+	if n.driver == nil {
+		return nil, nil, types.BadRequestErrorf("no driver found")
+	}
+
+	return n.driver.natChain, n.driver.filterChain, nil
+}
+
+func (n *bridgeNetwork) getNetworkBridgeName() string {
+	n.Lock()
+	config := n.config
+	n.Unlock()
+
+	return config.BridgeName
+}
+
 func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
 	n.Lock()
 	defer n.Unlock()
@@ -413,6 +430,7 @@ func (c *networkConfiguration) conflictsWithNetworks(id types.UUID, others []*br
 
 func (d *driver) Config(option map[string]interface{}) error {
 	var config *configuration
+	var err error
 
 	d.Lock()
 	defer d.Unlock()
@@ -439,10 +457,19 @@ func (d *driver) Config(option map[string]interface{}) error {
 		d.config = config
 	} else {
 		config = &configuration{}
+		d.config = config
 	}
 
 	if config.EnableIPForwarding {
-		return setupIPForwarding(config)
+		err = setupIPForwarding()
+		if err != nil {
+			return err
+		}
+	}
+
+	if config.EnableIPTables {
+		d.natChain, d.filterChain, err = setupIPChains(config)
+		return err
 	}
 
 	return nil
@@ -475,7 +502,6 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
 	case map[string]interface{}:
 		config = &networkConfiguration{
 			EnableICC:          true,
-			EnableIPTables:     true,
 			EnableIPMasquerade: true,
 		}
 		err = config.fromMap(opt)
@@ -573,6 +599,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 		endpoints:  make(map[types.UUID]*bridgeEndpoint),
 		config:     config,
 		portMapper: portmapper.New(),
+		driver:     d,
 	}
 
 	d.Lock()
@@ -655,14 +682,14 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 		{enableIPv6Forwarding, setupIPv6Forwarding},
 
 		// Setup Loopback Adresses Routing
-		{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},
+		{!d.config.EnableUserlandProxy, setupLoopbackAdressesRouting},
 
 		// Setup IPTables.
-		{config.EnableIPTables, network.setupIPTables},
+		{d.config.EnableIPTables, network.setupIPTables},
 
 		//We want to track firewalld configuration so that
 		//if it is started/reloaded, the rules can be applied correctly
-		{config.EnableIPTables, network.setupFirewalld},
+		{d.config.EnableIPTables, network.setupFirewalld},
 
 		// Setup DefaultGatewayIPv4
 		{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
@@ -671,10 +698,10 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 		{config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},
 
 		// Add inter-network communication rules.
-		{config.EnableIPTables, setupNetworkIsolationRules},
+		{d.config.EnableIPTables, setupNetworkIsolationRules},
 
 		//Configure bridge networking filtering if ICC is off and IP tables are enabled
-		{!config.EnableICC && config.EnableIPTables, setupBridgeNetFiltering},
+		{!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering},
 	} {
 		if step.Condition {
 			bridgeSetup.queueStep(step.Fn)
@@ -833,6 +860,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	// Get the network handler and make sure it exists
 	d.Lock()
 	n, ok := d.networks[nid]
+	dconfig := d.config
 	d.Unlock()
 
 	if !ok {
@@ -945,7 +973,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 		return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
 	}
 
-	if !config.EnableUserlandProxy {
+	if !dconfig.EnableUserlandProxy {
 		err = setHairpinMode(host, true)
 		if err != nil {
 			return err
@@ -1018,7 +1046,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 
 	// Program any required port mapping and store them in the endpoint
-	endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, config.EnableUserlandProxy)
+	endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
 	if err != nil {
 		return err
 	}
@@ -1101,9 +1129,9 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
 	}
 
 	// Try removal of link. Discard error: link pair might have
-	// already been deleted by sandbox delete.
-	link, err := netlink.LinkByName(ep.srcName)
-	if err == nil {
+	// already been deleted by sandbox delete. Make sure defer
+	// does not see this error either.
+	if link, err := netlink.LinkByName(ep.srcName); err == nil {
 		netlink.LinkDel(link)
 	}
 
@@ -1381,34 +1409,9 @@ func parseContainerOptions(cOptions map[string]interface{}) (*containerConfigura
 	}
 }
 
-// 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 electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr {
 	if epConfig != nil && epConfig.MacAddress != nil {
 		return epConfig.MacAddress
 	}
-	return generateMacAddr(ip)
+	return netutils.GenerateMACFromIP(ip)
 }

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

@@ -115,17 +115,6 @@ func (eim ErrInvalidMtu) Error() string {
 // BadRequest denotes the type of this error
 func (eim ErrInvalidMtu) BadRequest() {}
 
-// ErrIPFwdCfg is returned when ip forwarding setup is invoked when the configuration
-// not enabled.
-type ErrIPFwdCfg struct{}
-
-func (eipf *ErrIPFwdCfg) Error() string {
-	return "unexpected request to enable IP Forwarding"
-}
-
-// BadRequest denotes the type of this error
-func (eipf *ErrIPFwdCfg) BadRequest() {}
-
 // ErrInvalidPort is returned when the container or host port specified in the port binding is not valid.
 type ErrInvalidPort string
 

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

@@ -74,9 +74,9 @@ func linkContainers(action, parentIP, childIP string, ports []types.TransportPor
 		return InvalidLinkIPAddrError(childIP)
 	}
 
-	chain := iptables.Chain{Name: DockerChain, Bridge: bridge}
+	chain := iptables.ChainInfo{Name: DockerChain}
 	for _, port := range ports {
-		err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String())
+		err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
 		if !ignoreErrors && err != nil {
 			return err
 		}

+ 3 - 11
vendor/src/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go

@@ -7,6 +7,8 @@ import (
 	"syscall"
 	"time"
 	"unsafe"
+
+	"github.com/docker/libnetwork/netutils"
 )
 
 const (
@@ -74,16 +76,6 @@ func ioctlAddToBridge(iface, master *net.Interface) error {
 	return ifIoctBridge(iface, master, ioctlBrAddIf)
 }
 
-func randMacAddr() string {
-	hw := make(net.HardwareAddr, 6)
-	for i := 0; i < 6; i++ {
-		hw[i] = byte(rnd.Intn(255))
-	}
-	hw[0] &^= 0x1 // clear multicast bit
-	hw[0] |= 0x2  // set local assignment bit (IEEE802)
-	return hw.String()
-}
-
 func ioctlSetMacAddress(name, addr string) error {
 	if len(name) >= ifNameSize {
 		return fmt.Errorf("Interface name %s too long", name)
@@ -133,7 +125,7 @@ func ioctlCreateBridge(name string, setMacAddr bool) error {
 		return err
 	}
 	if setMacAddr {
-		return ioctlSetMacAddress(name, randMacAddr())
+		return ioctlSetMacAddress(name, netutils.GenerateRandomMAC().String())
 	}
 	return nil
 }

+ 7 - 2
vendor/src/github.com/docker/libnetwork/drivers/bridge/port_mapping.go

@@ -57,6 +57,11 @@ func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHos
 		bnd.HostIP = defHostIP
 	}
 
+	// Adjust HostPortEnd if this is not a range.
+	if bnd.HostPortEnd == 0 {
+		bnd.HostPortEnd = bnd.HostPort
+	}
+
 	// Construct the container side transport address
 	container, err := bnd.ContainerAddr()
 	if err != nil {
@@ -65,12 +70,12 @@ func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHos
 
 	// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
 	for i := 0; i < maxAllocatePortAttempts; i++ {
-		if host, err = n.portMapper.Map(container, bnd.HostIP, int(bnd.HostPort), ulPxyEnabled); err == nil {
+		if host, err = n.portMapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), ulPxyEnabled); err == nil {
 			break
 		}
 		// There is no point in immediately retrying to map an explicitly chosen port.
 		if bnd.HostPort != 0 {
-			logrus.Warnf("Failed to allocate and map port %d: %s", bnd.HostPort, err)
+			logrus.Warnf("Failed to allocate and map port %d-%d: %s", bnd.HostPort, bnd.HostPortEnd, err)
 			break
 		}
 		logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)

+ 6 - 1
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go

@@ -3,8 +3,13 @@ package bridge
 import "github.com/docker/libnetwork/iptables"
 
 func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
+	d := n.driver
+	d.Lock()
+	driverConfig := d.config
+	d.Unlock()
+
 	// Sanity check.
-	if config.EnableIPTables == false {
+	if driverConfig.EnableIPTables == false {
 		return IPTableCfgError(config.BridgeName)
 	}
 

+ 11 - 7
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go

@@ -10,15 +10,19 @@ const (
 	ipv4ForwardConfPerm = 0644
 )
 
-func setupIPForwarding(config *configuration) error {
-	// Sanity Check
-	if config.EnableIPForwarding == false {
-		return &ErrIPFwdCfg{}
+func setupIPForwarding() error {
+	// Get current IPv4 forward setup
+	ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf)
+	if err != nil {
+		return fmt.Errorf("Cannot read IP forwarding setup: %v", err)
 	}
 
-	// Enable IPv4 forwarding
-	if err := ioutil.WriteFile(ipv4ForwardConf, []byte{'1', '\n'}, ipv4ForwardConfPerm); err != nil {
-		return fmt.Errorf("Setup IP forwarding failed: %v", err)
+	// Enable IPv4 forwarding only if it is not already enabled
+	if ipv4ForwardData[0] != '1' {
+		// Enable IPv4 forwarding
+		if err := ioutil.WriteFile(ipv4ForwardConf, []byte{'1', '\n'}, ipv4ForwardConfPerm); err != nil {
+			return fmt.Errorf("Setup IP forwarding failed: %v", err)
+		}
 	}
 
 	return nil

+ 53 - 8
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"net"
 
+	"github.com/Sirupsen/logrus"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/netutils"
 )
@@ -13,33 +14,77 @@ const (
 	DockerChain = "DOCKER"
 )
 
-func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
+func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, error) {
 	// Sanity check.
 	if config.EnableIPTables == false {
-		return IPTableCfgError(config.BridgeName)
+		return nil, nil, fmt.Errorf("Cannot create new chains, EnableIPTable is disabled")
 	}
 
 	hairpinMode := !config.EnableUserlandProxy
 
+	natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode)
+	if err != nil {
+		return nil, nil, fmt.Errorf("Failed to create NAT chain: %s", err.Error())
+	}
+	defer func() {
+		if err != nil {
+			if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
+				logrus.Warnf("Failed on removing iptables NAT chain on cleanup: %v", err)
+			}
+		}
+	}()
+
+	filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, hairpinMode)
+	if err != nil {
+		return nil, nil, fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
+	}
+
+	return natChain, filterChain, nil
+}
+
+func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
+	d := n.driver
+	d.Lock()
+	driverConfig := d.config
+	d.Unlock()
+
+	// Sanity check.
+	if driverConfig.EnableIPTables == false {
+		return fmt.Errorf("Cannot program chains, EnableIPTable is disabled")
+	}
+
+	// Pickup this configuraton option from driver
+	hairpinMode := !driverConfig.EnableUserlandProxy
+
 	addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
 	if err != nil {
 		return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
 	}
-	if err = setupIPTablesInternal(config.BridgeName, addrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
+	ipnet := addrv4.(*net.IPNet)
+	maskedAddrv4 := &net.IPNet{
+		IP:   ipnet.IP.Mask(ipnet.Mask),
+		Mask: ipnet.Mask,
+	}
+	if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
 		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
 	}
 
-	_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat, hairpinMode)
+	natChain, filterChain, err := n.getDriverChains()
+	if err != nil {
+		return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
+	}
+
+	err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode)
 	if err != nil {
-		return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
+		return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
 	}
 
-	chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter, hairpinMode)
+	err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode)
 	if err != nil {
-		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
+		return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
 	}
 
-	n.portMapper.SetIptablesChain(chain)
+	n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
 
 	return nil
 }

+ 9 - 3
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go

@@ -131,10 +131,16 @@ func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
 }
 
 func setupLoopbackAdressesRouting(config *networkConfiguration, i *bridgeInterface) error {
-	// Enable loopback adresses routing
 	sysPath := filepath.Join("/proc/sys/net/ipv4/conf", config.BridgeName, "route_localnet")
-	if err := ioutil.WriteFile(sysPath, []byte{'1', '\n'}, 0644); err != nil {
-		return fmt.Errorf("Unable to enable local routing for hairpin mode: %v", err)
+	ipv4LoRoutingData, err := ioutil.ReadFile(sysPath)
+	if err != nil {
+		return fmt.Errorf("Cannot read IPv4 local routing setup: %v", err)
+	}
+	// Enable loopback adresses routing only if it isn't already enabled
+	if ipv4LoRoutingData[0] != '1' {
+		if err := ioutil.WriteFile(sysPath, []byte{'1', '\n'}, 0644); err != nil {
+			return fmt.Errorf("Unable to enable local routing for hairpin mode: %v", err)
+		}
 	}
 	return nil
 }

+ 35 - 10
vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go

@@ -12,8 +12,10 @@ import (
 var bridgeIPv6 *net.IPNet
 
 const (
-	bridgeIPv6Str       = "fe80::1/64"
-	ipv6ForwardConfPerm = 0644
+	bridgeIPv6Str          = "fe80::1/64"
+	ipv6ForwardConfPerm    = 0644
+	ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
+	ipv6ForwardConfAll     = "/proc/sys/net/ipv6/conf/all/forwarding"
 )
 
 func init() {
@@ -27,10 +29,16 @@ func init() {
 }
 
 func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
-	// Enable IPv6 on the bridge
 	procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
-	if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
-		return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
+	ipv6BridgeData, err := ioutil.ReadFile(procFile)
+	if err != nil {
+		return fmt.Errorf("Cannot read IPv6 setup for bridge %v: %v", config.BridgeName, err)
+	}
+	// Enable IPv6 on the bridge only if it isn't already enabled
+	if ipv6BridgeData[0] != '0' {
+		if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
+			return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
+		}
 	}
 
 	_, addrsv6, err := i.addresses()
@@ -70,12 +78,29 @@ func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
 }
 
 func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error {
-	// Enable IPv6 forwarding
-	if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
-		logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err)
+	// Get current IPv6 default forwarding setup
+	ipv6ForwardDataDefault, err := ioutil.ReadFile(ipv6ForwardConfDefault)
+	if err != nil {
+		return fmt.Errorf("Cannot read IPv6 default forwarding setup: %v", err)
 	}
-	if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/all/forwarding", []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
-		logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err)
+	// Enable IPv6 default forwarding only if it is not already enabled
+	if ipv6ForwardDataDefault[0] != '1' {
+		if err := ioutil.WriteFile(ipv6ForwardConfDefault, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
+			logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err)
+		}
 	}
+
+	// Get current IPv6 all forwarding setup
+	ipv6ForwardDataAll, err := ioutil.ReadFile(ipv6ForwardConfAll)
+	if err != nil {
+		return fmt.Errorf("Cannot read IPv6 all forwarding setup: %v", err)
+	}
+	// Enable IPv6 all forwarding only if it is not already enabled
+	if ipv6ForwardDataAll[0] != '1' {
+		if err := ioutil.WriteFile(ipv6ForwardConfAll, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
+			logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err)
+		}
+	}
+
 	return nil
 }

+ 33 - 3
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go

@@ -30,6 +30,9 @@ type network struct {
 	vxlanName   string
 	driver      *driver
 	joinCnt     int
+	once        *sync.Once
+	initEpoch   int
+	initErr     error
 	sync.Mutex
 }
 
@@ -42,6 +45,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 		id:        id,
 		driver:    d,
 		endpoints: endpointTable{},
+		once:      &sync.Once{},
 	}
 
 	n.gw = bridgeIP.IP
@@ -77,10 +81,26 @@ func (n *network) joinSandbox() error {
 		n.Unlock()
 		return nil
 	}
-	n.joinCnt++
 	n.Unlock()
 
-	return n.initSandbox()
+	// If there is a race between two go routines here only one will win
+	// the other will wait.
+	n.once.Do(func() {
+		// save the error status of initSandbox in n.initErr so that
+		// all the racing go routines are able to know the status.
+		n.initErr = n.initSandbox()
+	})
+
+	// Increment joinCnt in all the goroutines only when the one time initSandbox
+	// was a success.
+	n.Lock()
+	if n.initErr == nil {
+		n.joinCnt++
+	}
+	err := n.initErr
+	n.Unlock()
+
+	return err
 }
 
 func (n *network) leaveSandbox() {
@@ -90,6 +110,11 @@ func (n *network) leaveSandbox() {
 		n.Unlock()
 		return
 	}
+
+	// We are about to destroy sandbox since the container is leaving the network
+	// Reinitialize the once variable so that we will be able to trigger one time
+	// sandbox initialization(again) when another container joins subsequently.
+	n.once = &sync.Once{}
 	n.Unlock()
 
 	n.destroySandbox()
@@ -111,7 +136,12 @@ func (n *network) destroySandbox() {
 }
 
 func (n *network) initSandbox() error {
-	sbox, err := sandbox.NewSandbox(sandbox.GenerateKey(string(n.id)), true)
+	n.Lock()
+	n.initEpoch++
+	n.Unlock()
+
+	sbox, err := sandbox.NewSandbox(
+		sandbox.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+string(n.id)), true)
 	if err != nil {
 		return fmt.Errorf("could not create network sandbox: %v", err)
 	}

+ 2 - 1
vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go

@@ -6,6 +6,7 @@ import (
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
+	"github.com/vishvananda/netlink/nl"
 )
 
 func validateID(nid, eid types.UUID) error {
@@ -54,7 +55,7 @@ func createVxlan(vni uint32) (string, error) {
 		LinkAttrs: netlink.LinkAttrs{Name: name},
 		VxlanId:   int(vni),
 		Learning:  true,
-		Port:      vxlanPort,
+		Port:      int(nl.Swap16(vxlanPort)), //network endian order
 		Proxy:     true,
 		L3miss:    true,
 		L2miss:    true,

+ 144 - 0
vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go

@@ -0,0 +1,144 @@
+/*
+Package api represents all requests and responses suitable for conversation
+with a remote driver.
+*/
+package api
+
+import "net"
+
+// Response is the basic response structure used in all responses.
+type Response struct {
+	Err string
+}
+
+// GetError returns the error from the response, if any.
+func (r *Response) GetError() string {
+	return r.Err
+}
+
+// CreateNetworkRequest requests a new network.
+type CreateNetworkRequest struct {
+	// A network ID that remote plugins are expected to store for future
+	// reference.
+	NetworkID string
+
+	// A free form map->object interface for communication of options.
+	Options map[string]interface{}
+}
+
+// CreateNetworkResponse is the response to the CreateNetworkRequest.
+type CreateNetworkResponse struct {
+	Response
+}
+
+// DeleteNetworkRequest is the request to delete an existing network.
+type DeleteNetworkRequest struct {
+	// The ID of the network to delete.
+	NetworkID string
+}
+
+// DeleteNetworkResponse is the response to a request for deleting a network.
+type DeleteNetworkResponse struct {
+	Response
+}
+
+// CreateEndpointRequest is the request to create an endpoint within a network.
+type CreateEndpointRequest struct {
+	// Provided at create time, this will be the network id referenced.
+	NetworkID string
+	// The ID of the endpoint for later reference.
+	EndpointID string
+	Interfaces []*EndpointInterface
+	Options    map[string]interface{}
+}
+
+// EndpointInterface represents an interface endpoint.
+type EndpointInterface struct {
+	ID          int
+	Address     string
+	AddressIPv6 string
+	MacAddress  string
+}
+
+// CreateEndpointResponse is the response to the CreateEndpoint action.
+type CreateEndpointResponse struct {
+	Response
+	Interfaces []*EndpointInterface
+}
+
+// Interface is the representation of a linux interface.
+type Interface struct {
+	ID          int
+	Address     *net.IPNet
+	AddressIPv6 *net.IPNet
+	MacAddress  net.HardwareAddr
+}
+
+// DeleteEndpointRequest describes the API for deleting an endpoint.
+type DeleteEndpointRequest struct {
+	NetworkID  string
+	EndpointID string
+}
+
+// DeleteEndpointResponse is the response to the DeleteEndpoint action.
+type DeleteEndpointResponse struct {
+	Response
+}
+
+// EndpointInfoRequest retrieves information about the endpoint from the network driver.
+type EndpointInfoRequest struct {
+	NetworkID  string
+	EndpointID string
+}
+
+// EndpointInfoResponse is the response to an EndpointInfoRequest.
+type EndpointInfoResponse struct {
+	Response
+	Value map[string]interface{}
+}
+
+// JoinRequest describes the API for joining an endpoint to a sandbox.
+type JoinRequest struct {
+	NetworkID  string
+	EndpointID string
+	SandboxKey string
+	Options    map[string]interface{}
+}
+
+// InterfaceName is the struct represetation of a pair of devices with source
+// and destination, for the purposes of putting an endpoint into a container.
+type InterfaceName struct {
+	SrcName   string
+	DstName   string
+	DstPrefix string
+}
+
+// StaticRoute is the plain JSON representation of a static route.
+type StaticRoute struct {
+	Destination string
+	RouteType   int
+	NextHop     string
+	InterfaceID int
+}
+
+// JoinResponse is the response to a JoinRequest.
+type JoinResponse struct {
+	Response
+	InterfaceNames []*InterfaceName
+	Gateway        string
+	GatewayIPv6    string
+	HostsPath      string
+	ResolvConfPath string
+	StaticRoutes   []StaticRoute
+}
+
+// LeaveRequest describes the API for detaching an endpoint from a sandbox.
+type LeaveRequest struct {
+	NetworkID  string
+	EndpointID string
+}
+
+// LeaveResponse is the answer to LeaveRequest.
+type LeaveResponse struct {
+	Response
+}

+ 85 - 19
vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go

@@ -7,6 +7,7 @@ import (
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/plugins"
 	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/drivers/remote/api"
 	"github.com/docker/libnetwork/types"
 )
 
@@ -15,6 +16,10 @@ type driver struct {
 	networkType string
 }
 
+type maybeError interface {
+	GetError() string
+}
+
 func newDriver(name string, client *plugins.Client) driverapi.Driver {
 	return &driver{networkType: name, endpoint: client}
 }
@@ -46,23 +51,23 @@ func (d *driver) call(methodName string, arg interface{}, retVal maybeError) err
 	if err != nil {
 		return err
 	}
-	if e := retVal.getError(); e != "" {
+	if e := retVal.GetError(); e != "" {
 		return fmt.Errorf("remote: %s", e)
 	}
 	return nil
 }
 
 func (d *driver) CreateNetwork(id types.UUID, options map[string]interface{}) error {
-	create := &createNetworkRequest{
+	create := &api.CreateNetworkRequest{
 		NetworkID: string(id),
 		Options:   options,
 	}
-	return d.call("CreateNetwork", create, &createNetworkResponse{})
+	return d.call("CreateNetwork", create, &api.CreateNetworkResponse{})
 }
 
 func (d *driver) DeleteNetwork(nid types.UUID) error {
-	delete := &deleteNetworkRequest{NetworkID: string(nid)}
-	return d.call("DeleteNetwork", delete, &deleteNetworkResponse{})
+	delete := &api.DeleteNetworkRequest{NetworkID: string(nid)}
+	return d.call("DeleteNetwork", delete, &api.DeleteNetworkResponse{})
 }
 
 func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
@@ -70,29 +75,29 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 		return fmt.Errorf("must not be called with nil EndpointInfo")
 	}
 
-	reqIfaces := make([]*endpointInterface, len(epInfo.Interfaces()))
+	reqIfaces := make([]*api.EndpointInterface, len(epInfo.Interfaces()))
 	for i, iface := range epInfo.Interfaces() {
 		addr4 := iface.Address()
 		addr6 := iface.AddressIPv6()
-		reqIfaces[i] = &endpointInterface{
+		reqIfaces[i] = &api.EndpointInterface{
 			ID:          iface.ID(),
 			Address:     addr4.String(),
 			AddressIPv6: addr6.String(),
 			MacAddress:  iface.MacAddress().String(),
 		}
 	}
-	create := &createEndpointRequest{
+	create := &api.CreateEndpointRequest{
 		NetworkID:  string(nid),
 		EndpointID: string(eid),
 		Interfaces: reqIfaces,
 		Options:    epOptions,
 	}
-	var res createEndpointResponse
+	var res api.CreateEndpointResponse
 	if err := d.call("CreateEndpoint", create, &res); err != nil {
 		return err
 	}
 
-	ifaces, err := res.parseInterfaces()
+	ifaces, err := parseInterfaces(res)
 	if err != nil {
 		return err
 	}
@@ -125,19 +130,19 @@ func errorWithRollback(msg string, err error) error {
 }
 
 func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
-	delete := &deleteEndpointRequest{
+	delete := &api.DeleteEndpointRequest{
 		NetworkID:  string(nid),
 		EndpointID: string(eid),
 	}
-	return d.call("DeleteEndpoint", delete, &deleteEndpointResponse{})
+	return d.call("DeleteEndpoint", delete, &api.DeleteEndpointResponse{})
 }
 
 func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
-	info := &endpointInfoRequest{
+	info := &api.EndpointInfoRequest{
 		NetworkID:  string(nid),
 		EndpointID: string(eid),
 	}
-	var res endpointInfoResponse
+	var res api.EndpointInfoResponse
 	if err := d.call("EndpointOperInfo", info, &res); err != nil {
 		return nil, err
 	}
@@ -146,14 +151,14 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{},
 
 // Join method is invoked when a Sandbox is attached to an endpoint.
 func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
-	join := &joinRequest{
+	join := &api.JoinRequest{
 		NetworkID:  string(nid),
 		EndpointID: string(eid),
 		SandboxKey: sboxKey,
 		Options:    options,
 	}
 	var (
-		res joinResponse
+		res api.JoinResponse
 		err error
 	)
 	if err = d.call("Join", join, &res); err != nil {
@@ -194,7 +199,7 @@ func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinI
 		}
 	}
 	if len(res.StaticRoutes) > 0 {
-		routes, err := res.parseStaticRoutes()
+		routes, err := parseStaticRoutes(res)
 		if err != nil {
 			return err
 		}
@@ -215,13 +220,74 @@ func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinI
 
 // Leave method is invoked when a Sandbox detaches from an endpoint.
 func (d *driver) Leave(nid, eid types.UUID) error {
-	leave := &leaveRequest{
+	leave := &api.LeaveRequest{
 		NetworkID:  string(nid),
 		EndpointID: string(eid),
 	}
-	return d.call("Leave", leave, &leaveResponse{})
+	return d.call("Leave", leave, &api.LeaveResponse{})
 }
 
 func (d *driver) Type() string {
 	return d.networkType
 }
+
+func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) {
+	var routes = make([]*types.StaticRoute, len(r.StaticRoutes))
+	for i, inRoute := range r.StaticRoutes {
+		var err error
+		outRoute := &types.StaticRoute{InterfaceID: inRoute.InterfaceID, RouteType: inRoute.RouteType}
+
+		if inRoute.Destination != "" {
+			if outRoute.Destination, err = toAddr(inRoute.Destination); err != nil {
+				return nil, err
+			}
+		}
+
+		if inRoute.NextHop != "" {
+			outRoute.NextHop = net.ParseIP(inRoute.NextHop)
+			if outRoute.NextHop == nil {
+				return nil, fmt.Errorf("failed to parse nexthop IP %s", inRoute.NextHop)
+			}
+		}
+
+		routes[i] = outRoute
+	}
+	return routes, nil
+}
+
+// parseInterfaces validates all the parameters of an Interface and returns them.
+func parseInterfaces(r api.CreateEndpointResponse) ([]*api.Interface, error) {
+	var (
+		Interfaces = make([]*api.Interface, len(r.Interfaces))
+	)
+	for i, inIf := range r.Interfaces {
+		var err error
+		outIf := &api.Interface{ID: inIf.ID}
+		if inIf.Address != "" {
+			if outIf.Address, err = toAddr(inIf.Address); err != nil {
+				return nil, err
+			}
+		}
+		if inIf.AddressIPv6 != "" {
+			if outIf.AddressIPv6, err = toAddr(inIf.AddressIPv6); err != nil {
+				return nil, err
+			}
+		}
+		if inIf.MacAddress != "" {
+			if outIf.MacAddress, err = net.ParseMAC(inIf.MacAddress); err != nil {
+				return nil, err
+			}
+		}
+		Interfaces[i] = outIf
+	}
+	return Interfaces, nil
+}
+
+func toAddr(ipAddr string) (*net.IPNet, error) {
+	ip, ipnet, err := net.ParseCIDR(ipAddr)
+	if err != nil {
+		return nil, err
+	}
+	ipnet.IP = ip
+	return ipnet, nil
+}

+ 0 - 178
vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go

@@ -1,178 +0,0 @@
-package remote
-
-import (
-	"fmt"
-	"net"
-
-	"github.com/docker/libnetwork/types"
-)
-
-type response struct {
-	Err string
-}
-
-type maybeError interface {
-	getError() string
-}
-
-func (r *response) getError() string {
-	return r.Err
-}
-
-type createNetworkRequest struct {
-	NetworkID string
-	Options   map[string]interface{}
-}
-
-type createNetworkResponse struct {
-	response
-}
-
-type deleteNetworkRequest struct {
-	NetworkID string
-}
-
-type deleteNetworkResponse struct {
-	response
-}
-
-type createEndpointRequest struct {
-	NetworkID  string
-	EndpointID string
-	Interfaces []*endpointInterface
-	Options    map[string]interface{}
-}
-
-type endpointInterface struct {
-	ID          int
-	Address     string
-	AddressIPv6 string
-	MacAddress  string
-}
-
-type staticRoute struct {
-	Destination string
-	RouteType   int
-	NextHop     string
-	InterfaceID int
-}
-
-type createEndpointResponse struct {
-	response
-	Interfaces []*endpointInterface
-}
-
-func toAddr(ipAddr string) (*net.IPNet, error) {
-	ip, ipnet, err := net.ParseCIDR(ipAddr)
-	if err != nil {
-		return nil, err
-	}
-	ipnet.IP = ip
-	return ipnet, nil
-}
-
-type iface struct {
-	ID          int
-	Address     *net.IPNet
-	AddressIPv6 *net.IPNet
-	MacAddress  net.HardwareAddr
-}
-
-func (r *createEndpointResponse) parseInterfaces() ([]*iface, error) {
-	var ifaces = make([]*iface, len(r.Interfaces))
-	for i, inIf := range r.Interfaces {
-		var err error
-		outIf := &iface{ID: inIf.ID}
-		if inIf.Address != "" {
-			if outIf.Address, err = toAddr(inIf.Address); err != nil {
-				return nil, err
-			}
-		}
-		if inIf.AddressIPv6 != "" {
-			if outIf.AddressIPv6, err = toAddr(inIf.AddressIPv6); err != nil {
-				return nil, err
-			}
-		}
-		if inIf.MacAddress != "" {
-			if outIf.MacAddress, err = net.ParseMAC(inIf.MacAddress); err != nil {
-				return nil, err
-			}
-		}
-		ifaces[i] = outIf
-	}
-	return ifaces, nil
-}
-
-func (r *joinResponse) parseStaticRoutes() ([]*types.StaticRoute, error) {
-	var routes = make([]*types.StaticRoute, len(r.StaticRoutes))
-	for i, inRoute := range r.StaticRoutes {
-		var err error
-		outRoute := &types.StaticRoute{InterfaceID: inRoute.InterfaceID, RouteType: inRoute.RouteType}
-
-		if inRoute.Destination != "" {
-			if outRoute.Destination, err = toAddr(inRoute.Destination); err != nil {
-				return nil, err
-			}
-		}
-
-		if inRoute.NextHop != "" {
-			outRoute.NextHop = net.ParseIP(inRoute.NextHop)
-			if outRoute.NextHop == nil {
-				return nil, fmt.Errorf("failed to parse nexthop IP %s", inRoute.NextHop)
-			}
-		}
-
-		routes[i] = outRoute
-	}
-	return routes, nil
-}
-
-type deleteEndpointRequest struct {
-	NetworkID  string
-	EndpointID string
-}
-
-type deleteEndpointResponse struct {
-	response
-}
-
-type endpointInfoRequest struct {
-	NetworkID  string
-	EndpointID string
-}
-
-type endpointInfoResponse struct {
-	response
-	Value map[string]interface{}
-}
-
-type joinRequest struct {
-	NetworkID  string
-	EndpointID string
-	SandboxKey string
-	Options    map[string]interface{}
-}
-
-type ifaceName struct {
-	SrcName   string
-	DstPrefix string
-}
-
-type joinResponse struct {
-	response
-	InterfaceNames []*ifaceName
-	Gateway        string
-	GatewayIPv6    string
-	StaticRoutes   []*staticRoute
-	HostsPath      string
-	ResolvConfPath string
-}
-
-type leaveRequest struct {
-	NetworkID  string
-	EndpointID string
-}
-
-type leaveResponse struct {
-	response
-}

+ 1 - 6
vendor/src/github.com/docker/libnetwork/endpoint.go

@@ -297,12 +297,7 @@ func (ep *endpoint) processOptions(options ...EndpointOption) {
 }
 
 func createBasePath(dir string) error {
-	err := os.MkdirAll(dir, 0644)
-	if err != nil && !os.IsExist(err) {
-		return err
-	}
-
-	return nil
+	return os.MkdirAll(dir, 0644)
 }
 
 func createFile(path string) error {

+ 34 - 25
vendor/src/github.com/docker/libnetwork/iptables/iptables.go

@@ -42,10 +42,9 @@ var (
 	ErrIptablesNotFound = errors.New("Iptables not found")
 )
 
-// Chain defines the iptables chain.
-type Chain struct {
+// ChainInfo defines the iptables chain.
+type ChainInfo struct {
 	Name        string
-	Bridge      string
 	Table       Table
 	HairpinMode bool
 }
@@ -74,14 +73,12 @@ func initCheck() error {
 }
 
 // NewChain adds a new chain to ip table.
-func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error) {
-	c := &Chain{
+func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
+	c := &ChainInfo{
 		Name:        name,
-		Bridge:      bridge,
 		Table:       table,
 		HairpinMode: hairpinMode,
 	}
-
 	if string(c.Table) == "" {
 		c.Table = Filter
 	}
@@ -94,8 +91,16 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
 			return nil, fmt.Errorf("Could not create %s/%s chain: %s", c.Table, c.Name, output)
 		}
 	}
+	return c, nil
+}
+
+// ProgramChain is used to add rules to a chain
+func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
+	if c.Name == "" {
+		return fmt.Errorf("Could not program chain, missing chain name.")
+	}
 
-	switch table {
+	switch c.Table {
 	case Nat:
 		preroute := []string{
 			"-m", "addrtype",
@@ -103,7 +108,7 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
 			"-j", c.Name}
 		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)
+				return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
 			}
 		}
 		output := []string{
@@ -115,28 +120,32 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
 		}
 		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)
+				return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
 			}
 		}
 	case Filter:
+		if bridgeName == "" {
+			return fmt.Errorf("Could not program chain %s/%s, missing bridge name.",
+				c.Table, c.Name)
+		}
 		link := []string{
-			"-o", c.Bridge,
+			"-o", bridgeName,
 			"-j", c.Name}
 		if !Exists(Filter, "FORWARD", link...) {
 			insert := append([]string{string(Insert), "FORWARD"}, link...)
 			if output, err := Raw(insert...); err != nil {
-				return nil, err
+				return err
 			} else if len(output) != 0 {
-				return nil, fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
+				return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
 			}
 		}
 	}
-	return c, nil
+	return nil
 }
 
 // RemoveExistingChain removes existing chain from the table.
 func RemoveExistingChain(name string, table Table) error {
-	c := &Chain{
+	c := &ChainInfo{
 		Name:  name,
 		Table: table,
 	}
@@ -147,7 +156,7 @@ func RemoveExistingChain(name string, table Table) error {
 }
 
 // Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
-func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int) error {
+func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
 	daddr := ip.String()
 	if ip.IsUnspecified() {
 		// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we
@@ -162,7 +171,7 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
 		"-j", "DNAT",
 		"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
 	if !c.HairpinMode {
-		args = append(args, "!", "-i", c.Bridge)
+		args = append(args, "!", "-i", bridgeName)
 	}
 	if output, err := Raw(args...); err != nil {
 		return err
@@ -171,8 +180,8 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
 	}
 
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
-		"!", "-i", c.Bridge,
-		"-o", c.Bridge,
+		"!", "-i", bridgeName,
+		"-o", bridgeName,
 		"-p", proto,
 		"-d", destAddr,
 		"--dport", strconv.Itoa(destPort),
@@ -198,9 +207,9 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
 
 // Link adds reciprocal ACCEPT rule for two supplied IP addresses.
 // Traffic is allowed from ip1 to ip2 and vice-versa
-func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) error {
+func (c *ChainInfo) Link(action Action, ip1, ip2 net.IP, port int, proto string, bridgeName string) error {
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
-		"-i", c.Bridge, "-o", c.Bridge,
+		"-i", bridgeName, "-o", bridgeName,
 		"-p", proto,
 		"-s", ip1.String(),
 		"-d", ip2.String(),
@@ -211,7 +220,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
 		return fmt.Errorf("Error iptables forward: %s", output)
 	}
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
-		"-i", c.Bridge, "-o", c.Bridge,
+		"-i", bridgeName, "-o", bridgeName,
 		"-p", proto,
 		"-s", ip2.String(),
 		"-d", ip1.String(),
@@ -225,7 +234,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
 }
 
 // Prerouting adds linking rule to nat/PREROUTING chain.
-func (c *Chain) Prerouting(action Action, args ...string) error {
+func (c *ChainInfo) Prerouting(action Action, args ...string) error {
 	a := []string{"-t", string(Nat), string(action), "PREROUTING"}
 	if len(args) > 0 {
 		a = append(a, args...)
@@ -239,7 +248,7 @@ func (c *Chain) Prerouting(action Action, args ...string) error {
 }
 
 // Output adds linking rule to an OUTPUT chain.
-func (c *Chain) Output(action Action, args ...string) error {
+func (c *ChainInfo) Output(action Action, args ...string) error {
 	a := []string{"-t", string(c.Table), string(action), "OUTPUT"}
 	if len(args) > 0 {
 		a = append(a, args...)
@@ -253,7 +262,7 @@ func (c *Chain) Output(action Action, args ...string) error {
 }
 
 // Remove removes the chain.
-func (c *Chain) Remove() error {
+func (c *ChainInfo) Remove() error {
 	// Ignore errors - This could mean the chains were never set up
 	if c.Table == Nat {
 		c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name)

+ 17 - 7
vendor/src/github.com/docker/libnetwork/netutils/utils.go

@@ -122,26 +122,36 @@ func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
 	return addrs4[0], addrs6, nil
 }
 
-// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
-func GenerateRandomMAC() net.HardwareAddr {
+func genMAC(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
-	// Randomly generate the remaining 4 bytes (2^32)
-	_, err := rand.Read(hw[2:])
-	if err != nil {
-		return nil
+	// Fill the remaining 4 bytes based on the input
+	if ip == nil {
+		rand.Read(hw[2:])
+	} else {
+		copy(hw[2:], ip.To4())
 	}
 	return hw
 }
 
+// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
+func GenerateRandomMAC() net.HardwareAddr {
+	return genMAC(nil)
+}
+
+// GenerateMACFromIP returns a locally administered MAC address where the 4 least
+// significant bytes are derived from the IPv4 address.
+func GenerateMACFromIP(ip net.IP) net.HardwareAddr {
+	return genMAC(ip)
+}
+
 // GenerateRandomName returns a new name joined with a prefix.  This size
 // specified is used to truncate the randomly generated value
 func GenerateRandomName(prefix string, size int) (string, error) {

+ 79 - 21
vendor/src/github.com/docker/libnetwork/portallocator/portallocator.go

@@ -70,10 +70,15 @@ type (
 		Begin int
 		End   int
 	}
+	portRange struct {
+		begin int
+		end   int
+		last  int
+	}
 	portMap struct {
-		p          map[int]struct{}
-		begin, end int
-		last       int
+		p            map[int]struct{}
+		defaultRange string
+		portRanges   map[string]*portRange
 	}
 	protoMap map[string]*portMap
 )
@@ -123,8 +128,17 @@ func getDynamicPortRange() (start int, end int, err error) {
 
 // RequestPort requests new port from global ports pool for specified ip and proto.
 // If port is 0 it returns first free port. Otherwise it checks port availability
-// in pool and return that port or error if port is already busy.
+// in proto's pool and returns that port or error if port is already busy.
 func (p *PortAllocator) RequestPort(ip net.IP, proto string, port int) (int, error) {
+	return p.RequestPortInRange(ip, proto, port, port)
+}
+
+// RequestPortInRange requests new port from global ports pool for specified ip and proto.
+// If portStart and portEnd are 0 it returns the first free port in the default ephemeral range.
+// If portStart != portEnd it returns the first free port in the requested range.
+// Otherwise (portStart == portEnd) it checks port availability in the requested proto's port-pool
+// and returns that port or error if port is already busy.
+func (p *PortAllocator) RequestPortInRange(ip net.IP, proto string, portStart, portEnd int) (int, error) {
 	p.mutex.Lock()
 	defer p.mutex.Unlock()
 
@@ -146,15 +160,15 @@ func (p *PortAllocator) RequestPort(ip net.IP, proto string, port int) (int, err
 		p.ipMap[ipstr] = protomap
 	}
 	mapping := protomap[proto]
-	if port > 0 {
-		if _, ok := mapping.p[port]; !ok {
-			mapping.p[port] = struct{}{}
-			return port, nil
+	if portStart > 0 && portStart == portEnd {
+		if _, ok := mapping.p[portStart]; !ok {
+			mapping.p[portStart] = struct{}{}
+			return portStart, nil
 		}
-		return 0, newErrPortAlreadyAllocated(ipstr, port)
+		return 0, newErrPortAlreadyAllocated(ipstr, portStart)
 	}
 
-	port, err := mapping.findPort()
+	port, err := mapping.findPort(portStart, portEnd)
 	if err != nil {
 		return 0, err
 	}
@@ -178,12 +192,15 @@ func (p *PortAllocator) ReleasePort(ip net.IP, proto string, port int) error {
 }
 
 func (p *PortAllocator) newPortMap() *portMap {
-	return &portMap{
-		p:     map[int]struct{}{},
-		begin: p.Begin,
-		end:   p.End,
-		last:  p.End,
+	defaultKey := getRangeKey(p.Begin, p.End)
+	pm := &portMap{
+		p:            map[int]struct{}{},
+		defaultRange: defaultKey,
+		portRanges: map[string]*portRange{
+			defaultKey: newPortRange(p.Begin, p.End),
+		},
 	}
+	return pm
 }
 
 // ReleaseAll releases all ports for all ips.
@@ -194,17 +211,58 @@ func (p *PortAllocator) ReleaseAll() error {
 	return nil
 }
 
-func (pm *portMap) findPort() (int, error) {
-	port := pm.last
-	for i := 0; i <= pm.end-pm.begin; i++ {
+func getRangeKey(portStart, portEnd int) string {
+	return fmt.Sprintf("%d-%d", portStart, portEnd)
+}
+
+func newPortRange(portStart, portEnd int) *portRange {
+	return &portRange{
+		begin: portStart,
+		end:   portEnd,
+		last:  portEnd,
+	}
+}
+
+func (pm *portMap) getPortRange(portStart, portEnd int) (*portRange, error) {
+	var key string
+	if portStart == 0 && portEnd == 0 {
+		key = pm.defaultRange
+	} else {
+		key = getRangeKey(portStart, portEnd)
+		if portStart == portEnd ||
+			portStart == 0 || portEnd == 0 ||
+			portEnd < portStart {
+			return nil, fmt.Errorf("invalid port range: %s", key)
+		}
+	}
+
+	// Return existing port range, if already known.
+	if pr, exists := pm.portRanges[key]; exists {
+		return pr, nil
+	}
+
+	// Otherwise create a new port range.
+	pr := newPortRange(portStart, portEnd)
+	pm.portRanges[key] = pr
+	return pr, nil
+}
+
+func (pm *portMap) findPort(portStart, portEnd int) (int, error) {
+	pr, err := pm.getPortRange(portStart, portEnd)
+	if err != nil {
+		return 0, err
+	}
+	port := pr.last
+
+	for i := 0; i <= pr.end-pr.begin; i++ {
 		port++
-		if port > pm.end {
-			port = pm.begin
+		if port > pr.end {
+			port = pr.begin
 		}
 
 		if _, ok := pm.p[port]; !ok {
 			pm.p[port] = struct{}{}
-			pm.last = port
+			pr.last = port
 			return port, nil
 		}
 	}

+ 12 - 5
vendor/src/github.com/docker/libnetwork/portmapper/mapper.go

@@ -31,7 +31,8 @@ var (
 
 // PortMapper manages the network address translation
 type PortMapper struct {
-	chain *iptables.Chain
+	chain      *iptables.ChainInfo
+	bridgeName string
 
 	// udp:ip:port
 	currentMappings map[string]*mapping
@@ -54,12 +55,18 @@ func NewWithPortAllocator(allocator *portallocator.PortAllocator) *PortMapper {
 }
 
 // SetIptablesChain sets the specified chain into portmapper
-func (pm *PortMapper) SetIptablesChain(c *iptables.Chain) {
+func (pm *PortMapper) SetIptablesChain(c *iptables.ChainInfo, bridgeName string) {
 	pm.chain = c
+	pm.bridgeName = bridgeName
 }
 
 // Map maps the specified container transport address to the host's network address and transport port
 func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, useProxy bool) (host net.Addr, err error) {
+	return pm.MapRange(container, hostIP, hostPort, hostPort, useProxy)
+}
+
+// MapRange maps the specified container transport address to the host's network address and transport port range
+func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, hostPortEnd int, useProxy bool) (host net.Addr, err error) {
 	pm.lock.Lock()
 	defer pm.lock.Unlock()
 
@@ -72,7 +79,7 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
 	switch container.(type) {
 	case *net.TCPAddr:
 		proto = "tcp"
-		if allocatedHostPort, err = pm.Allocator.RequestPort(hostIP, proto, hostPort); err != nil {
+		if allocatedHostPort, err = pm.Allocator.RequestPortInRange(hostIP, proto, hostPortStart, hostPortEnd); err != nil {
 			return nil, err
 		}
 
@@ -89,7 +96,7 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
 		}
 	case *net.UDPAddr:
 		proto = "udp"
-		if allocatedHostPort, err = pm.Allocator.RequestPort(hostIP, proto, hostPort); err != nil {
+		if allocatedHostPort, err = pm.Allocator.RequestPortInRange(hostIP, proto, hostPortStart, hostPortEnd); err != nil {
 			return nil, err
 		}
 
@@ -215,5 +222,5 @@ func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net
 	if pm.chain == nil {
 		return nil
 	}
-	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
+	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName)
 }

+ 1 - 1
vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go

@@ -48,7 +48,7 @@ func init() {
 
 func createBasePath() {
 	err := os.MkdirAll(prefix, 0644)
-	if err != nil && !os.IsExist(err) {
+	if err != nil {
 		panic("Could not create net namespace path directory")
 	}
 

+ 14 - 11
vendor/src/github.com/docker/libnetwork/types/types.go

@@ -24,11 +24,12 @@ func (t *TransportPort) GetCopy() TransportPort {
 
 // PortBinding represent a port binding between the container and the host
 type PortBinding struct {
-	Proto    Protocol
-	IP       net.IP
-	Port     uint16
-	HostIP   net.IP
-	HostPort uint16
+	Proto       Protocol
+	IP          net.IP
+	Port        uint16
+	HostIP      net.IP
+	HostPort    uint16
+	HostPortEnd uint16
 }
 
 // HostAddr returns the host side transport address
@@ -58,11 +59,12 @@ func (p PortBinding) ContainerAddr() (net.Addr, error) {
 // GetCopy returns a copy of this PortBinding structure instance
 func (p *PortBinding) GetCopy() PortBinding {
 	return PortBinding{
-		Proto:    p.Proto,
-		IP:       GetIPCopy(p.IP),
-		Port:     p.Port,
-		HostIP:   GetIPCopy(p.HostIP),
-		HostPort: p.HostPort,
+		Proto:       p.Proto,
+		IP:          GetIPCopy(p.IP),
+		Port:        p.Port,
+		HostIP:      GetIPCopy(p.HostIP),
+		HostPort:    p.HostPort,
+		HostPortEnd: p.HostPortEnd,
 	}
 }
 
@@ -76,7 +78,8 @@ func (p *PortBinding) Equal(o *PortBinding) bool {
 		return false
 	}
 
-	if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
+	if p.Proto != o.Proto || p.Port != o.Port ||
+		p.HostPort != o.HostPort || p.HostPortEnd != o.HostPortEnd {
 		return false
 	}
 

+ 2 - 1
vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -39,8 +39,9 @@ func NativeEndian() binary.ByteOrder {
 		var x uint32 = 0x01020304
 		if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
 			nativeEndian = binary.BigEndian
+		} else {
+			nativeEndian = binary.LittleEndian
 		}
-		nativeEndian = binary.LittleEndian
 	}
 	return nativeEndian
 }

+ 9 - 0
vendor/src/github.com/vishvananda/netlink/nl/route_linux.go

@@ -20,6 +20,15 @@ func NewRtMsg() *RtMsg {
 	}
 }
 
+func NewRtDelMsg() *RtMsg {
+	return &RtMsg{
+		RtMsg: syscall.RtMsg{
+			Table: syscall.RT_TABLE_MAIN,
+			Scope: syscall.RT_SCOPE_NOWHERE,
+		},
+	}
+}
+
 func (msg *RtMsg) Len() int {
 	return syscall.SizeofRtMsg
 }

+ 3 - 4
vendor/src/github.com/vishvananda/netlink/route_linux.go

@@ -14,22 +14,21 @@ import (
 // Equivalent to: `ip route add $route`
 func RouteAdd(route *Route) error {
 	req := nl.NewNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-	return routeHandle(route, req)
+	return routeHandle(route, req, nl.NewRtMsg())
 }
 
 // RouteAdd will delete a route from the system.
 // Equivalent to: `ip route del $route`
 func RouteDel(route *Route) error {
 	req := nl.NewNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
-	return routeHandle(route, req)
+	return routeHandle(route, req, nl.NewRtDelMsg())
 }
 
-func routeHandle(route *Route, req *nl.NetlinkRequest) error {
+func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
 	if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil {
 		return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
 	}
 
-	msg := nl.NewRtMsg()
 	msg.Scope = uint8(route.Scope)
 	family := -1
 	var rtAttrs []*nl.RtAttr