diff --git a/libnetwork/drivers/bridge/port_mapping.go b/libnetwork/drivers/bridge/port_mapping.go index 5e4fb42846..d1bb610f77 100644 --- a/libnetwork/drivers/bridge/port_mapping.go +++ b/libnetwork/drivers/bridge/port_mapping.go @@ -26,23 +26,28 @@ func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, u defHostIP = reqDefBindIP } - var pb []types.PortBinding - - if ep.addrv6 != nil { - pb, _ = n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addrv6.IP, defaultBindingIPV6, ulPxyEnabled, nil) + // IPv4 port binding including user land proxy + pb, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled) + if err != nil { + return nil, err } - return n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled, pb) + // IPv6 port binding excluding user land proxy + if n.driver.config.EnableIP6Tables && ep.addrv6 != nil { + pbv6, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addrv6.IP, defaultBindingIPV6, false) + if err != nil { + // ensure we clear the previous allocated IPv4 ports + n.releasePortsInternal(pb) + return nil, err + } + + pb = append(pb, pbv6...) + } + return pb, nil } -func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool, existingPortBindings []types.PortBinding) ([]types.PortBinding, error) { - - bs := existingPortBindings - - if existingPortBindings == nil { - bs = make([]types.PortBinding, 0, len(bindings)) - } - +func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) { + bs := make([]types.PortBinding, 0, len(bindings)) for _, c := range bindings { b := c.GetCopy() if err := n.allocatePort(&b, containerIP, defHostIP, ulPxyEnabled); err != nil { diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index 3e1a2524ae..ace38e89a2 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -195,7 +195,7 @@ func TestBridge(t *testing.T) { if !ok { t.Fatalf("Unexpected format for port mapping in endpoint operational data") } - if len(pm) != 10 { + if len(pm) != 5 { t.Fatalf("Incomplete data for port mapping in endpoint operational data: %d", len(pm)) } } diff --git a/libnetwork/portmapper/mapper.go b/libnetwork/portmapper/mapper.go index abb7ea1700..f447f3f8a0 100644 --- a/libnetwork/portmapper/mapper.go +++ b/libnetwork/portmapper/mapper.go @@ -160,7 +160,7 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, cleanup := func() error { // need to undo the iptables rules before we return m.userlandProxy.Stop() - if hostIP.To4() != nil { + if hostIP.To4() != nil || hostIP.To16() != nil { pm.DeleteForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort) if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil { return err @@ -170,13 +170,11 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, return nil } - if hostIP.To4() != nil { - if err := m.userlandProxy.Start(); err != nil { - if err := cleanup(); err != nil { - return nil, fmt.Errorf("Error during port allocation cleanup: %v", err) - } - return nil, err + if err := m.userlandProxy.Start(); err != nil { + if err := cleanup(); err != nil { + return nil, fmt.Errorf("Error during port allocation cleanup: %v", err) } + return nil, err } pm.currentMappings[key] = m