Skip to content

Commit

Permalink
One port mapper per bridge network
Browse files Browse the repository at this point in the history
Signed-off-by: Alessandro Boch <aboch@docker.com>
  • Loading branch information
aboch committed Jun 1, 2015
1 parent bcbc5f5 commit ba0a84f
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 28 deletions.
24 changes: 14 additions & 10 deletions drivers/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const (

var (
ipAllocator *ipallocator.IPAllocator
portMapper *portmapper.PortMapper
)

// configuration info for the "bridge" driver.
Expand Down Expand Up @@ -78,10 +77,11 @@ type bridgeEndpoint 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
}

Expand All @@ -94,7 +94,6 @@ type driver struct {

func init() {
ipAllocator = ipallocator.New()
portMapper = portmapper.New()
}

// New constructs a new bridge driver
Expand Down Expand Up @@ -451,7 +450,12 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
}

// 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.Unlock()

Expand Down Expand Up @@ -537,7 +541,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},

// Setup IPTables.
{config.EnableIPTables, setupIPTables},
{config.EnableIPTables, network.setupIPTables},

// Setup DefaultGatewayIPv4
{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
Expand Down Expand Up @@ -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
endpoint.portMapping, err = allocatePorts(epConfig, intf, config.DefaultBindingIP, config.EnableUserlandProxy)
endpoint.portMapping, err = n.allocatePorts(epConfig, intf, config.DefaultBindingIP, config.EnableUserlandProxy)
if err != nil {
return err
}
Expand Down Expand Up @@ -851,7 +855,7 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
}()

// 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
err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.intf.Address.IP)
Expand Down
2 changes: 1 addition & 1 deletion drivers/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
}

// Cleanup as host ports are there
err = releasePorts(ep)
err = network.releasePorts(ep)
if err != nil {
t.Fatalf("Failed to release mapped ports: %v", err)
}
Expand Down
26 changes: 13 additions & 13 deletions drivers/bridge/port_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var (
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 {
return nil, nil
}
Expand All @@ -25,16 +25,16 @@ func allocatePorts(epConfig *endpointConfiguration, intf *sandbox.Interface, req
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))
for _, c := range bindings {
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
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)
}
return nil, err
Expand All @@ -44,7 +44,7 @@ func allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP
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 (
host net.Addr
err error
Expand All @@ -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.
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
}
// There is no point in immediately retrying to map an explicitly chosen port.
Expand Down Expand Up @@ -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

// Attempt to release all port bindings, do not stop on failure
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))
}
}
Expand All @@ -114,11 +114,11 @@ func releasePortsInternal(bindings []types.PortBinding) error {
return nil
}

func releasePort(bnd types.PortBinding) error {
func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
// Construct the host side transport address
host, err := bnd.HostAddr()
if err != nil {
return err
}
return portMapper.Unmap(host)
return n.portMapper.Unmap(host)
}
2 changes: 1 addition & 1 deletion drivers/bridge/port_mapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestPortMappingConfig(t *testing.T) {
t.Fatalf("operational port mapping data not found on bridgeEndpoint")
}

err = releasePorts(ep)
err = network.releasePorts(ep)
if err != nil {
t.Fatalf("Failed to release mapped ports: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/bridge/setup_ip_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const (
DockerChain = "DOCKER"
)

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

portMapper.SetIptablesChain(chain)
n.portMapper.SetIptablesChain(chain)

return nil
}
Expand Down
4 changes: 3 additions & 1 deletion drivers/bridge/setup_ip_tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/docker/libnetwork/iptables"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/portmapper"
)

const (
Expand Down Expand Up @@ -95,8 +96,9 @@ func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {

// Assert function which pushes chains based on bridge config parameters.
func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
nw := bridgeNetwork{portMapper: portmapper.New()}
// Attempt programming of ip tables.
err := setupIPTables(config, br)
err := nw.setupIPTables(config, br)
if err != nil {
t.Fatalf("%v", err)
}
Expand Down

0 comments on commit ba0a84f

Please sign in to comment.