瀏覽代碼

Merge pull request #51 from mrjana/cnm

Added driver specific config support
Madhu Venugopal 10 年之前
父節點
當前提交
82e75048c7

+ 11 - 3
libnetwork/README.md

@@ -22,10 +22,18 @@ There are many networking solutions available to suit a broad range of use-cases
 ```go
  // Create a new controller instance
  controller := libnetwork.New()
- 
- options := options.Generic{}
+
+ // This option is only needed for in-tree drivers. Plugins(in future) will get 
+ // their options through plugin infrastructure.
+ option := options.Generic{}
+ driver, err := controller.NewNetworkDriver("simplebridge", option)
+ if err != nil {
+    return
+ }
+
+ netOptions := options.Generic{}
  // Create a network for containers to join.
- network, err := controller.NewNetwork("simplebridge", "network1", options)
+ network, err := controller.NewNetwork(driver, "network1", netOptions)
  if err != nil {
     return
  }

+ 2 - 1
libnetwork/cmd/test/main.go

@@ -15,7 +15,8 @@ func main() {
 
 	options := options.Generic{"AddressIPv4": net}
 	controller := libnetwork.New()
-	netw, err := controller.NewNetwork("simplebridge", "dummy", options)
+	driver, _ := controller.NewNetworkDriver("simplebridge", options)
+	netw, err := controller.NewNetwork(driver, "dummy", "")
 	if err != nil {
 		log.Fatal(err)
 	}

+ 4 - 1
libnetwork/driverapi/driverapi.go

@@ -19,8 +19,11 @@ type UUID string
 
 // Driver is an interface that every plugin driver needs to implement.
 type Driver interface {
+	// Push driver specific config to the driver
+	Config(config interface{}) error
+
 	// CreateNetwork invokes the driver method to create a network passing
-	// the network id and driver specific config. The config mechanism will
+	// the network id and network specific config. The config mechanism will
 	// eventually be replaced with labels which are yet to be introduced.
 	CreateNetwork(nid UUID, config interface{}) error
 

+ 2 - 1
libnetwork/drivers.go

@@ -8,7 +8,8 @@ import (
 type driverTable map[string]driverapi.Driver
 
 func enumerateDrivers() driverTable {
-	var drivers driverTable
+	drivers := make(driverTable)
+
 	for _, fn := range [](func() (string, driverapi.Driver)){bridge.New} {
 		name, driver := fn()
 		drivers[name] = driver

+ 52 - 29
libnetwork/drivers/bridge/bridge.go

@@ -36,15 +36,16 @@ func initPortMapper() {
 
 // Configuration info for the "simplebridge" driver.
 type Configuration struct {
-	BridgeName         string
-	AddressIPv4        *net.IPNet
-	FixedCIDR          *net.IPNet
-	FixedCIDRv6        *net.IPNet
-	EnableIPv6         bool
-	EnableIPTables     bool
-	EnableIPMasquerade bool
-	EnableICC          bool
-	EnableIPForwarding bool
+	BridgeName            string
+	AddressIPv4           *net.IPNet
+	FixedCIDR             *net.IPNet
+	FixedCIDRv6           *net.IPNet
+	EnableIPv6            bool
+	EnableIPTables        bool
+	EnableIPMasquerade    bool
+	EnableICC             bool
+	EnableIPForwarding    bool
+	AllowNonDefaultBridge bool
 }
 
 type bridgeEndpoint struct {
@@ -62,6 +63,7 @@ type bridgeNetwork struct {
 }
 
 type driver struct {
+	config  *Configuration
 	network *bridgeNetwork
 	sync.Mutex
 }
@@ -76,15 +78,45 @@ func New() (string, driverapi.Driver) {
 	return networkType, &driver{}
 }
 
+func (d *driver) Config(option interface{}) error {
+	var config *Configuration
+
+	d.Lock()
+	defer d.Unlock()
+
+	if d.config != nil {
+		return fmt.Errorf("configuration already exists, simplebridge configuration can be applied only once")
+	}
+
+	switch opt := option.(type) {
+	case options.Generic:
+		opaqueConfig, err := options.GenerateFromModel(opt, &Configuration{})
+		if err != nil {
+			return fmt.Errorf("failed to generate driver config: %v", err)
+		}
+		config = opaqueConfig.(*Configuration)
+	case *Configuration:
+		config = opt
+	}
+
+	d.config = config
+	return nil
+}
+
 // Create a new network using simplebridge plugin
 func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error {
 
 	var (
-		config *Configuration
-		err    error
+		err error
 	)
 
 	d.Lock()
+	if d.config == nil {
+		d.Unlock()
+		return fmt.Errorf("trying to create a network on a driver without valid config")
+	}
+	config := d.config
+
 	if d.network != nil {
 		d.Unlock()
 		return fmt.Errorf("network already exists, simplebridge can only have one network")
@@ -100,19 +132,8 @@ func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error {
 		}
 	}()
 
-	switch opt := option.(type) {
-	case options.Generic:
-		opaqueConfig, err := options.GenerateFromModel(opt, &Configuration{})
-		if err != nil {
-			return fmt.Errorf("failed to generate driver config: %v", err)
-		}
-		config = opaqueConfig.(*Configuration)
-	case *Configuration:
-		config = opt
-	}
-
 	bridgeIface := newInterface(config)
-	bridgeSetup := newBridgeSetup(bridgeIface)
+	bridgeSetup := newBridgeSetup(config, bridgeIface)
 
 	// If the bridge interface doesn't exist, we need to start the setup steps
 	// by creating a new device and assigning it an IPv4 address.
@@ -199,7 +220,7 @@ func (d *driver) DeleteNetwork(nid driverapi.UUID) error {
 	return err
 }
 
-func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, config interface{}) (*driverapi.SandboxInfo, error) {
+func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOption interface{}) (*driverapi.SandboxInfo, error) {
 	var (
 		ipv6Addr net.IPNet
 		err      error
@@ -207,6 +228,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, config
 
 	d.Lock()
 	n := d.network
+	config := d.config
 	d.Unlock()
 	if n == nil {
 		return nil, driverapi.ErrNoNetwork
@@ -271,7 +293,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, config
 	}()
 
 	if err = netlink.LinkSetMaster(host,
-		&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: n.bridge.Config.BridgeName}}); err != nil {
+		&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil {
 		return nil, err
 	}
 
@@ -281,7 +303,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, config
 	}
 	ipv4Addr := net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
 
-	if n.bridge.Config.EnableIPv6 {
+	if config.EnableIPv6 {
 		ip6, err := ipAllocator.RequestIP(n.bridge.bridgeIPv6, nil)
 		if err != nil {
 			return nil, err
@@ -297,7 +319,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, config
 	intf.DstName = containerVeth
 	intf.Address = ipv4Addr
 	sinfo.Gateway = n.bridge.bridgeIPv4.IP
-	if n.bridge.Config.EnableIPv6 {
+	if config.EnableIPv6 {
 		intf.AddressIPv6 = ipv6Addr
 		sinfo.GatewayIPv6 = n.bridge.bridgeIPv6.IP
 	}
@@ -314,6 +336,7 @@ func (d *driver) DeleteEndpoint(nid, eid driverapi.UUID) error {
 
 	d.Lock()
 	n := d.network
+	config := d.config
 	d.Unlock()
 	if n == nil {
 		return driverapi.ErrNoNetwork
@@ -356,8 +379,8 @@ func (d *driver) DeleteEndpoint(nid, eid driverapi.UUID) error {
 		return err
 	}
 
-	if n.bridge.Config.EnableIPv6 {
-		err := ipAllocator.ReleaseIP(n.bridge.bridgeIPv6, n.endpoint.addressIPv6)
+	if config.EnableIPv6 {
+		err := ipAllocator.ReleaseIP(n.bridge.bridgeIPv6, ep.addressIPv6)
 		if err != nil {
 			return err
 		}

+ 14 - 4
libnetwork/drivers/bridge/bridge_test.go

@@ -12,8 +12,11 @@ func TestCreate(t *testing.T) {
 	_, d := New()
 
 	config := &Configuration{BridgeName: DefaultBridgeName}
-	err := d.CreateNetwork("dummy", config)
-	if err != nil {
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
+
+	if err := d.CreateNetwork("dummy", ""); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 }
@@ -23,7 +26,11 @@ func TestCreateFail(t *testing.T) {
 	_, d := New()
 
 	config := &Configuration{BridgeName: "dummy0"}
-	if err := d.CreateNetwork("dummy", config); err == nil {
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
+
+	if err := d.CreateNetwork("dummy", ""); err == nil {
 		t.Fatal("Bridge creation was expected to fail")
 	}
 }
@@ -40,8 +47,11 @@ func TestCreateFullOptions(t *testing.T) {
 		EnableIPForwarding: true,
 	}
 	_, config.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
 
-	err := d.CreateNetwork("dummy", config)
+	err := d.CreateNetwork("dummy", "")
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 	}

+ 4 - 7
libnetwork/drivers/bridge/interface.go

@@ -14,7 +14,6 @@ const (
 
 // Interface models the bridge network device.
 type bridgeInterface struct {
-	Config     *Configuration
 	Link       netlink.Link
 	bridgeIPv4 *net.IPNet
 	bridgeIPv6 *net.IPNet
@@ -25,17 +24,15 @@ type bridgeInterface struct {
 // or the default bridge name when unspecified), but doesn't attempt to create
 // on when missing
 func newInterface(config *Configuration) *bridgeInterface {
-	i := &bridgeInterface{
-		Config: config,
-	}
+	i := &bridgeInterface{}
 
 	// Initialize the bridge name to the default if unspecified.
-	if i.Config.BridgeName == "" {
-		i.Config.BridgeName = DefaultBridgeName
+	if config.BridgeName == "" {
+		config.BridgeName = DefaultBridgeName
 	}
 
 	// Attempt to find an existing bridge named with the specified name.
-	i.Link, _ = netlink.LinkByName(i.Config.BridgeName)
+	i.Link, _ = netlink.LinkByName(config.BridgeName)
 	return i
 }
 

+ 3 - 2
libnetwork/drivers/bridge/interface_test.go

@@ -10,8 +10,9 @@ import (
 func TestInterfaceDefaultName(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	if inf := newInterface(&Configuration{}); inf.Config.BridgeName != DefaultBridgeName {
-		t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, inf.Config.BridgeName)
+	config := &Configuration{}
+	if _ = newInterface(config); config.BridgeName != DefaultBridgeName {
+		t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, config.BridgeName)
 	}
 }
 

+ 15 - 3
libnetwork/drivers/bridge/network_test.go

@@ -16,7 +16,11 @@ func TestLinkCreate(t *testing.T) {
 	config := &Configuration{
 		BridgeName: DefaultBridgeName,
 		EnableIPv6: true}
-	err := d.CreateNetwork("dummy", config)
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
+
+	err := d.CreateNetwork("dummy", "")
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
@@ -69,7 +73,11 @@ func TestLinkCreateTwo(t *testing.T) {
 	config := &Configuration{
 		BridgeName: DefaultBridgeName,
 		EnableIPv6: true}
-	err := d.CreateNetwork("dummy", config)
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
+
+	err := d.CreateNetwork("dummy", "")
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
@@ -95,7 +103,11 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
 
 	config := &Configuration{
 		BridgeName: DefaultBridgeName}
-	err := d.CreateNetwork("dummy", config)
+	if err := d.Config(config); err != nil {
+		t.Fatalf("Failed to setup driver config: %v", err)
+	}
+
+	err := d.CreateNetwork("dummy", "")
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 	}

+ 5 - 4
libnetwork/drivers/bridge/setup.go

@@ -1,19 +1,20 @@
 package bridge
 
-type setupStep func(*bridgeInterface) error
+type setupStep func(*Configuration, *bridgeInterface) error
 
 type bridgeSetup struct {
+	config *Configuration
 	bridge *bridgeInterface
 	steps  []setupStep
 }
 
-func newBridgeSetup(i *bridgeInterface) *bridgeSetup {
-	return &bridgeSetup{bridge: i}
+func newBridgeSetup(c *Configuration, i *bridgeInterface) *bridgeSetup {
+	return &bridgeSetup{config: c, bridge: i}
 }
 
 func (b *bridgeSetup) apply() error {
 	for _, fn := range b.steps {
-		if err := fn(b.bridge); err != nil {
+		if err := fn(b.config, b.bridge); err != nil {
 			return err
 		}
 	}

+ 6 - 6
libnetwork/drivers/bridge/setup_device.go

@@ -10,17 +10,17 @@ import (
 )
 
 // SetupDevice create a new bridge interface/
-func setupDevice(i *bridgeInterface) error {
+func setupDevice(config *Configuration, i *bridgeInterface) error {
 	// We only attempt to create the bridge when the requested device name is
 	// the default one.
-	if i.Config.BridgeName != DefaultBridgeName {
-		return fmt.Errorf("bridge device with non default name %q must be created manually", i.Config.BridgeName)
+	if config.BridgeName != DefaultBridgeName && !config.AllowNonDefaultBridge {
+		return fmt.Errorf("bridge device with non default name %q must be created manually", config.BridgeName)
 	}
 
 	// Set the bridgeInterface netlink.Bridge.
 	i.Link = &netlink.Bridge{
 		LinkAttrs: netlink.LinkAttrs{
-			Name: i.Config.BridgeName,
+			Name: config.BridgeName,
 		},
 	}
 
@@ -37,7 +37,7 @@ func setupDevice(i *bridgeInterface) error {
 }
 
 // SetupDeviceUp ups the given bridge interface.
-func setupDeviceUp(i *bridgeInterface) error {
+func setupDeviceUp(config *Configuration, i *bridgeInterface) error {
 	err := netlink.LinkSetUp(i.Link)
 	if err != nil {
 		return err
@@ -45,7 +45,7 @@ func setupDeviceUp(i *bridgeInterface) error {
 
 	// Attempt to update the bridge interface to refresh the flags status,
 	// ignoring any failure to do so.
-	if lnk, err := netlink.LinkByName(i.Config.BridgeName); err == nil {
+	if lnk, err := netlink.LinkByName(config.BridgeName); err == nil {
 		i.Link = lnk
 	}
 	return nil

+ 13 - 19
libnetwork/drivers/bridge/setup_device_test.go

@@ -13,12 +13,10 @@ import (
 func TestSetupNewBridge(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName: DefaultBridgeName,
-		},
-	}
-	if err := setupDevice(br); err != nil {
+	config := &Configuration{BridgeName: DefaultBridgeName}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
 	if br.Link == nil {
@@ -35,12 +33,10 @@ func TestSetupNewBridge(t *testing.T) {
 func TestSetupNewNonDefaultBridge(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName: "test0",
-		},
-	}
-	if err := setupDevice(br); err == nil || !strings.Contains(err.Error(), "non default name") {
+	config := &Configuration{BridgeName: "test0"}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err == nil || !strings.Contains(err.Error(), "non default name") {
 		t.Fatalf("Expected bridge creation failure with \"non default name\", got: %v", err)
 	}
 }
@@ -48,15 +44,13 @@ func TestSetupNewNonDefaultBridge(t *testing.T) {
 func TestSetupDeviceUp(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName: DefaultBridgeName,
-		},
-	}
-	if err := setupDevice(br); err != nil {
+	config := &Configuration{BridgeName: DefaultBridgeName}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
-	if err := setupDeviceUp(br); err != nil {
+	if err := setupDeviceUp(config, br); err != nil {
 		t.Fatalf("Failed to up bridge device: %v", err)
 	}
 

+ 4 - 4
libnetwork/drivers/bridge/setup_fixedcidrv4.go

@@ -6,15 +6,15 @@ import (
 	log "github.com/Sirupsen/logrus"
 )
 
-func setupFixedCIDRv4(i *bridgeInterface) error {
+func setupFixedCIDRv4(config *Configuration, i *bridgeInterface) error {
 	addrv4, _, err := i.addresses()
 	if err != nil {
 		return err
 	}
 
-	log.Debugf("Using IPv4 subnet: %v", i.Config.FixedCIDR)
-	if err := ipAllocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR); err != nil {
-		return fmt.Errorf("Setup FixedCIDRv4 failed for subnet %s in %s: %v", i.Config.FixedCIDR, addrv4.IPNet, err)
+	log.Debugf("Using IPv4 subnet: %v", config.FixedCIDR)
+	if err := ipAllocator.RegisterSubnet(addrv4.IPNet, config.FixedCIDR); err != nil {
+		return fmt.Errorf("Setup FixedCIDRv4 failed for subnet %s in %s: %v", config.FixedCIDR, addrv4.IPNet, err)
 	}
 
 	return nil

+ 19 - 21
libnetwork/drivers/bridge/setup_fixedcidrv4_test.go

@@ -10,25 +10,24 @@ import (
 func TestSetupFixedCIDRv4(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName:  DefaultBridgeName,
-			AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(16, 32)},
-			FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
-		},
-	}
-	if err := setupDevice(br); err != nil {
+	config := &Configuration{
+		BridgeName:  DefaultBridgeName,
+		AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(16, 32)},
+		FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)}}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
-	if err := setupBridgeIPv4(br); err != nil {
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
 	}
 
-	if err := setupFixedCIDRv4(br); err != nil {
+	if err := setupFixedCIDRv4(config, br); err != nil {
 		t.Fatalf("Failed to setup bridge FixedCIDRv4: %v", err)
 	}
 
-	if ip, err := ipAllocator.RequestIP(br.Config.FixedCIDR, nil); err != nil {
+	if ip, err := ipAllocator.RequestIP(config.FixedCIDR, nil); err != nil {
 		t.Fatalf("Failed to request IP to allocator: %v", err)
 	} else if expected := "192.168.2.1"; ip.String() != expected {
 		t.Fatalf("Expected allocated IP %s, got %s", expected, ip)
@@ -38,21 +37,20 @@ func TestSetupFixedCIDRv4(t *testing.T) {
 func TestSetupBadFixedCIDRv4(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName:  DefaultBridgeName,
-			AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(24, 32)},
-			FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)},
-		},
-	}
-	if err := setupDevice(br); err != nil {
+	config := &Configuration{
+		BridgeName:  DefaultBridgeName,
+		AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(24, 32)},
+		FixedCIDR:   &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)}}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
-	if err := setupBridgeIPv4(br); err != nil {
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
 	}
 
-	if err := setupFixedCIDRv4(br); err == nil {
+	if err := setupFixedCIDRv4(config, br); err == nil {
 		t.Fatal("Setup bridge FixedCIDRv4 should have failed")
 	}
 }

+ 4 - 4
libnetwork/drivers/bridge/setup_fixedcidrv6.go

@@ -6,10 +6,10 @@ import (
 	log "github.com/Sirupsen/logrus"
 )
 
-func setupFixedCIDRv6(i *bridgeInterface) error {
-	log.Debugf("Using IPv6 subnet: %v", i.Config.FixedCIDRv6)
-	if err := ipAllocator.RegisterSubnet(i.Config.FixedCIDRv6, i.Config.FixedCIDRv6); err != nil {
-		return fmt.Errorf("Setup FixedCIDRv6 failed for subnet %s in %s: %v", i.Config.FixedCIDRv6, i.Config.FixedCIDRv6, err)
+func setupFixedCIDRv6(config *Configuration, i *bridgeInterface) error {
+	log.Debugf("Using IPv6 subnet: %v", config.FixedCIDRv6)
+	if err := ipAllocator.RegisterSubnet(config.FixedCIDRv6, config.FixedCIDRv6); err != nil {
+		return fmt.Errorf("Setup FixedCIDRv6 failed for subnet %s in %s: %v", config.FixedCIDRv6, config.FixedCIDRv6, err)
 	}
 
 	return nil

+ 8 - 7
libnetwork/drivers/bridge/setup_fixedcidrv6_test.go

@@ -10,25 +10,26 @@ import (
 func TestSetupFixedCIDRv6(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := newInterface(&Configuration{})
+	config := &Configuration{}
+	br := newInterface(config)
 
-	_, br.Config.FixedCIDRv6, _ = net.ParseCIDR("2002:db8::/48")
-	if err := setupDevice(br); err != nil {
+	_, config.FixedCIDRv6, _ = net.ParseCIDR("2002:db8::/48")
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
-	if err := setupBridgeIPv4(br); err != nil {
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
 	}
 
-	if err := setupBridgeIPv6(br); err != nil {
+	if err := setupBridgeIPv6(config, br); err != nil {
 		t.Fatalf("Assign IPv4 to bridge failed: %v", err)
 	}
 
-	if err := setupFixedCIDRv6(br); err != nil {
+	if err := setupFixedCIDRv6(config, br); err != nil {
 		t.Fatalf("Failed to setup bridge FixedCIDRv6: %v", err)
 	}
 
-	if ip, err := ipAllocator.RequestIP(br.Config.FixedCIDRv6, nil); err != nil {
+	if ip, err := ipAllocator.RequestIP(config.FixedCIDRv6, nil); err != nil {
 		t.Fatalf("Failed to request IP to allocator: %v", err)
 	} else if expected := "2002:db8::1"; ip.String() != expected {
 		t.Fatalf("Expected allocated IP %s, got %s", expected, ip)

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

@@ -10,9 +10,9 @@ const (
 	ipv4ForwardConfPerm = 0644
 )
 
-func setupIPForwarding(i *bridgeInterface) error {
+func setupIPForwarding(config *Configuration, i *bridgeInterface) error {
 	// Sanity Check
-	if i.Config.EnableIPForwarding == false {
+	if config.EnableIPForwarding == false {
 		return fmt.Errorf("Unexpected request to enable IP Forwarding for: %v", *i)
 	}
 

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

@@ -18,15 +18,13 @@ func TestSetupIPForwarding(t *testing.T) {
 	}
 
 	// Create test interface with ip forwarding setting enabled
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName:         DefaultBridgeName,
-			EnableIPForwarding: true,
-		},
-	}
+	config := &Configuration{
+		BridgeName:         DefaultBridgeName,
+		EnableIPForwarding: true}
+	br := &bridgeInterface{}
 
 	// Set IP Forwarding
-	if err := setupIPForwarding(br); err != nil {
+	if err := setupIPForwarding(config, br); err != nil {
 		t.Fatalf("Failed to setup IP forwarding: %v", err)
 	}
 
@@ -43,15 +41,13 @@ func TestUnexpectedSetupIPForwarding(t *testing.T) {
 	defer reconcileIPForwardingSetting(t, procSetting)
 
 	// Create test interface without ip forwarding setting enabled
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName:         DefaultBridgeName,
-			EnableIPForwarding: false,
-		},
-	}
+	config := &Configuration{
+		BridgeName:         DefaultBridgeName,
+		EnableIPForwarding: false}
+	br := &bridgeInterface{}
 
 	// Attempt Set IP Forwarding
-	if err := setupIPForwarding(br); err == nil {
+	if err := setupIPForwarding(config, br); err == nil {
 		t.Fatal("Setup IP forwarding was expected to fail")
 	} else if !strings.Contains(err.Error(), "Unexpected request") {
 		t.Fatalf("Setup IP forwarding failed with unexpected error: %v", err)

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

@@ -13,26 +13,26 @@ const (
 	DockerChain = "DOCKER"
 )
 
-func setupIPTables(i *bridgeInterface) error {
+func setupIPTables(config *Configuration, i *bridgeInterface) error {
 	// Sanity check.
-	if i.Config.EnableIPTables == false {
-		return fmt.Errorf("Unexpected request to set IP tables for interface: %s", i.Config.BridgeName)
+	if config.EnableIPTables == false {
+		return fmt.Errorf("Unexpected request to set IP tables for interface: %s", config.BridgeName)
 	}
 
-	addrv4, _, err := netutils.GetIfaceAddr(i.Config.BridgeName)
+	addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
 	if err != nil {
 		return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
 	}
-	if err = setupIPTablesInternal(i.Config.BridgeName, addrv4, i.Config.EnableICC, i.Config.EnableIPMasquerade, true); err != nil {
+	if err = setupIPTablesInternal(config.BridgeName, addrv4, config.EnableICC, config.EnableIPMasquerade, true); err != nil {
 		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
 	}
 
-	_, err = iptables.NewChain(DockerChain, i.Config.BridgeName, iptables.Nat)
+	_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat)
 	if err != nil {
 		return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
 	}
 
-	chain, err := iptables.NewChain(DockerChain, i.Config.BridgeName, iptables.Filter)
+	chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter)
 	if err != nil {
 		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
 	}

+ 23 - 23
libnetwork/drivers/bridge/setup_ip_tables_test.go

@@ -15,7 +15,7 @@ const (
 func TestProgramIPTable(t *testing.T) {
 	// Create a test bridge with a basic bridge configuration (name + IPv4).
 	defer netutils.SetupTestNetNS(t)()
-	createTestBridge(getBasicTestConfig(), t)
+	createTestBridge(getBasicTestConfig(), &bridgeInterface{}, t)
 
 	// Store various iptables chain rules we care for.
 	rules := []struct {
@@ -39,37 +39,37 @@ func TestProgramIPTable(t *testing.T) {
 func TestSetupIPTables(t *testing.T) {
 	// Create a test bridge with a basic bridge configuration (name + IPv4).
 	defer netutils.SetupTestNetNS(t)()
-	br := getBasicTestConfig()
-	createTestBridge(br, t)
+	config := getBasicTestConfig()
+	br := &bridgeInterface{}
+
+	createTestBridge(config, br, t)
 
 	// Modify iptables params in base configuration and apply them.
-	br.Config.EnableIPTables = true
-	assertBridgeConfig(br, t)
+	config.EnableIPTables = true
+	assertBridgeConfig(config, br, t)
 
-	br.Config.EnableIPMasquerade = true
-	assertBridgeConfig(br, t)
+	config.EnableIPMasquerade = true
+	assertBridgeConfig(config, br, t)
 
-	br.Config.EnableICC = true
-	assertBridgeConfig(br, t)
+	config.EnableICC = true
+	assertBridgeConfig(config, br, t)
 
-	br.Config.EnableIPMasquerade = false
-	assertBridgeConfig(br, t)
+	config.EnableIPMasquerade = false
+	assertBridgeConfig(config, br, t)
 }
 
-func getBasicTestConfig() *bridgeInterface {
-	return &bridgeInterface{
-		Config: &Configuration{
-			BridgeName:  DefaultBridgeName,
-			AddressIPv4: &net.IPNet{IP: net.ParseIP(iptablesTestBridgeIP), Mask: net.CIDRMask(16, 32)},
-		},
-	}
+func getBasicTestConfig() *Configuration {
+	config := &Configuration{
+		BridgeName:  DefaultBridgeName,
+		AddressIPv4: &net.IPNet{IP: net.ParseIP(iptablesTestBridgeIP), Mask: net.CIDRMask(16, 32)}}
+	return config
 }
 
-func createTestBridge(br *bridgeInterface, t *testing.T) {
-	if err := setupDevice(br); err != nil {
+func createTestBridge(config *Configuration, br *bridgeInterface, t *testing.T) {
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Failed to create the testing Bridge: %s", err.Error())
 	}
-	if err := setupBridgeIPv4(br); err != nil {
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Failed to bring up the testing Bridge: %s", err.Error())
 	}
 }
@@ -94,9 +94,9 @@ func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
 }
 
 // Assert function which pushes chains based on bridge config parameters.
-func assertBridgeConfig(br *bridgeInterface, t *testing.T) {
+func assertBridgeConfig(config *Configuration, br *bridgeInterface, t *testing.T) {
 	// Attempt programming of ip tables.
-	err := setupIPTables(br)
+	err := setupIPTables(config, br)
 	if err != nil {
 		t.Fatalf("%v", err)
 	}

+ 3 - 3
libnetwork/drivers/bridge/setup_ipv4.go

@@ -41,13 +41,13 @@ func init() {
 	}
 }
 
-func setupBridgeIPv4(i *bridgeInterface) error {
-	bridgeIPv4, err := electBridgeIPv4(i.Config)
+func setupBridgeIPv4(config *Configuration, i *bridgeInterface) error {
+	bridgeIPv4, err := electBridgeIPv4(config)
 	if err != nil {
 		return err
 	}
 
-	log.Debugf("Creating bridge interface %q with network %s", i.Config.BridgeName, bridgeIPv4)
+	log.Debugf("Creating bridge interface %q with network %s", config.BridgeName, bridgeIPv4)
 	if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: bridgeIPv4}); err != nil {
 		return fmt.Errorf("Failed to add IPv4 address %s to bridge: %v", bridgeIPv4, err)
 	}

+ 14 - 15
libnetwork/drivers/bridge/setup_ipv4_test.go

@@ -8,16 +8,15 @@ import (
 	"github.com/vishvananda/netlink"
 )
 
-func setupTestInterface(t *testing.T) *bridgeInterface {
-	br := &bridgeInterface{
-		Config: &Configuration{
-			BridgeName: DefaultBridgeName,
-		},
-	}
-	if err := setupDevice(br); err != nil {
+func setupTestInterface(t *testing.T) (*Configuration, *bridgeInterface) {
+	config := &Configuration{
+		BridgeName: DefaultBridgeName}
+	br := &bridgeInterface{}
+
+	if err := setupDevice(config, br); err != nil {
 		t.Fatalf("Bridge creation failed: %v", err)
 	}
-	return br
+	return config, br
 }
 
 func TestSetupBridgeIPv4Fixed(t *testing.T) {
@@ -28,9 +27,9 @@ func TestSetupBridgeIPv4Fixed(t *testing.T) {
 		t.Fatalf("Failed to parse bridge IPv4: %v", err)
 	}
 
-	br := setupTestInterface(t)
-	br.Config.AddressIPv4 = &net.IPNet{IP: ip, Mask: netw.Mask}
-	if err := setupBridgeIPv4(br); err != nil {
+	config, br := setupTestInterface(t)
+	config.AddressIPv4 = &net.IPNet{IP: ip, Mask: netw.Mask}
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Failed to setup bridge IPv4: %v", err)
 	}
 
@@ -41,22 +40,22 @@ func TestSetupBridgeIPv4Fixed(t *testing.T) {
 
 	var found bool
 	for _, addr := range addrsv4 {
-		if br.Config.AddressIPv4.String() == addr.IPNet.String() {
+		if config.AddressIPv4.String() == addr.IPNet.String() {
 			found = true
 			break
 		}
 	}
 
 	if !found {
-		t.Fatalf("Bridge device does not have requested IPv4 address %v", br.Config.AddressIPv4)
+		t.Fatalf("Bridge device does not have requested IPv4 address %v", config.AddressIPv4)
 	}
 }
 
 func TestSetupBridgeIPv4Auto(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := setupTestInterface(t)
-	if err := setupBridgeIPv4(br); err != nil {
+	config, br := setupTestInterface(t)
+	if err := setupBridgeIPv4(config, br); err != nil {
 		t.Fatalf("Failed to setup bridge IPv4: %v", err)
 	}
 

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

@@ -22,9 +22,9 @@ func init() {
 	}
 }
 
-func setupBridgeIPv6(i *bridgeInterface) error {
+func setupBridgeIPv6(config *Configuration, i *bridgeInterface) error {
 	// Enable IPv6 on the bridge
-	procFile := "/proc/sys/net/ipv6/conf/" + i.Config.BridgeName + "/disable_ipv6"
+	procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
 	if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
 		return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
 	}

+ 3 - 3
libnetwork/drivers/bridge/setup_ipv6_test.go

@@ -13,12 +13,12 @@ import (
 func TestSetupIPv6(t *testing.T) {
 	defer netutils.SetupTestNetNS(t)()
 
-	br := setupTestInterface(t)
-	if err := setupBridgeIPv6(br); err != nil {
+	config, br := setupTestInterface(t)
+	if err := setupBridgeIPv6(config, br); err != nil {
 		t.Fatalf("Failed to setup bridge IPv6: %v", err)
 	}
 
-	procSetting, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", br.Config.BridgeName))
+	procSetting, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", config.BridgeName))
 	if err != nil {
 		t.Fatalf("Failed to read disable_ipv6 kernel setting: %v", err)
 	}

+ 4 - 4
libnetwork/drivers/bridge/setup_verify.go

@@ -6,7 +6,7 @@ import (
 	"github.com/vishvananda/netlink"
 )
 
-func setupVerifyConfiguredAddresses(i *bridgeInterface) error {
+func setupVerifyConfiguredAddresses(config *Configuration, i *bridgeInterface) error {
 	// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
 	addrv4, addrsv6, err := i.addresses()
 	if err != nil {
@@ -19,13 +19,13 @@ func setupVerifyConfiguredAddresses(i *bridgeInterface) error {
 	}
 
 	// Verify that the bridge IPv4 address matches the requested configuration.
-	if i.Config.AddressIPv4 != nil && !addrv4.IP.Equal(i.Config.AddressIPv4.IP) {
-		return fmt.Errorf("Bridge IPv4 (%s) does not match requested configuration %s", addrv4.IP, i.Config.AddressIPv4.IP)
+	if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
+		return fmt.Errorf("Bridge IPv4 (%s) does not match requested configuration %s", addrv4.IP, config.AddressIPv4.IP)
 	}
 
 	// Verify that one of the bridge IPv6 addresses matches the requested
 	// configuration.
-	if i.Config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
+	if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
 		return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", bridgeIPv6)
 	}
 

+ 24 - 19
libnetwork/drivers/bridge/setup_verify_test.go

@@ -9,7 +9,7 @@ import (
 )
 
 func setupVerifyTest(t *testing.T) *bridgeInterface {
-	inf := &bridgeInterface{Config: &Configuration{}}
+	inf := &bridgeInterface{}
 
 	br := netlink.Bridge{}
 	br.LinkAttrs.Name = "default0"
@@ -27,13 +27,14 @@ func TestSetupVerify(t *testing.T) {
 
 	addrv4 := net.IPv4(192, 168, 1, 1)
 	inf := setupVerifyTest(t)
-	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	config := &Configuration{}
+	config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
 
-	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
-		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
 	}
 
-	if err := setupVerifyConfiguredAddresses(inf); err != nil {
+	if err := setupVerifyConfiguredAddresses(config, inf); err != nil {
 		t.Fatalf("Address verification failed: %v", err)
 	}
 }
@@ -43,14 +44,15 @@ func TestSetupVerifyBad(t *testing.T) {
 
 	addrv4 := net.IPv4(192, 168, 1, 1)
 	inf := setupVerifyTest(t)
-	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	config := &Configuration{}
+	config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
 
 	ipnet := &net.IPNet{IP: net.IPv4(192, 168, 1, 2), Mask: addrv4.DefaultMask()}
 	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: ipnet}); err != nil {
 		t.Fatalf("Failed to assign IPv4 %s to interface: %v", ipnet, err)
 	}
 
-	if err := setupVerifyConfiguredAddresses(inf); err == nil {
+	if err := setupVerifyConfiguredAddresses(config, inf); err == nil {
 		t.Fatal("Address verification was expected to fail")
 	}
 }
@@ -60,9 +62,10 @@ func TestSetupVerifyMissing(t *testing.T) {
 
 	addrv4 := net.IPv4(192, 168, 1, 1)
 	inf := setupVerifyTest(t)
-	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	config := &Configuration{}
+	config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
 
-	if err := setupVerifyConfiguredAddresses(inf); err == nil {
+	if err := setupVerifyConfiguredAddresses(config, inf); err == nil {
 		t.Fatal("Address verification was expected to fail")
 	}
 }
@@ -72,17 +75,18 @@ func TestSetupVerifyIPv6(t *testing.T) {
 
 	addrv4 := net.IPv4(192, 168, 1, 1)
 	inf := setupVerifyTest(t)
-	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
-	inf.Config.EnableIPv6 = true
+	config := &Configuration{}
+	config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	config.EnableIPv6 = true
 
 	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: bridgeIPv6}); err != nil {
 		t.Fatalf("Failed to assign IPv6 %s to interface: %v", bridgeIPv6, err)
 	}
-	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
-		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
 	}
 
-	if err := setupVerifyConfiguredAddresses(inf); err != nil {
+	if err := setupVerifyConfiguredAddresses(config, inf); err != nil {
 		t.Fatalf("Address verification failed: %v", err)
 	}
 }
@@ -92,14 +96,15 @@ func TestSetupVerifyIPv6Missing(t *testing.T) {
 
 	addrv4 := net.IPv4(192, 168, 1, 1)
 	inf := setupVerifyTest(t)
-	inf.Config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
-	inf.Config.EnableIPv6 = true
+	config := &Configuration{}
+	config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
+	config.EnableIPv6 = true
 
-	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: inf.Config.AddressIPv4}); err != nil {
-		t.Fatalf("Failed to assign IPv4 %s to interface: %v", inf.Config.AddressIPv4, err)
+	if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
+		t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
 	}
 
-	if err := setupVerifyConfiguredAddresses(inf); err == nil {
+	if err := setupVerifyConfiguredAddresses(config, inf); err == nil {
 		t.Fatal("Address verification was expected to fail")
 	}
 }

+ 26 - 17
libnetwork/libnetwork_test.go

@@ -1,7 +1,6 @@
 package libnetwork_test
 
 import (
-	"flag"
 	"net"
 	"testing"
 
@@ -12,14 +11,9 @@ import (
 	"github.com/vishvananda/netlink"
 )
 
-var bridgeName = "docker0"
-var enableBridgeTest = flag.Bool("enable-bridge-test", false, "")
+var bridgeName = "dockertest0"
 
 func TestSimplebridge(t *testing.T) {
-	if *enableBridgeTest == false {
-		t.Skip()
-	}
-
 	bridge := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}}
 	netlink.LinkDel(bridge)
 
@@ -43,23 +37,38 @@ func TestSimplebridge(t *testing.T) {
 
 	log.Debug("Adding a simple bridge")
 	options := options.Generic{
-		"BridgeName":         bridgeName,
-		"AddressIPv4":        subnet,
-		"FixedCIDR":          cidr,
-		"FixedCIDRv6":        cidrv6,
-		"EnableIPv6":         true,
-		"EnableIPTables":     true,
-		"EnableIPMasquerade": true,
-		"EnableICC":          true,
-		"EnableIPForwarding": true}
+		"BridgeName":            bridgeName,
+		"AddressIPv4":           subnet,
+		"FixedCIDR":             cidr,
+		"FixedCIDRv6":           cidrv6,
+		"EnableIPv6":            true,
+		"EnableIPTables":        true,
+		"EnableIPMasquerade":    true,
+		"EnableICC":             true,
+		"EnableIPForwarding":    true,
+		"AllowNonDefaultBridge": true}
 
 	controller := libnetwork.New()
 
-	network, err := controller.NewNetwork("simplebridge", "dummy", options)
+	driver, err := controller.NewNetworkDriver("simplebridge", options)
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	network, err := controller.NewNetwork(driver, "testnetwork", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	ep, _, err := network.CreateEndpoint("testep", "", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := ep.Delete(); err != nil {
+		t.Fatal(err)
+	}
+
 	if err := network.Delete(); err != nil {
 		t.Fatal(err)
 	}

+ 49 - 29
libnetwork/network.go

@@ -5,9 +5,17 @@ create network namespaces and allocate interfaces for containers to use.
 // Create a new controller instance
 controller := libnetwork.New()
 
-options := options.Generic{}
+// This option is only needed for in-tree drivers. Plugins(in future) will get
+// their options through plugin infrastructure.
+option := options.Generic{}
+driver, err := controller.NewNetworkDriver("simplebridge", option)
+if err != nil {
+        return
+}
+
+netOptions := options.Generic{}
 // Create a network for containers to join.
-network, err := controller.NewNetwork("simplebridge", "network1", options)
+network, err := controller.NewNetwork(driver, "network1", netOptions)
 if err != nil {
 	return
 }
@@ -53,13 +61,14 @@ import (
 // NetworkController provides the interface for controller instance which manages
 // networks.
 type NetworkController interface {
+	NewNetworkDriver(networkType string, options interface{}) (*NetworkDriver, error)
 	// Create a new network. The options parameter carry driver specific options.
 	// Labels support will be added in the near future.
-	NewNetwork(networkType, name string, options interface{}) (Network, error)
+	NewNetwork(d *NetworkDriver, name string, options interface{}) (Network, error)
 }
 
 // A Network represents a logical connectivity zone that containers may
-// ulteriorly join using the Link method. A Network is managed by a specific
+// ulteriorly join using the CreateEndpoint method. A Network is managed by a specific
 // driver.
 type Network interface {
 	// A user chosen name for this network.
@@ -86,6 +95,11 @@ type Endpoint interface {
 	Delete() error
 }
 
+// NetworkDriver provides a reference to driver and way to push driver specific config
+type NetworkDriver struct {
+	internalDriver driverapi.Driver
+}
+
 type endpoint struct {
 	name        string
 	id          driverapi.UUID
@@ -98,11 +112,13 @@ type network struct {
 	name        string
 	networkType string
 	id          driverapi.UUID
-	endpoints   map[driverapi.UUID]*endpoint
+	driver      *NetworkDriver
+	endpoints   endpointTable
 	sync.Mutex
 }
 
 type networkTable map[driverapi.UUID]*network
+type endpointTable map[driverapi.UUID]*endpoint
 
 type controller struct {
 	networks networkTable
@@ -115,18 +131,34 @@ func New() NetworkController {
 	return &controller{networkTable{}, enumerateDrivers(), sync.Mutex{}}
 }
 
-// NewNetwork creates a new network of the specified networkType. The options
-// are driver specific and modeled in a generic way.
-func (c *controller) NewNetwork(networkType, name string, options interface{}) (Network, error) {
-	network := &network{name: name, networkType: networkType}
-	network.id = driverapi.UUID(common.GenerateRandomID())
-	network.ctrlr = c
-
+func (c *controller) NewNetworkDriver(networkType string, options interface{}) (*NetworkDriver, error) {
 	d, ok := c.drivers[networkType]
 	if !ok {
 		return nil, fmt.Errorf("unknown driver %q", networkType)
 	}
 
+	if err := d.Config(options); err != nil {
+		return nil, err
+	}
+
+	return &NetworkDriver{internalDriver: d}, nil
+}
+
+// NewNetwork creates a new network of the specified networkType. The options
+// are driver specific and modeled in a generic way.
+func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interface{}) (Network, error) {
+	network := &network{
+		name:   name,
+		id:     driverapi.UUID(common.GenerateRandomID()),
+		ctrlr:  c,
+		driver: nd}
+	network.endpoints = make(endpointTable)
+
+	d := network.driver.internalDriver
+	if d == nil {
+		return nil, fmt.Errorf("invalid driver bound to network")
+	}
+
 	if err := d.CreateNetwork(network.id, options); err != nil {
 		return nil, err
 	}
@@ -153,13 +185,8 @@ func (n *network) Type() string {
 func (n *network) Delete() error {
 	var err error
 
-	d, ok := n.ctrlr.drivers[n.networkType]
-	if !ok {
-		return fmt.Errorf("unknown driver %q", n.networkType)
-	}
-
 	n.ctrlr.Lock()
-	_, ok = n.ctrlr.networks[n.id]
+	_, ok := n.ctrlr.networks[n.id]
 	if !ok {
 		n.ctrlr.Unlock()
 		return fmt.Errorf("unknown network %s id %s", n.name, n.id)
@@ -183,6 +210,7 @@ func (n *network) Delete() error {
 		}
 	}()
 
+	d := n.driver.internalDriver
 	err = d.DeleteNetwork(n.id)
 	return err
 }
@@ -192,11 +220,7 @@ func (n *network) CreateEndpoint(name string, sboxKey string, options interface{
 	ep.id = driverapi.UUID(common.GenerateRandomID())
 	ep.network = n
 
-	d, ok := n.ctrlr.drivers[n.networkType]
-	if !ok {
-		return nil, nil, fmt.Errorf("unknown driver %q", n.networkType)
-	}
-
+	d := n.driver.internalDriver
 	sinfo, err := d.CreateEndpoint(n.id, ep.id, sboxKey, options)
 	if err != nil {
 		return nil, nil, err
@@ -212,14 +236,9 @@ func (n *network) CreateEndpoint(name string, sboxKey string, options interface{
 func (ep *endpoint) Delete() error {
 	var err error
 
-	d, ok := ep.network.ctrlr.drivers[ep.network.networkType]
-	if !ok {
-		return fmt.Errorf("unknown driver %q", ep.network.networkType)
-	}
-
 	n := ep.network
 	n.Lock()
-	_, ok = n.endpoints[ep.id]
+	_, ok := n.endpoints[ep.id]
 	if !ok {
 		n.Unlock()
 		return fmt.Errorf("unknown endpoint %s id %s", ep.name, ep.id)
@@ -235,6 +254,7 @@ func (ep *endpoint) Delete() error {
 		}
 	}()
 
+	d := n.driver.internalDriver
 	err = d.DeleteEndpoint(n.id, ep.id)
 	return err
 }