Kaynağa Gözat

One port mapper per bridge network

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 10 yıl önce
ebeveyn
işleme
cfc28a900a

+ 14 - 10
libnetwork/drivers/bridge/bridge.go

@@ -29,7 +29,6 @@ const (
 
 
 var (
 var (
 	ipAllocator *ipallocator.IPAllocator
 	ipAllocator *ipallocator.IPAllocator
-	portMapper  *portmapper.PortMapper
 )
 )
 
 
 // configuration info for the "bridge" driver.
 // configuration info for the "bridge" driver.
@@ -78,10 +77,11 @@ type bridgeEndpoint struct {
 }
 }
 
 
 type bridgeNetwork struct {
 type bridgeNetwork struct {
-	id        types.UUID
-	bridge    *bridgeInterface // The bridge's L3 interface
-	config    *networkConfiguration
-	endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
+	id         types.UUID
+	bridge     *bridgeInterface // The bridge's L3 interface
+	config     *networkConfiguration
+	endpoints  map[types.UUID]*bridgeEndpoint // key: endpoint id
+	portMapper *portmapper.PortMapper
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
@@ -94,7 +94,6 @@ type driver struct {
 
 
 func init() {
 func init() {
 	ipAllocator = ipallocator.New()
 	ipAllocator = ipallocator.New()
-	portMapper = portmapper.New()
 }
 }
 
 
 // New constructs a new bridge driver
 // New constructs a new bridge driver
@@ -451,7 +450,12 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 	}
 	}
 
 
 	// Create and set network handler in driver
 	// Create and set network handler in driver
-	network := &bridgeNetwork{id: id, endpoints: make(map[types.UUID]*bridgeEndpoint), config: config}
+	network := &bridgeNetwork{
+		id:         id,
+		endpoints:  make(map[types.UUID]*bridgeEndpoint),
+		config:     config,
+		portMapper: portmapper.New(),
+	}
 	d.networks[id] = network
 	d.networks[id] = network
 	d.Unlock()
 	d.Unlock()
 
 
@@ -537,7 +541,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
 		{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},
 		{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},
 
 
 		// Setup IPTables.
 		// Setup IPTables.
-		{config.EnableIPTables, setupIPTables},
+		{config.EnableIPTables, network.setupIPTables},
 
 
 		// Setup DefaultGatewayIPv4
 		// Setup DefaultGatewayIPv4
 		{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
 		{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
@@ -792,7 +796,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 	}
 
 
 	// Program any required port mapping and store them in the endpoint
 	// Program any required port mapping and store them in the endpoint
-	endpoint.portMapping, err = allocatePorts(epConfig, intf, config.DefaultBindingIP, config.EnableUserlandProxy)
+	endpoint.portMapping, err = n.allocatePorts(epConfig, intf, config.DefaultBindingIP, config.EnableUserlandProxy)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -851,7 +855,7 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
 	}()
 	}()
 
 
 	// Remove port mappings. Do not stop endpoint delete on unmap failure
 	// Remove port mappings. Do not stop endpoint delete on unmap failure
-	releasePorts(ep)
+	n.releasePorts(ep)
 
 
 	// Release the v4 address allocated to this endpoint's sandbox interface
 	// Release the v4 address allocated to this endpoint's sandbox interface
 	err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.intf.Address.IP)
 	err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.intf.Address.IP)

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

@@ -227,7 +227,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
 	}
 	}
 
 
 	// Cleanup as host ports are there
 	// Cleanup as host ports are there
-	err = releasePorts(ep)
+	err = network.releasePorts(ep)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to release mapped ports: %v", err)
 		t.Fatalf("Failed to release mapped ports: %v", err)
 	}
 	}

+ 13 - 13
libnetwork/drivers/bridge/port_mapping.go

@@ -15,7 +15,7 @@ var (
 	defaultBindingIP = net.IPv4(0, 0, 0, 0)
 	defaultBindingIP = net.IPv4(0, 0, 0, 0)
 )
 )
 
 
-func allocatePorts(epConfig *endpointConfiguration, intf *sandbox.Interface, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
+func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, intf *sandbox.Interface, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
 	if epConfig == nil || epConfig.PortBindings == nil {
 	if epConfig == nil || epConfig.PortBindings == nil {
 		return nil, nil
 		return nil, nil
 	}
 	}
@@ -25,16 +25,16 @@ func allocatePorts(epConfig *endpointConfiguration, intf *sandbox.Interface, req
 		defHostIP = reqDefBindIP
 		defHostIP = reqDefBindIP
 	}
 	}
 
 
-	return allocatePortsInternal(epConfig.PortBindings, intf.Address.IP, defHostIP, ulPxyEnabled)
+	return n.allocatePortsInternal(epConfig.PortBindings, intf.Address.IP, defHostIP, ulPxyEnabled)
 }
 }
 
 
-func allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
+func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
 	bs := make([]types.PortBinding, 0, len(bindings))
 	bs := make([]types.PortBinding, 0, len(bindings))
 	for _, c := range bindings {
 	for _, c := range bindings {
 		b := c.GetCopy()
 		b := c.GetCopy()
-		if err := allocatePort(&b, containerIP, defHostIP, ulPxyEnabled); err != nil {
+		if err := n.allocatePort(&b, containerIP, defHostIP, ulPxyEnabled); err != nil {
 			// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
 			// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
-			if cuErr := releasePortsInternal(bs); cuErr != nil {
+			if cuErr := n.releasePortsInternal(bs); cuErr != nil {
 				logrus.Warnf("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v", b, cuErr)
 				logrus.Warnf("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v", b, cuErr)
 			}
 			}
 			return nil, err
 			return nil, err
@@ -44,7 +44,7 @@ func allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP
 	return bs, nil
 	return bs, nil
 }
 }
 
 
-func allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error {
+func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error {
 	var (
 	var (
 		host net.Addr
 		host net.Addr
 		err  error
 		err  error
@@ -66,7 +66,7 @@ func allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEn
 
 
 	// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
 	// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
 	for i := 0; i < maxAllocatePortAttempts; i++ {
 	for i := 0; i < maxAllocatePortAttempts; i++ {
-		if host, err = portMapper.Map(container, bnd.HostIP, int(bnd.HostPort), ulPxyEnabled); err == nil {
+		if host, err = n.portMapper.Map(container, bnd.HostIP, int(bnd.HostPort), ulPxyEnabled); err == nil {
 			break
 			break
 		}
 		}
 		// There is no point in immediately retrying to map an explicitly chosen port.
 		// There is no point in immediately retrying to map an explicitly chosen port.
@@ -94,16 +94,16 @@ func allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEn
 	}
 	}
 }
 }
 
 
-func releasePorts(ep *bridgeEndpoint) error {
-	return releasePortsInternal(ep.portMapping)
+func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
+	return n.releasePortsInternal(ep.portMapping)
 }
 }
 
 
-func releasePortsInternal(bindings []types.PortBinding) error {
+func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
 	var errorBuf bytes.Buffer
 	var errorBuf bytes.Buffer
 
 
 	// Attempt to release all port bindings, do not stop on failure
 	// Attempt to release all port bindings, do not stop on failure
 	for _, m := range bindings {
 	for _, m := range bindings {
-		if err := releasePort(m); err != nil {
+		if err := n.releasePort(m); err != nil {
 			errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
 			errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
 		}
 		}
 	}
 	}
@@ -114,11 +114,11 @@ func releasePortsInternal(bindings []types.PortBinding) error {
 	return nil
 	return nil
 }
 }
 
 
-func releasePort(bnd types.PortBinding) error {
+func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
 	// Construct the host side transport address
 	// Construct the host side transport address
 	host, err := bnd.HostAddr()
 	host, err := bnd.HostAddr()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	return portMapper.Unmap(host)
+	return n.portMapper.Unmap(host)
 }
 }

+ 1 - 1
libnetwork/drivers/bridge/port_mapping_test.go

@@ -64,7 +64,7 @@ func TestPortMappingConfig(t *testing.T) {
 		t.Fatalf("operational port mapping data not found on bridgeEndpoint")
 		t.Fatalf("operational port mapping data not found on bridgeEndpoint")
 	}
 	}
 
 
-	err = releasePorts(ep)
+	err = network.releasePorts(ep)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to release mapped ports: %v", err)
 		t.Fatalf("Failed to release mapped ports: %v", err)
 	}
 	}

+ 2 - 2
libnetwork/drivers/bridge/setup_ip_tables.go

@@ -13,7 +13,7 @@ const (
 	DockerChain = "DOCKER"
 	DockerChain = "DOCKER"
 )
 )
 
 
-func setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
+func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
 	// Sanity check.
 	// Sanity check.
 	if config.EnableIPTables == false {
 	if config.EnableIPTables == false {
 		return IPTableCfgError(config.BridgeName)
 		return IPTableCfgError(config.BridgeName)
@@ -39,7 +39,7 @@ func setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
 		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
 		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
 	}
 	}
 
 
-	portMapper.SetIptablesChain(chain)
+	n.portMapper.SetIptablesChain(chain)
 
 
 	return nil
 	return nil
 }
 }

+ 3 - 1
libnetwork/drivers/bridge/setup_ip_tables_test.go

@@ -6,6 +6,7 @@ import (
 
 
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/netutils"
+	"github.com/docker/libnetwork/portmapper"
 )
 )
 
 
 const (
 const (
@@ -95,8 +96,9 @@ func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
 
 
 // Assert function which pushes chains based on bridge config parameters.
 // Assert function which pushes chains based on bridge config parameters.
 func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
 func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
+	nw := bridgeNetwork{portMapper: portmapper.New()}
 	// Attempt programming of ip tables.
 	// Attempt programming of ip tables.
-	err := setupIPTables(config, br)
+	err := nw.setupIPTables(config, br)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("%v", err)
 		t.Fatalf("%v", err)
 	}
 	}