From 703e2264bae99784496794365ea72348715e7c70 Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Thu, 6 Aug 2015 04:53:44 -0700 Subject: [PATCH] Vendoring in libnetwork 22dc04d06067b40a9e7ef575aee6d1bb69d4dcc3 Notable changes include : - #285 : Fix required for https://github.com/docker/docker/pull/12927 - #283 : Code re-architecture/tech-debt in bridge driver - Upgraded to latest Netlink library - Fixed certain race-conditions Signed-off-by: Madhu Venugopal --- daemon/daemon_unix.go | 14 +- hack/vendor.sh | 4 +- .../github.com/docker/libnetwork/README.md | 2 +- .../github.com/docker/libnetwork/api/api.go | 57 +++--- .../libnetwork/drivers/bridge/bridge.go | 119 ++++++------ .../libnetwork/drivers/bridge/errors.go | 11 -- .../docker/libnetwork/drivers/bridge/link.go | 4 +- .../bridge/netlink_deprecated_linux.go | 14 +- .../libnetwork/drivers/bridge/port_mapping.go | 9 +- .../drivers/bridge/setup_firewalld.go | 7 +- .../drivers/bridge/setup_ip_forwarding.go | 18 +- .../drivers/bridge/setup_ip_tables.go | 61 +++++- .../libnetwork/drivers/bridge/setup_ipv4.go | 12 +- .../libnetwork/drivers/bridge/setup_ipv6.go | 45 ++++- .../libnetwork/drivers/overlay/ov_network.go | 36 +++- .../libnetwork/drivers/overlay/ov_utils.go | 3 +- .../libnetwork/drivers/remote/api/api.go | 144 ++++++++++++++ .../libnetwork/drivers/remote/driver.go | 104 ++++++++-- .../libnetwork/drivers/remote/messages.go | 178 ------------------ .../github.com/docker/libnetwork/endpoint.go | 7 +- .../docker/libnetwork/iptables/iptables.go | 59 +++--- .../docker/libnetwork/netutils/utils.go | 24 ++- .../libnetwork/portallocator/portallocator.go | 100 +++++++--- .../docker/libnetwork/portmapper/mapper.go | 17 +- .../libnetwork/sandbox/namespace_linux.go | 2 +- .../docker/libnetwork/types/types.go | 25 +-- .../vishvananda/netlink/nl/nl_linux.go | 3 +- .../vishvananda/netlink/nl/route_linux.go | 9 + .../vishvananda/netlink/route_linux.go | 7 +- 29 files changed, 656 insertions(+), 439 deletions(-) create mode 100644 vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go delete mode 100644 vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index ae36dd94a8..ead54dece0 100644 --- a/daemon/daemon_unix.go +++ b/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 != "" { diff --git a/hack/vendor.sh b/hack/vendor.sh index 15ae7ab20d..631b66f556 100755 --- a/hack/vendor.sh +++ b/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 diff --git a/vendor/src/github.com/docker/libnetwork/README.md b/vendor/src/github.com/docker/libnetwork/README.md index 90fcbe017f..d71c5b31e4 100644 --- a/vendor/src/github.com/docker/libnetwork/README.md +++ b/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) } diff --git a/vendor/src/github.com/docker/libnetwork/api/api.go b/vendor/src/github.com/docker/libnetwork/api/api.go index 2b5b577354..2bfc81b078 100644 --- a/vendor/src/github.com/docker/libnetwork/api/api.go +++ b/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 + "}" + 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 + "}" - // 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 + // 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) } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index 8fc05ae64f..a6a88b5cb8 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/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) } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go index d22912c5c7..dd17ddf902 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go +++ b/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 diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/link.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/link.go index 894c5e772c..25877737ba 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/link.go +++ b/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 } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go index 007ccb285a..6b49efa166 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go +++ b/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 } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/port_mapping.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/port_mapping.go index b102132190..4dab8a0c89 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/port_mapping.go +++ b/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) diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go index eeb7764801..fc45a7e983 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go +++ b/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) } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go index 2a8c73301a..53f9c88d4d 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go +++ b/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 diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go index fa241c1b34..f597f67b7f 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go +++ b/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 create NAT chain: %s", err.Error()) + return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error()) } - chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter, hairpinMode) + err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode) if err != nil { - return fmt.Errorf("Failed to create FILTER chain: %s", err.Error()) + return fmt.Errorf("Failed to program NAT chain: %s", err.Error()) } - n.portMapper.SetIptablesChain(chain) + err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode) + if err != nil { + return fmt.Errorf("Failed to program FILTER chain: %s", err.Error()) + } + + n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName()) return nil } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go index 91a9a6bcf1..c72e71e9a6 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go +++ b/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 } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go index b534644edf..da3c9db9c3 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go +++ b/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 } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go index be33e49b7c..21009e1685 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go +++ b/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) } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go index 46f7ea110a..384ec468e1 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_utils.go +++ b/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, diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go new file mode 100644 index 0000000000..ec703235c6 --- /dev/null +++ b/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 +} diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go index 1395933a17..8cfbe51aa2 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go +++ b/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 +} diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go deleted file mode 100644 index d9c9e1534e..0000000000 --- a/vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go +++ /dev/null @@ -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 -} diff --git a/vendor/src/github.com/docker/libnetwork/endpoint.go b/vendor/src/github.com/docker/libnetwork/endpoint.go index d38a4fd121..3475e9eafd 100644 --- a/vendor/src/github.com/docker/libnetwork/endpoint.go +++ b/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 { diff --git a/vendor/src/github.com/docker/libnetwork/iptables/iptables.go b/vendor/src/github.com/docker/libnetwork/iptables/iptables.go index 707ddb7e59..4e24c3ac52 100644 --- a/vendor/src/github.com/docker/libnetwork/iptables/iptables.go +++ b/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 +} - switch table { +// 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 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) diff --git a/vendor/src/github.com/docker/libnetwork/netutils/utils.go b/vendor/src/github.com/docker/libnetwork/netutils/utils.go index cb430eb03f..6ade406db4 100644 --- a/vendor/src/github.com/docker/libnetwork/netutils/utils.go +++ b/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) { diff --git a/vendor/src/github.com/docker/libnetwork/portallocator/portallocator.go b/vendor/src/github.com/docker/libnetwork/portallocator/portallocator.go index 37d9c769b4..240e94fc82 100644 --- a/vendor/src/github.com/docker/libnetwork/portallocator/portallocator.go +++ b/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 } } diff --git a/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go b/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go index b928e3c619..bbdedaa3ca 100644 --- a/vendor/src/github.com/docker/libnetwork/portmapper/mapper.go +++ b/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) } diff --git a/vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go b/vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go index 3ab011cd1c..214da312d0 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go +++ b/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") } diff --git a/vendor/src/github.com/docker/libnetwork/types/types.go b/vendor/src/github.com/docker/libnetwork/types/types.go index fa13bdeacc..3f394baa19 100644 --- a/vendor/src/github.com/docker/libnetwork/types/types.go +++ b/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 } diff --git a/vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go index a554adbf86..3cb137d01b 100644 --- a/vendor/src/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/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 } diff --git a/vendor/src/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/src/github.com/vishvananda/netlink/nl/route_linux.go index 5dde998e96..447e83e5ae 100644 --- a/vendor/src/github.com/vishvananda/netlink/nl/route_linux.go +++ b/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 } diff --git a/vendor/src/github.com/vishvananda/netlink/route_linux.go b/vendor/src/github.com/vishvananda/netlink/route_linux.go index 88fa6db0fc..38908951fe 100644 --- a/vendor/src/github.com/vishvananda/netlink/route_linux.go +++ b/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