Selaa lähdekoodia

Remove jobs from daemon/networkdriver/bridge

Signed-off-by: Tibor Vass <tibor@docker.com>
Tibor Vass 10 vuotta sitten
vanhempi
commit
53582321ee

+ 9 - 8
api/client/port.go

@@ -1,10 +1,10 @@
 package client
 package client
 
 
 import (
 import (
+	"encoding/json"
 	"fmt"
 	"fmt"
 	"strings"
 	"strings"
 
 
-	"github.com/docker/docker/engine"
 	"github.com/docker/docker/nat"
 	"github.com/docker/docker/nat"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 )
 )
@@ -23,12 +23,13 @@ func (cli *DockerCli) CmdPort(args ...string) error {
 		return err
 		return err
 	}
 	}
 
 
-	env := engine.Env{}
-	if err := env.Decode(stream); err != nil {
-		return err
+	var c struct {
+		NetworkSettings struct {
+			Ports nat.PortMap
+		}
 	}
 	}
-	ports := nat.PortMap{}
-	if err := env.GetSubEnv("NetworkSettings").GetJson("Ports", &ports); err != nil {
+
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -44,7 +45,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
 			proto = parts[1]
 			proto = parts[1]
 		}
 		}
 		natPort := port + "/" + proto
 		natPort := port + "/" + proto
-		if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
+		if frontends, exists := c.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
 			for _, frontend := range frontends {
 			for _, frontend := range frontends {
 				fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
 				fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
 			}
 			}
@@ -53,7 +54,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
 		return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
 		return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
 	}
 	}
 
 
-	for from, frontends := range ports {
+	for from, frontends := range c.NetworkSettings.Ports {
 		for _, frontend := range frontends {
 		for _, frontend := range frontends {
 			fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
 			fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
 		}
 		}

+ 0 - 23
builtins/builtins.go

@@ -6,15 +6,11 @@ import (
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api"
 	apiserver "github.com/docker/docker/api/server"
 	apiserver "github.com/docker/docker/api/server"
 	"github.com/docker/docker/autogen/dockerversion"
 	"github.com/docker/docker/autogen/dockerversion"
-	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/kernel"
 )
 )
 
 
 func Register(eng *engine.Engine) error {
 func Register(eng *engine.Engine) error {
-	if err := daemon(eng); err != nil {
-		return err
-	}
 	if err := remote(eng); err != nil {
 	if err := remote(eng); err != nil {
 		return err
 		return err
 	}
 	}
@@ -33,25 +29,6 @@ func remote(eng *engine.Engine) error {
 	return eng.Register("acceptconnections", apiserver.AcceptConnections)
 	return eng.Register("acceptconnections", apiserver.AcceptConnections)
 }
 }
 
 
-// daemon: a default execution and storage backend for Docker on Linux,
-// with the following underlying components:
-//
-// * Pluggable storage drivers including aufs, vfs, lvm and btrfs.
-// * Pluggable execution drivers including lxc and chroot.
-//
-// In practice `daemon` still includes most core Docker components, including:
-//
-// * The reference registry client implementation
-// * Image management
-// * The build facility
-// * Logging
-//
-// These components should be broken off into plugins of their own.
-//
-func daemon(eng *engine.Engine) error {
-	return eng.Register("init_networkdriver", bridge.InitDriver)
-}
-
 // builtins jobs independent of any subsystem
 // builtins jobs independent of any subsystem
 func dockerVersion(job *engine.Job) error {
 func dockerVersion(job *engine.Job) error {
 	v := &engine.Env{}
 	v := &engine.Env{}

+ 32 - 41
daemon/config.go

@@ -1,9 +1,8 @@
 package daemon
 package daemon
 
 
 import (
 import (
-	"net"
-
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver"
+	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/ulimit"
 	"github.com/docker/docker/pkg/ulimit"
@@ -20,35 +19,27 @@ const (
 // to the docker daemon when you launch it with say: `docker -d -e lxc`
 // to the docker daemon when you launch it with say: `docker -d -e lxc`
 // FIXME: separate runtime configuration from http api configuration
 // FIXME: separate runtime configuration from http api configuration
 type Config struct {
 type Config struct {
-	Pidfile                     string
-	Root                        string
-	AutoRestart                 bool
-	Dns                         []string
-	DnsSearch                   []string
-	EnableIPv6                  bool
-	EnableIptables              bool
-	EnableIpForward             bool
-	EnableIpMasq                bool
-	DefaultIp                   net.IP
-	BridgeIface                 string
-	BridgeIP                    string
-	FixedCIDR                   string
-	FixedCIDRv6                 string
-	InterContainerCommunication bool
-	GraphDriver                 string
-	GraphOptions                []string
-	ExecDriver                  string
-	Mtu                         int
-	SocketGroup                 string
-	EnableCors                  bool
-	CorsHeaders                 string
-	DisableNetwork              bool
-	EnableSelinuxSupport        bool
-	Context                     map[string][]string
-	TrustKeyPath                string
-	Labels                      []string
-	Ulimits                     map[string]*ulimit.Ulimit
-	LogConfig                   runconfig.LogConfig
+	Bridge bridge.Config
+
+	Pidfile              string
+	Root                 string
+	AutoRestart          bool
+	Dns                  []string
+	DnsSearch            []string
+	GraphDriver          string
+	GraphOptions         []string
+	ExecDriver           string
+	Mtu                  int
+	SocketGroup          string
+	EnableCors           bool
+	CorsHeaders          string
+	DisableNetwork       bool
+	EnableSelinuxSupport bool
+	Context              map[string][]string
+	TrustKeyPath         string
+	Labels               []string
+	Ulimits              map[string]*ulimit.Ulimit
+	LogConfig            runconfig.LogConfig
 }
 }
 
 
 // InstallFlags adds command-line options to the top-level flag parser for
 // InstallFlags adds command-line options to the top-level flag parser for
@@ -59,15 +50,15 @@ func (config *Config) InstallFlags() {
 	flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
 	flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
 	flag.StringVar(&config.Root, []string{"g", "-graph"}, "/var/lib/docker", "Root of the Docker runtime")
 	flag.StringVar(&config.Root, []string{"g", "-graph"}, "/var/lib/docker", "Root of the Docker runtime")
 	flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
 	flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
-	flag.BoolVar(&config.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
-	flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
-	flag.BoolVar(&config.EnableIpMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
-	flag.BoolVar(&config.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
-	flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
-	flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
-	flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
-	flag.StringVar(&config.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
-	flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
+	flag.BoolVar(&config.Bridge.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
+	flag.BoolVar(&config.Bridge.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
+	flag.BoolVar(&config.Bridge.EnableIpMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
+	flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
+	flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
+	flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
+	flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
+	flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
+	flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
 	flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
 	flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
 	flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")
 	flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")
 	flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
 	flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
@@ -75,7 +66,7 @@ func (config *Config) InstallFlags() {
 	flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
 	flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
 	flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
 	flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
 	flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
 	flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
-	opts.IPVar(&config.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
+	opts.IPVar(&config.Bridge.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
 	opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
 	opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
 	// FIXME: why the inconsistency between "hosts" and "sockets"?
 	// FIXME: why the inconsistency between "hosts" and "sockets"?
 	opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
 	opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")

+ 17 - 48
daemon/container.go

@@ -24,6 +24,8 @@ import (
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/logger/jsonfilelog"
 	"github.com/docker/docker/daemon/logger/jsonfilelog"
 	"github.com/docker/docker/daemon/logger/syslog"
 	"github.com/docker/docker/daemon/logger/syslog"
+	"github.com/docker/docker/daemon/network"
+	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/links"
 	"github.com/docker/docker/links"
@@ -73,7 +75,7 @@ type Container struct {
 	Config  *runconfig.Config
 	Config  *runconfig.Config
 	ImageID string `json:"Image"`
 	ImageID string `json:"Image"`
 
 
-	NetworkSettings *NetworkSettings
+	NetworkSettings *network.Settings
 
 
 	ResolvConfPath string
 	ResolvConfPath string
 	HostnamePath   string
 	HostnamePath   string
@@ -571,17 +573,12 @@ func (container *Container) AllocateNetwork() error {
 	}
 	}
 
 
 	var (
 	var (
-		env *engine.Env
 		err error
 		err error
 		eng = container.daemon.eng
 		eng = container.daemon.eng
 	)
 	)
 
 
-	job := eng.Job("allocate_interface", container.ID)
-	job.Setenv("RequestedMac", container.Config.MacAddress)
-	if env, err = job.Stdout.AddEnv(); err != nil {
-		return err
-	}
-	if err = job.Run(); err != nil {
+	networkSettings, err := bridge.Allocate(container.ID, container.Config.MacAddress, "", "")
+	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -591,12 +588,12 @@ func (container *Container) AllocateNetwork() error {
 
 
 	if container.Config.PortSpecs != nil {
 	if container.Config.PortSpecs != nil {
 		if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
 		if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
-			eng.Job("release_interface", container.ID).Run()
+			bridge.Release(container.ID)
 			return err
 			return err
 		}
 		}
 		container.Config.PortSpecs = nil
 		container.Config.PortSpecs = nil
 		if err = container.WriteHostConfig(); err != nil {
 		if err = container.WriteHostConfig(); err != nil {
-			eng.Job("release_interface", container.ID).Run()
+			bridge.Release(container.ID)
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -626,23 +623,14 @@ func (container *Container) AllocateNetwork() error {
 
 
 	for port := range portSpecs {
 	for port := range portSpecs {
 		if err = container.allocatePort(eng, port, bindings); err != nil {
 		if err = container.allocatePort(eng, port, bindings); err != nil {
-			eng.Job("release_interface", container.ID).Run()
+			bridge.Release(container.ID)
 			return err
 			return err
 		}
 		}
 	}
 	}
 	container.WriteHostConfig()
 	container.WriteHostConfig()
 
 
-	container.NetworkSettings.Ports = bindings
-	container.NetworkSettings.Bridge = env.Get("Bridge")
-	container.NetworkSettings.IPAddress = env.Get("IP")
-	container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
-	container.NetworkSettings.MacAddress = env.Get("MacAddress")
-	container.NetworkSettings.Gateway = env.Get("Gateway")
-	container.NetworkSettings.LinkLocalIPv6Address = env.Get("LinkLocalIPv6")
-	container.NetworkSettings.LinkLocalIPv6PrefixLen = 64
-	container.NetworkSettings.GlobalIPv6Address = env.Get("GlobalIPv6")
-	container.NetworkSettings.GlobalIPv6PrefixLen = env.GetInt("GlobalIPv6PrefixLen")
-	container.NetworkSettings.IPv6Gateway = env.Get("IPv6Gateway")
+	networkSettings.Ports = bindings
+	container.NetworkSettings = networkSettings
 
 
 	return nil
 	return nil
 }
 }
@@ -651,12 +639,10 @@ func (container *Container) ReleaseNetwork() {
 	if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
 	if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
 		return
 		return
 	}
 	}
-	eng := container.daemon.eng
 
 
-	job := eng.Job("release_interface", container.ID)
-	job.SetenvBool("overrideShutdown", true)
-	job.Run()
-	container.NetworkSettings = &NetworkSettings{}
+	bridge.Release(container.ID)
+
+	container.NetworkSettings = &network.Settings{}
 }
 }
 
 
 func (container *Container) isNetworkAllocated() bool {
 func (container *Container) isNetworkAllocated() bool {
@@ -675,10 +661,7 @@ func (container *Container) RestoreNetwork() error {
 	eng := container.daemon.eng
 	eng := container.daemon.eng
 
 
 	// Re-allocate the interface with the same IP and MAC address.
 	// Re-allocate the interface with the same IP and MAC address.
-	job := eng.Job("allocate_interface", container.ID)
-	job.Setenv("RequestedIP", container.NetworkSettings.IPAddress)
-	job.Setenv("RequestedMac", container.NetworkSettings.MacAddress)
-	if err := job.Run(); err != nil {
+	if _, err := bridge.Allocate(container.ID, container.NetworkSettings.MacAddress, container.NetworkSettings.IPAddress, ""); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -1077,7 +1060,7 @@ func (container *Container) setupContainerDns() error {
 			latestResolvConf, latestHash := resolvconf.GetLastModified()
 			latestResolvConf, latestHash := resolvconf.GetLastModified()
 
 
 			// clean container resolv.conf re: localhost nameservers and IPv6 NS (if IPv6 disabled)
 			// clean container resolv.conf re: localhost nameservers and IPv6 NS (if IPv6 disabled)
-			updatedResolvConf, modified := resolvconf.FilterResolvDns(latestResolvConf, container.daemon.config.EnableIPv6)
+			updatedResolvConf, modified := resolvconf.FilterResolvDns(latestResolvConf, container.daemon.config.Bridge.EnableIPv6)
 			if modified {
 			if modified {
 				// changes have occurred during resolv.conf localhost cleanup: generate an updated hash
 				// changes have occurred during resolv.conf localhost cleanup: generate an updated hash
 				newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
 				newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
@@ -1131,7 +1114,7 @@ func (container *Container) setupContainerDns() error {
 		}
 		}
 
 
 		// replace any localhost/127.*, and remove IPv6 nameservers if IPv6 disabled in daemon
 		// replace any localhost/127.*, and remove IPv6 nameservers if IPv6 disabled in daemon
-		resolvConf, _ = resolvconf.FilterResolvDns(resolvConf, daemon.config.EnableIPv6)
+		resolvConf, _ = resolvconf.FilterResolvDns(resolvConf, daemon.config.Bridge.EnableIPv6)
 	}
 	}
 	//get a sha256 hash of the resolv conf at this point so we can check
 	//get a sha256 hash of the resolv conf at this point so we can check
 	//for changes when the host resolv.conf changes (e.g. network update)
 	//for changes when the host resolv.conf changes (e.g. network update)
@@ -1481,24 +1464,10 @@ func (container *Container) allocatePort(eng *engine.Engine, port nat.Port, bind
 	}
 	}
 
 
 	for i := 0; i < len(binding); i++ {
 	for i := 0; i < len(binding); i++ {
-		b := binding[i]
-
-		job := eng.Job("allocate_port", container.ID)
-		job.Setenv("HostIP", b.HostIp)
-		job.Setenv("HostPort", b.HostPort)
-		job.Setenv("Proto", port.Proto())
-		job.Setenv("ContainerPort", port.Port())
-
-		portEnv, err := job.Stdout.AddEnv()
+		b, err := bridge.AllocatePort(container.ID, port, binding[i])
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		if err := job.Run(); err != nil {
-			return err
-		}
-		b.HostIp = portEnv.Get("HostIP")
-		b.HostPort = portEnv.Get("HostPort")
-
 		binding[i] = b
 		binding[i] = b
 	}
 	}
 	bindings[port] = binding
 	bindings[port] = binding

+ 10 - 22
daemon/daemon.go

@@ -25,7 +25,8 @@ import (
 	"github.com/docker/docker/daemon/execdriver/lxc"
 	"github.com/docker/docker/daemon/execdriver/lxc"
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/daemon/graphdriver"
 	_ "github.com/docker/docker/daemon/graphdriver/vfs"
 	_ "github.com/docker/docker/daemon/graphdriver/vfs"
-	_ "github.com/docker/docker/daemon/networkdriver/bridge"
+	"github.com/docker/docker/daemon/network"
+	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/graph"
 	"github.com/docker/docker/graph"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image"
@@ -445,7 +446,7 @@ func (daemon *Daemon) setupResolvconfWatcher() error {
 						logrus.Debugf("Error retrieving updated host resolv.conf: %v", err)
 						logrus.Debugf("Error retrieving updated host resolv.conf: %v", err)
 					} else if updatedResolvConf != nil {
 					} else if updatedResolvConf != nil {
 						// because the new host resolv.conf might have localhost nameservers..
 						// because the new host resolv.conf might have localhost nameservers..
-						updatedResolvConf, modified := resolvconf.FilterResolvDns(updatedResolvConf, daemon.config.EnableIPv6)
+						updatedResolvConf, modified := resolvconf.FilterResolvDns(updatedResolvConf, daemon.config.Bridge.EnableIPv6)
 						if modified {
 						if modified {
 							// changes have occurred during localhost cleanup: generate an updated hash
 							// changes have occurred during localhost cleanup: generate an updated hash
 							newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
 							newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
@@ -653,7 +654,7 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
 		Config:          config,
 		Config:          config,
 		hostConfig:      &runconfig.HostConfig{},
 		hostConfig:      &runconfig.HostConfig{},
 		ImageID:         imgID,
 		ImageID:         imgID,
-		NetworkSettings: &NetworkSettings{},
+		NetworkSettings: &network.Settings{},
 		Name:            name,
 		Name:            name,
 		Driver:          daemon.driver.String(),
 		Driver:          daemon.driver.String(),
 		ExecDriver:      daemon.execDriver.Name(),
 		ExecDriver:      daemon.execDriver.Name(),
@@ -807,16 +808,16 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
 		config.Mtu = getDefaultNetworkMtu()
 		config.Mtu = getDefaultNetworkMtu()
 	}
 	}
 	// Check for mutually incompatible config options
 	// Check for mutually incompatible config options
-	if config.BridgeIface != "" && config.BridgeIP != "" {
+	if config.Bridge.Iface != "" && config.Bridge.IP != "" {
 		return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
 		return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
 	}
 	}
-	if !config.EnableIptables && !config.InterContainerCommunication {
+	if !config.Bridge.EnableIptables && !config.Bridge.InterContainerCommunication {
 		return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
 		return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
 	}
 	}
-	if !config.EnableIptables && config.EnableIpMasq {
-		config.EnableIpMasq = false
+	if !config.Bridge.EnableIptables && config.Bridge.EnableIpMasq {
+		config.Bridge.EnableIpMasq = false
 	}
 	}
-	config.DisableNetwork = config.BridgeIface == disableNetworkBridge
+	config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge
 
 
 	// Claim the pidfile first, to avoid any and all unexpected race conditions.
 	// Claim the pidfile first, to avoid any and all unexpected race conditions.
 	// Some of the init doesn't need a pidfile lock - but let's not try to be smart.
 	// Some of the init doesn't need a pidfile lock - but let's not try to be smart.
@@ -948,20 +949,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
 	}
 	}
 
 
 	if !config.DisableNetwork {
 	if !config.DisableNetwork {
-		job := eng.Job("init_networkdriver")
-
-		job.SetenvBool("EnableIptables", config.EnableIptables)
-		job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication)
-		job.SetenvBool("EnableIpForward", config.EnableIpForward)
-		job.SetenvBool("EnableIpMasq", config.EnableIpMasq)
-		job.SetenvBool("EnableIPv6", config.EnableIPv6)
-		job.Setenv("BridgeIface", config.BridgeIface)
-		job.Setenv("BridgeIP", config.BridgeIP)
-		job.Setenv("FixedCIDR", config.FixedCIDR)
-		job.Setenv("FixedCIDRv6", config.FixedCIDRv6)
-		job.Setenv("DefaultBindingIP", config.DefaultIp.String())
-
-		if err := job.Run(); err != nil {
+		if err := bridge.InitDriver(&config.Bridge); err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}

+ 4 - 9
daemon/network_settings.go → daemon/network/settings.go

@@ -1,13 +1,8 @@
-package daemon
+package network
 
 
-import (
-	"github.com/docker/docker/nat"
-)
+import "github.com/docker/docker/nat"
 
 
-// FIXME: move deprecated port stuff to nat to clean up the core.
-type PortMapping map[string]string // Deprecated
-
-type NetworkSettings struct {
+type Settings struct {
 	IPAddress              string
 	IPAddress              string
 	IPPrefixLen            int
 	IPPrefixLen            int
 	MacAddress             string
 	MacAddress             string
@@ -18,6 +13,6 @@ type NetworkSettings struct {
 	Gateway                string
 	Gateway                string
 	IPv6Gateway            string
 	IPv6Gateway            string
 	Bridge                 string
 	Bridge                 string
-	PortMapping            map[string]PortMapping // Deprecated
+	PortMapping            map[string]map[string]string // Deprecated
 	Ports                  nat.PortMap
 	Ports                  nat.PortMap
 }
 }

+ 102 - 129
daemon/networkdriver/bridge/driver.go

@@ -7,14 +7,15 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"net"
 	"net"
 	"os"
 	"os"
+	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/daemon/network"
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver"
 	"github.com/docker/docker/daemon/networkdriver/ipallocator"
 	"github.com/docker/docker/daemon/networkdriver/ipallocator"
 	"github.com/docker/docker/daemon/networkdriver/portmapper"
 	"github.com/docker/docker/daemon/networkdriver/portmapper"
-	"github.com/docker/docker/engine"
 	"github.com/docker/docker/nat"
 	"github.com/docker/docker/nat"
 	"github.com/docker/docker/pkg/iptables"
 	"github.com/docker/docker/pkg/iptables"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/kernel"
@@ -91,29 +92,34 @@ func initPortMapper() {
 	})
 	})
 }
 }
 
 
-func InitDriver(job *engine.Job) error {
+type Config struct {
+	EnableIPv6                  bool
+	EnableIptables              bool
+	EnableIpForward             bool
+	EnableIpMasq                bool
+	DefaultIp                   net.IP
+	Iface                       string
+	IP                          string
+	FixedCIDR                   string
+	FixedCIDRv6                 string
+	InterContainerCommunication bool
+}
+
+func InitDriver(config *Config) error {
 	var (
 	var (
-		networkv4      *net.IPNet
-		networkv6      *net.IPNet
-		addrv4         net.Addr
-		addrsv6        []net.Addr
-		enableIPTables = job.GetenvBool("EnableIptables")
-		enableIPv6     = job.GetenvBool("EnableIPv6")
-		icc            = job.GetenvBool("InterContainerCommunication")
-		ipMasq         = job.GetenvBool("EnableIpMasq")
-		ipForward      = job.GetenvBool("EnableIpForward")
-		bridgeIP       = job.Getenv("BridgeIP")
-		bridgeIPv6     = "fe80::1/64"
-		fixedCIDR      = job.Getenv("FixedCIDR")
-		fixedCIDRv6    = job.Getenv("FixedCIDRv6")
+		networkv4  *net.IPNet
+		networkv6  *net.IPNet
+		addrv4     net.Addr
+		addrsv6    []net.Addr
+		bridgeIPv6 = "fe80::1/64"
 	)
 	)
 	initPortMapper()
 	initPortMapper()
 
 
-	if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
-		defaultBindingIP = net.ParseIP(defaultIP)
+	if config.DefaultIp != nil {
+		defaultBindingIP = config.DefaultIp
 	}
 	}
 
 
-	bridgeIface = job.Getenv("BridgeIface")
+	bridgeIface = config.Iface
 	usingDefaultBridge := false
 	usingDefaultBridge := false
 	if bridgeIface == "" {
 	if bridgeIface == "" {
 		usingDefaultBridge = true
 		usingDefaultBridge = true
@@ -130,7 +136,7 @@ func InitDriver(job *engine.Job) error {
 		}
 		}
 
 
 		// If the iface is not found, try to create it
 		// If the iface is not found, try to create it
-		if err := configureBridge(bridgeIP, bridgeIPv6, enableIPv6); err != nil {
+		if err := configureBridge(config.IP, bridgeIPv6, config.EnableIPv6); err != nil {
 			return err
 			return err
 		}
 		}
 
 
@@ -139,19 +145,19 @@ func InitDriver(job *engine.Job) error {
 			return err
 			return err
 		}
 		}
 
 
-		if fixedCIDRv6 != "" {
+		if config.FixedCIDRv6 != "" {
 			// Setting route to global IPv6 subnet
 			// Setting route to global IPv6 subnet
-			logrus.Infof("Adding route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
-			if err := netlink.AddRoute(fixedCIDRv6, "", "", bridgeIface); err != nil {
-				logrus.Fatalf("Could not add route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
+			logrus.Infof("Adding route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
+			if err := netlink.AddRoute(config.FixedCIDRv6, "", "", bridgeIface); err != nil {
+				logrus.Fatalf("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
 			}
 			}
 		}
 		}
 	} else {
 	} else {
 		// Bridge exists already, getting info...
 		// Bridge exists already, getting info...
 		// Validate that the bridge ip matches the ip specified by BridgeIP
 		// Validate that the bridge ip matches the ip specified by BridgeIP
-		if bridgeIP != "" {
+		if config.IP != "" {
 			networkv4 = addrv4.(*net.IPNet)
 			networkv4 = addrv4.(*net.IPNet)
-			bip, _, err := net.ParseCIDR(bridgeIP)
+			bip, _, err := net.ParseCIDR(config.IP)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
@@ -164,7 +170,7 @@ func InitDriver(job *engine.Job) error {
 		// (for example, an existing Docker installation that has only been used
 		// (for example, an existing Docker installation that has only been used
 		// with IPv4 and docker0 already is set up) In that case, we can perform
 		// with IPv4 and docker0 already is set up) In that case, we can perform
 		// the bridge init for IPv6 here, else we will error out below if --ipv6=true
 		// the bridge init for IPv6 here, else we will error out below if --ipv6=true
-		if len(addrsv6) == 0 && enableIPv6 {
+		if len(addrsv6) == 0 && config.EnableIPv6 {
 			if err := setupIPv6Bridge(bridgeIPv6); err != nil {
 			if err := setupIPv6Bridge(bridgeIPv6); err != nil {
 				return err
 				return err
 			}
 			}
@@ -175,10 +181,10 @@ func InitDriver(job *engine.Job) error {
 			}
 			}
 		}
 		}
 
 
-		// TODO: Check if route to fixedCIDRv6 is set
+		// TODO: Check if route to config.FixedCIDRv6 is set
 	}
 	}
 
 
-	if enableIPv6 {
+	if config.EnableIPv6 {
 		bip6, _, err := net.ParseCIDR(bridgeIPv6)
 		bip6, _, err := net.ParseCIDR(bridgeIPv6)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
@@ -198,7 +204,7 @@ func InitDriver(job *engine.Job) error {
 
 
 	networkv4 = addrv4.(*net.IPNet)
 	networkv4 = addrv4.(*net.IPNet)
 
 
-	if enableIPv6 {
+	if config.EnableIPv6 {
 		if len(addrsv6) == 0 {
 		if len(addrsv6) == 0 {
 			return errors.New("IPv6 enabled but no IPv6 detected")
 			return errors.New("IPv6 enabled but no IPv6 detected")
 		}
 		}
@@ -206,20 +212,20 @@ func InitDriver(job *engine.Job) error {
 	}
 	}
 
 
 	// Configure iptables for link support
 	// Configure iptables for link support
-	if enableIPTables {
-		if err := setupIPTables(addrv4, icc, ipMasq); err != nil {
+	if config.EnableIptables {
+		if err := setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq); err != nil {
 			return err
 			return err
 		}
 		}
 
 
 	}
 	}
 
 
-	if ipForward {
+	if config.EnableIpForward {
 		// Enable IPv4 forwarding
 		// Enable IPv4 forwarding
 		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
 		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
 			logrus.Warnf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
 			logrus.Warnf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
 		}
 		}
 
 
-		if fixedCIDRv6 != "" {
+		if config.FixedCIDRv6 != "" {
 			// Enable IPv6 forwarding
 			// Enable IPv6 forwarding
 			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
 			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
 				logrus.Warnf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
 				logrus.Warnf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
@@ -235,7 +241,7 @@ func InitDriver(job *engine.Job) error {
 		return err
 		return err
 	}
 	}
 
 
-	if enableIPTables {
+	if config.EnableIptables {
 		_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
 		_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
@@ -248,8 +254,8 @@ func InitDriver(job *engine.Job) error {
 	}
 	}
 
 
 	bridgeIPv4Network = networkv4
 	bridgeIPv4Network = networkv4
-	if fixedCIDR != "" {
-		_, subnet, err := net.ParseCIDR(fixedCIDR)
+	if config.FixedCIDR != "" {
+		_, subnet, err := net.ParseCIDR(config.FixedCIDR)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -259,8 +265,8 @@ func InitDriver(job *engine.Job) error {
 		}
 		}
 	}
 	}
 
 
-	if fixedCIDRv6 != "" {
-		_, subnet, err := net.ParseCIDR(fixedCIDRv6)
+	if config.FixedCIDRv6 != "" {
+		_, subnet, err := net.ParseCIDR(config.FixedCIDRv6)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -274,19 +280,6 @@ func InitDriver(job *engine.Job) error {
 	// Block BridgeIP in IP allocator
 	// Block BridgeIP in IP allocator
 	ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
 	ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
 
 
-	// https://github.com/docker/docker/issues/2768
-	job.Eng.HackSetGlobalVar("httpapi.bridgeIP", bridgeIPv4Network.IP)
-
-	for name, f := range map[string]engine.Handler{
-		"allocate_interface": Allocate,
-		"release_interface":  Release,
-		"allocate_port":      AllocatePort,
-		"link":               LinkContainers,
-	} {
-		if err := job.Eng.Register(name, f); err != nil {
-			return err
-		}
-	}
 	return nil
 	return nil
 }
 }
 
 
@@ -513,70 +506,67 @@ func linkLocalIPv6FromMac(mac string) (string, error) {
 }
 }
 
 
 // Allocate a network interface
 // Allocate a network interface
-func Allocate(job *engine.Job) error {
+func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Settings, error) {
 	var (
 	var (
-		ip            net.IP
-		mac           net.HardwareAddr
-		err           error
-		id            = job.Args[0]
-		requestedIP   = net.ParseIP(job.Getenv("RequestedIP"))
-		requestedIPv6 = net.ParseIP(job.Getenv("RequestedIPv6"))
-		globalIPv6    net.IP
+		ip         net.IP
+		mac        net.HardwareAddr
+		err        error
+		globalIPv6 net.IP
 	)
 	)
 
 
-	ip, err = ipAllocator.RequestIP(bridgeIPv4Network, requestedIP)
+	ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP))
 	if err != nil {
 	if err != nil {
-		return err
+		return nil, err
 	}
 	}
 
 
 	// If no explicit mac address was given, generate a random one.
 	// If no explicit mac address was given, generate a random one.
-	if mac, err = net.ParseMAC(job.Getenv("RequestedMac")); err != nil {
+	if mac, err = net.ParseMAC(requestedMac); err != nil {
 		mac = generateMacAddr(ip)
 		mac = generateMacAddr(ip)
 	}
 	}
 
 
 	if globalIPv6Network != nil {
 	if globalIPv6Network != nil {
 		// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
 		// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
 		netmaskOnes, _ := globalIPv6Network.Mask.Size()
 		netmaskOnes, _ := globalIPv6Network.Mask.Size()
-		if requestedIPv6 == nil && netmaskOnes <= 80 {
-			requestedIPv6 = make(net.IP, len(globalIPv6Network.IP))
-			copy(requestedIPv6, globalIPv6Network.IP)
+		ipv6 := net.ParseIP(requestedIPv6)
+		if ipv6 == nil && netmaskOnes <= 80 {
+			ipv6 = make(net.IP, len(globalIPv6Network.IP))
+			copy(ipv6, globalIPv6Network.IP)
 			for i, h := range mac {
 			for i, h := range mac {
-				requestedIPv6[i+10] = h
+				ipv6[i+10] = h
 			}
 			}
 		}
 		}
 
 
-		globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, requestedIPv6)
+		globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, ipv6)
 		if err != nil {
 		if err != nil {
 			logrus.Errorf("Allocator: RequestIP v6: %v", err)
 			logrus.Errorf("Allocator: RequestIP v6: %v", err)
-			return err
+			return nil, err
 		}
 		}
 		logrus.Infof("Allocated IPv6 %s", globalIPv6)
 		logrus.Infof("Allocated IPv6 %s", globalIPv6)
 	}
 	}
 
 
-	out := engine.Env{}
-	out.Set("IP", ip.String())
-	out.Set("Mask", bridgeIPv4Network.Mask.String())
-	out.Set("Gateway", bridgeIPv4Network.IP.String())
-	out.Set("MacAddress", mac.String())
-	out.Set("Bridge", bridgeIface)
-
-	size, _ := bridgeIPv4Network.Mask.Size()
-	out.SetInt("IPPrefixLen", size)
+	maskSize, _ := bridgeIPv4Network.Mask.Size()
 
 
 	// If linklocal IPv6
 	// If linklocal IPv6
 	localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
 	localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
 	if err != nil {
 	if err != nil {
-		return err
+		return nil, err
 	}
 	}
 	localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
 	localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
-	out.Set("LinkLocalIPv6", localIPv6.String())
-	out.Set("MacAddress", mac.String())
+
+	networkSettings := &network.Settings{
+		IPAddress:            ip.String(),
+		Gateway:              bridgeIPv4Network.IP.String(),
+		MacAddress:           mac.String(),
+		Bridge:               bridgeIface,
+		IPPrefixLen:          maskSize,
+		LinkLocalIPv6Address: localIPv6.String(),
+	}
 
 
 	if globalIPv6Network != nil {
 	if globalIPv6Network != nil {
-		out.Set("GlobalIPv6", globalIPv6.String())
-		sizev6, _ := globalIPv6Network.Mask.Size()
-		out.SetInt("GlobalIPv6PrefixLen", sizev6)
-		out.Set("IPv6Gateway", bridgeIPv6Addr.String())
+		networkSettings.GlobalIPv6Address = globalIPv6.String()
+		maskV6Size, _ := globalIPv6Network.Mask.Size()
+		networkSettings.GlobalIPv6PrefixLen = maskV6Size
+		networkSettings.IPv6Gateway = bridgeIPv6Addr.String()
 	}
 	}
 
 
 	currentInterfaces.Set(id, &networkInterface{
 	currentInterfaces.Set(id, &networkInterface{
@@ -584,20 +574,15 @@ func Allocate(job *engine.Job) error {
 		IPv6: globalIPv6,
 		IPv6: globalIPv6,
 	})
 	})
 
 
-	out.WriteTo(job.Stdout)
-
-	return nil
+	return networkSettings, nil
 }
 }
 
 
 // Release an interface for a select ip
 // Release an interface for a select ip
-func Release(job *engine.Job) error {
-	var (
-		id                 = job.Args[0]
-		containerInterface = currentInterfaces.Get(id)
-	)
+func Release(id string) {
+	var containerInterface = currentInterfaces.Get(id)
 
 
 	if containerInterface == nil {
 	if containerInterface == nil {
-		return fmt.Errorf("No network information to release for %s", id)
+		logrus.Warnf("No network information to release for %s", id)
 	}
 	}
 
 
 	for _, nat := range containerInterface.PortMappings {
 	for _, nat := range containerInterface.PortMappings {
@@ -614,27 +599,21 @@ func Release(job *engine.Job) error {
 			logrus.Infof("Unable to release IPv6 %s", err)
 			logrus.Infof("Unable to release IPv6 %s", err)
 		}
 		}
 	}
 	}
-	return nil
 }
 }
 
 
 // Allocate an external port and map it to the interface
 // Allocate an external port and map it to the interface
-func AllocatePort(job *engine.Job) error {
+func AllocatePort(id string, port nat.Port, binding nat.PortBinding) (nat.PortBinding, error) {
 	var (
 	var (
-		err error
-
 		ip            = defaultBindingIP
 		ip            = defaultBindingIP
-		id            = job.Args[0]
-		hostIP        = job.Getenv("HostIP")
-		hostPort      = job.GetenvInt("HostPort")
-		containerPort = job.GetenvInt("ContainerPort")
-		proto         = job.Getenv("Proto")
+		proto         = port.Proto()
+		containerPort = port.Int()
 		network       = currentInterfaces.Get(id)
 		network       = currentInterfaces.Get(id)
 	)
 	)
 
 
-	if hostIP != "" {
-		ip = net.ParseIP(hostIP)
+	if binding.HostIp != "" {
+		ip = net.ParseIP(binding.HostIp)
 		if ip == nil {
 		if ip == nil {
-			return fmt.Errorf("Bad parameter: invalid host ip %s", hostIP)
+			return nat.PortBinding{}, fmt.Errorf("Bad parameter: invalid host ip %s", binding.HostIp)
 		}
 		}
 	}
 	}
 
 
@@ -646,7 +625,7 @@ func AllocatePort(job *engine.Job) error {
 	case "udp":
 	case "udp":
 		container = &net.UDPAddr{IP: network.IP, Port: containerPort}
 		container = &net.UDPAddr{IP: network.IP, Port: containerPort}
 	default:
 	default:
-		return fmt.Errorf("unsupported address type %s", proto)
+		return nat.PortBinding{}, fmt.Errorf("unsupported address type %s", proto)
 	}
 	}
 
 
 	//
 	//
@@ -656,7 +635,14 @@ func AllocatePort(job *engine.Job) error {
 	// yields.
 	// yields.
 	//
 	//
 
 
-	var host net.Addr
+	var (
+		host net.Addr
+		err  error
+	)
+	hostPort, err := nat.ParsePort(binding.HostPort)
+	if err != nil {
+		return nat.PortBinding{}, err
+	}
 	for i := 0; i < MaxAllocatedPortAttempts; i++ {
 	for i := 0; i < MaxAllocatedPortAttempts; i++ {
 		if host, err = portMapper.Map(container, ip, hostPort); err == nil {
 		if host, err = portMapper.Map(container, ip, hostPort); err == nil {
 			break
 			break
@@ -671,36 +657,24 @@ func AllocatePort(job *engine.Job) error {
 	}
 	}
 
 
 	if err != nil {
 	if err != nil {
-		return err
+		return nat.PortBinding{}, err
 	}
 	}
 
 
 	network.PortMappings = append(network.PortMappings, host)
 	network.PortMappings = append(network.PortMappings, host)
 
 
-	out := engine.Env{}
 	switch netAddr := host.(type) {
 	switch netAddr := host.(type) {
 	case *net.TCPAddr:
 	case *net.TCPAddr:
-		out.Set("HostIP", netAddr.IP.String())
-		out.SetInt("HostPort", netAddr.Port)
+		return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
 	case *net.UDPAddr:
 	case *net.UDPAddr:
-		out.Set("HostIP", netAddr.IP.String())
-		out.SetInt("HostPort", netAddr.Port)
-	}
-	if _, err := out.WriteTo(job.Stdout); err != nil {
-		return err
+		return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
+	default:
+		return nat.PortBinding{}, fmt.Errorf("unsupported address type %T", netAddr)
 	}
 	}
-
-	return nil
 }
 }
 
 
-func LinkContainers(job *engine.Job) error {
-	var (
-		action       = job.Args[0]
-		nfAction     iptables.Action
-		childIP      = job.Getenv("ChildIP")
-		parentIP     = job.Getenv("ParentIP")
-		ignoreErrors = job.GetenvBool("IgnoreErrors")
-		ports        = job.GetenvList("Ports")
-	)
+//TODO: should it return something more than just an error?
+func LinkContainers(action, parentIP, childIP string, ports []nat.Port, ignoreErrors bool) error {
+	var nfAction iptables.Action
 
 
 	switch action {
 	switch action {
 	case "-A":
 	case "-A":
@@ -723,8 +697,7 @@ func LinkContainers(job *engine.Job) error {
 	}
 	}
 
 
 	chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
 	chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
-	for _, p := range ports {
-		port := nat.Port(p)
+	for _, port := range ports {
 		if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
 		if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
 			return err
 			return err
 		}
 		}

+ 46 - 132
daemon/networkdriver/bridge/driver_test.go

@@ -6,8 +6,9 @@ import (
 	"strconv"
 	"strconv"
 	"testing"
 	"testing"
 
 
+	"github.com/docker/docker/daemon/network"
 	"github.com/docker/docker/daemon/networkdriver/portmapper"
 	"github.com/docker/docker/daemon/networkdriver/portmapper"
-	"github.com/docker/docker/engine"
+	"github.com/docker/docker/nat"
 	"github.com/docker/docker/pkg/iptables"
 	"github.com/docker/docker/pkg/iptables"
 )
 )
 
 
@@ -16,7 +17,7 @@ func init() {
 	portmapper.NewProxy = portmapper.NewMockProxyCommand
 	portmapper.NewProxy = portmapper.NewMockProxyCommand
 }
 }
 
 
-func findFreePort(t *testing.T) int {
+func findFreePort(t *testing.T) string {
 	l, err := net.Listen("tcp", ":0")
 	l, err := net.Listen("tcp", ":0")
 	if err != nil {
 	if err != nil {
 		t.Fatal("Failed to find a free port")
 		t.Fatal("Failed to find a free port")
@@ -27,143 +28,85 @@ func findFreePort(t *testing.T) int {
 	if err != nil {
 	if err != nil {
 		t.Fatal("Failed to resolve address to identify free port")
 		t.Fatal("Failed to resolve address to identify free port")
 	}
 	}
-	return result.Port
-}
-
-func newPortAllocationJob(eng *engine.Engine, port int) (job *engine.Job) {
-	strPort := strconv.Itoa(port)
-
-	job = eng.Job("allocate_port", "container_id")
-	job.Setenv("HostIP", "127.0.0.1")
-	job.Setenv("HostPort", strPort)
-	job.Setenv("Proto", "tcp")
-	job.Setenv("ContainerPort", strPort)
-	return
-}
-
-func newPortAllocationJobWithInvalidHostIP(eng *engine.Engine, port int) (job *engine.Job) {
-	strPort := strconv.Itoa(port)
-
-	job = eng.Job("allocate_port", "container_id")
-	job.Setenv("HostIP", "localhost")
-	job.Setenv("HostPort", strPort)
-	job.Setenv("Proto", "tcp")
-	job.Setenv("ContainerPort", strPort)
-	return
+	return strconv.Itoa(result.Port)
 }
 }
 
 
 func TestAllocatePortDetection(t *testing.T) {
 func TestAllocatePortDetection(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
 	freePort := findFreePort(t)
 	freePort := findFreePort(t)
 
 
-	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != nil {
+	if err := InitDriver(new(Config)); err != nil {
 		t.Fatal("Failed to initialize network driver")
 		t.Fatal("Failed to initialize network driver")
 	}
 	}
 
 
 	// Allocate interface
 	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != nil {
+	if _, err := Allocate("container_id", "", "", ""); err != nil {
 		t.Fatal("Failed to allocate network interface")
 		t.Fatal("Failed to allocate network interface")
 	}
 	}
 
 
+	port := nat.Port(freePort + "/tcp")
+	binding := nat.PortBinding{HostIp: "127.0.0.1", HostPort: freePort}
+
 	// Allocate same port twice, expect failure on second call
 	// Allocate same port twice, expect failure on second call
-	job = newPortAllocationJob(eng, freePort)
-	if res := AllocatePort(job); res != nil {
+	if _, err := AllocatePort("container_id", port, binding); err != nil {
 		t.Fatal("Failed to find a free port to allocate")
 		t.Fatal("Failed to find a free port to allocate")
 	}
 	}
-	if res := AllocatePort(job); res == nil {
+	if _, err := AllocatePort("container_id", port, binding); err == nil {
 		t.Fatal("Duplicate port allocation granted by AllocatePort")
 		t.Fatal("Duplicate port allocation granted by AllocatePort")
 	}
 	}
 }
 }
 
 
 func TestHostnameFormatChecking(t *testing.T) {
 func TestHostnameFormatChecking(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
 	freePort := findFreePort(t)
 	freePort := findFreePort(t)
 
 
-	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != nil {
+	if err := InitDriver(new(Config)); err != nil {
 		t.Fatal("Failed to initialize network driver")
 		t.Fatal("Failed to initialize network driver")
 	}
 	}
 
 
 	// Allocate interface
 	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != nil {
+	if _, err := Allocate("container_id", "", "", ""); err != nil {
 		t.Fatal("Failed to allocate network interface")
 		t.Fatal("Failed to allocate network interface")
 	}
 	}
 
 
-	// Allocate port with invalid HostIP, expect failure with Bad Request http status
-	job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
-	if res := AllocatePort(job); res == nil {
+	port := nat.Port(freePort + "/tcp")
+	binding := nat.PortBinding{HostIp: "localhost", HostPort: freePort}
+
+	if _, err := AllocatePort("container_id", port, binding); err == nil {
 		t.Fatal("Failed to check invalid HostIP")
 		t.Fatal("Failed to check invalid HostIP")
 	}
 	}
 }
 }
 
 
-func newInterfaceAllocation(t *testing.T, input engine.Env) (output engine.Env) {
-	eng := engine.New()
-	eng.Logging = false
-
-	done := make(chan bool)
-
+func newInterfaceAllocation(t *testing.T, globalIPv6 *net.IPNet, requestedMac, requestedIP, requestedIPv6 string, expectFail bool) *network.Settings {
 	// set IPv6 global if given
 	// set IPv6 global if given
-	if input.Exists("globalIPv6Network") {
-		_, globalIPv6Network, _ = net.ParseCIDR(input.Get("globalIPv6Network"))
+	if globalIPv6 != nil {
+		globalIPv6Network = globalIPv6
 	}
 	}
 
 
-	job := eng.Job("allocate_interface", "container_id")
-	job.Env().Init(&input)
-	reader, _ := job.Stdout.AddPipe()
-	go func() {
-		output.Decode(reader)
-		done <- true
-	}()
-
-	res := Allocate(job)
-	job.Stdout.Close()
-	<-done
-
-	if input.Exists("expectFail") && input.GetBool("expectFail") {
-		if res == nil {
-			t.Fatal("Doesn't fail to allocate network interface")
-		}
-	} else {
-		if res != nil {
-			t.Fatal("Failed to allocate network interface")
-		}
+	networkSettings, err := Allocate("container_id", requestedMac, requestedIP, requestedIPv6)
+	if err == nil && expectFail {
+		t.Fatal("Doesn't fail to allocate network interface")
+	} else if err != nil && !expectFail {
+		t.Fatal("Failed to allocate network interface")
+
 	}
 	}
 
 
-	if input.Exists("globalIPv6Network") {
+	if globalIPv6 != nil {
 		// check for bug #11427
 		// check for bug #11427
-		_, subnet, _ := net.ParseCIDR(input.Get("globalIPv6Network"))
-		if globalIPv6Network.IP.String() != subnet.IP.String() {
+		if globalIPv6Network.IP.String() != globalIPv6.IP.String() {
 			t.Fatal("globalIPv6Network was modified during allocation")
 			t.Fatal("globalIPv6Network was modified during allocation")
 		}
 		}
 		// clean up IPv6 global
 		// clean up IPv6 global
 		globalIPv6Network = nil
 		globalIPv6Network = nil
 	}
 	}
 
 
-	return
+	return networkSettings
 }
 }
 
 
 func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
 func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
-
-	input := engine.Env{}
-
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81")
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81")
-
-	// set global ipv6
-	input.Set("globalIPv6Network", subnet.String())
-
-	output := newInterfaceAllocation(t, input)
+	networkSettings := newInterfaceAllocation(t, subnet, "", "", "", false)
 
 
 	// ensure low manually assigend global ip
 	// ensure low manually assigend global ip
-	ip := net.ParseIP(output.Get("GlobalIPv6"))
+	ip := net.ParseIP(networkSettings.GlobalIPv6Address)
 	_, subnet, _ = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet.IP.String(), 120))
 	_, subnet, _ = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet.IP.String(), 120))
 	if !subnet.Contains(ip) {
 	if !subnet.Contains(ip) {
 		t.Fatalf("Error ip %s not in subnet %s", ip.String(), subnet.String())
 		t.Fatalf("Error ip %s not in subnet %s", ip.String(), subnet.String())
@@ -171,26 +114,18 @@ func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
 }
 }
 
 
 func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
 func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
-
-	input := engine.Env{}
-
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
-
-	// set global ipv6
-	input.Set("globalIPv6Network", subnet.String())
-	input.Set("RequestedMac", "ab:cd:ab:cd:ab:cd")
-
-	output := newInterfaceAllocation(t, input)
+	networkSettings := newInterfaceAllocation(t, subnet, "ab:cd:ab:cd:ab:cd", "", "", false)
 
 
 	// ensure global ip with mac
 	// ensure global ip with mac
-	ip := net.ParseIP(output.Get("GlobalIPv6"))
+	ip := net.ParseIP(networkSettings.GlobalIPv6Address)
 	expectedIP := net.ParseIP("2001:db8:1234:1234:1234:abcd:abcd:abcd")
 	expectedIP := net.ParseIP("2001:db8:1234:1234:1234:abcd:abcd:abcd")
 	if ip.String() != expectedIP.String() {
 	if ip.String() != expectedIP.String() {
 		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
 		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
 	}
 	}
 
 
 	// ensure link local format
 	// ensure link local format
-	ip = net.ParseIP(output.Get("LinkLocalIPv6"))
+	ip = net.ParseIP(networkSettings.LinkLocalIPv6Address)
 	expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd")
 	expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd")
 	if ip.String() != expectedIP.String() {
 	if ip.String() != expectedIP.String() {
 		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
 		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
@@ -199,27 +134,19 @@ func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
 }
 }
 
 
 func TestIPv6InterfaceAllocationRequest(t *testing.T) {
 func TestIPv6InterfaceAllocationRequest(t *testing.T) {
-
-	input := engine.Env{}
-
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
 	_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
-	expectedIP := net.ParseIP("2001:db8:1234:1234:1234::1328")
-
-	// set global ipv6
-	input.Set("globalIPv6Network", subnet.String())
-	input.Set("RequestedIPv6", expectedIP.String())
+	expectedIP := "2001:db8:1234:1234:1234::1328"
 
 
-	output := newInterfaceAllocation(t, input)
+	networkSettings := newInterfaceAllocation(t, subnet, "", "", expectedIP, false)
 
 
 	// ensure global ip with mac
 	// ensure global ip with mac
-	ip := net.ParseIP(output.Get("GlobalIPv6"))
-	if ip.String() != expectedIP.String() {
-		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
+	ip := net.ParseIP(networkSettings.GlobalIPv6Address)
+	if ip.String() != expectedIP {
+		t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP)
 	}
 	}
 
 
 	// retry -> fails for duplicated address
 	// retry -> fails for duplicated address
-	input.SetBool("expectFail", true)
-	output = newInterfaceAllocation(t, input)
+	_ = newInterfaceAllocation(t, subnet, "", "", expectedIP, true)
 }
 }
 
 
 func TestMacAddrGeneration(t *testing.T) {
 func TestMacAddrGeneration(t *testing.T) {
@@ -239,40 +166,27 @@ func TestMacAddrGeneration(t *testing.T) {
 }
 }
 
 
 func TestLinkContainers(t *testing.T) {
 func TestLinkContainers(t *testing.T) {
-	eng := engine.New()
-	eng.Logging = false
-
 	// Init driver
 	// Init driver
-	job := eng.Job("initdriver")
-	if res := InitDriver(job); res != nil {
+	if err := InitDriver(new(Config)); err != nil {
 		t.Fatal("Failed to initialize network driver")
 		t.Fatal("Failed to initialize network driver")
 	}
 	}
 
 
 	// Allocate interface
 	// Allocate interface
-	job = eng.Job("allocate_interface", "container_id")
-	if res := Allocate(job); res != nil {
+	if _, err := Allocate("container_id", "", "", ""); err != nil {
 		t.Fatal("Failed to allocate network interface")
 		t.Fatal("Failed to allocate network interface")
 	}
 	}
 
 
-	job.Args[0] = "-I"
-
-	job.Setenv("ChildIP", "172.17.0.2")
-	job.Setenv("ParentIP", "172.17.0.1")
-	job.SetenvBool("IgnoreErrors", false)
-	job.SetenvList("Ports", []string{"1234"})
-
 	bridgeIface = "lo"
 	bridgeIface = "lo"
-	_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
-	if err != nil {
+	if _, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	if res := LinkContainers(job); res != nil {
-		t.Fatalf("LinkContainers failed")
+	if err := LinkContainers("-I", "172.17.0.1", "172.17.0.2", []nat.Port{nat.Port("1234")}, false); err != nil {
+		t.Fatal("LinkContainers failed")
 	}
 	}
 
 
 	// flush rules
 	// flush rules
-	if _, err = iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
+	if _, err := iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 

+ 6 - 3
integration/utils_test.go

@@ -18,6 +18,7 @@ import (
 
 
 	"github.com/docker/docker/builtins"
 	"github.com/docker/docker/builtins"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/daemon"
+	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/engine"
 	flag "github.com/docker/docker/pkg/mflag"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/registry"
@@ -185,9 +186,11 @@ func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine {
 		ExecDriver:  "native",
 		ExecDriver:  "native",
 		// Either InterContainerCommunication or EnableIptables must be set,
 		// Either InterContainerCommunication or EnableIptables must be set,
 		// otherwise NewDaemon will fail because of conflicting settings.
 		// otherwise NewDaemon will fail because of conflicting settings.
-		InterContainerCommunication: true,
-		TrustKeyPath:                filepath.Join(root, "key.json"),
-		LogConfig:                   runconfig.LogConfig{Type: "json-file"},
+		Bridge: bridge.Config{
+			InterContainerCommunication: true,
+		},
+		TrustKeyPath: filepath.Join(root, "key.json"),
+		LogConfig:    runconfig.LogConfig{Type: "json-file"},
 	}
 	}
 	d, err := daemon.NewDaemon(cfg, eng, registry.NewService(nil))
 	d, err := daemon.NewDaemon(cfg, eng, registry.NewService(nil))
 	if err != nil {
 	if err != nil {

+ 5 - 19
links/links.go

@@ -2,10 +2,12 @@ package links
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/docker/docker/engine"
-	"github.com/docker/docker/nat"
 	"path"
 	"path"
 	"strings"
 	"strings"
+
+	"github.com/docker/docker/daemon/networkdriver/bridge"
+	"github.com/docker/docker/engine"
+	"github.com/docker/docker/nat"
 )
 )
 
 
 type Link struct {
 type Link struct {
@@ -158,21 +160,5 @@ func (l *Link) Disable() {
 }
 }
 
 
 func (l *Link) toggle(action string, ignoreErrors bool) error {
 func (l *Link) toggle(action string, ignoreErrors bool) error {
-	job := l.eng.Job("link", action)
-
-	job.Setenv("ParentIP", l.ParentIP)
-	job.Setenv("ChildIP", l.ChildIP)
-	job.SetenvBool("IgnoreErrors", ignoreErrors)
-
-	out := make([]string, len(l.Ports))
-	for i, p := range l.Ports {
-		out[i] = string(p)
-	}
-	job.SetenvList("Ports", out)
-
-	if err := job.Run(); err != nil {
-		// TODO: get ouput from job
-		return err
-	}
-	return nil
+	return bridge.LinkContainers(action, l.ParentIP, l.ChildIP, l.Ports, ignoreErrors)
 }
 }

+ 3 - 0
nat/nat.go

@@ -34,6 +34,9 @@ func NewPort(proto, port string) Port {
 }
 }
 
 
 func ParsePort(rawPort string) (int, error) {
 func ParsePort(rawPort string) (int, error) {
+	if len(rawPort) == 0 {
+		return 0, nil
+	}
 	port, err := strconv.ParseUint(rawPort, 10, 16)
 	port, err := strconv.ParseUint(rawPort, 10, 16)
 	if err != nil {
 	if err != nil {
 		return 0, err
 		return 0, err