mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #239 from aboch/pmc
One port mapper per bridge network
This commit is contained in:
commit
cad0f33910
6 changed files with 34 additions and 28 deletions
|
@ -31,7 +31,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.
|
||||||
|
@ -84,6 +83,7 @@ type bridgeNetwork struct {
|
||||||
bridge *bridgeInterface // The bridge's L3 interface
|
bridge *bridgeInterface // The bridge's L3 interface
|
||||||
config *networkConfiguration
|
config *networkConfiguration
|
||||||
endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
|
endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
|
||||||
|
portMapper *portmapper.PortMapper
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,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
|
||||||
|
@ -459,7 +458,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()
|
||||||
|
|
||||||
|
@ -553,7 +557,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},
|
||||||
|
@ -808,7 +812,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
|
||||||
}
|
}
|
||||||
|
@ -867,7 +871,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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
||||||
return releasePortsInternal(ep.portMapping)
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue