Browse code

Seperates the driver-specific and network-specific iptable operations for the bridge driver.

Moves two config options, namely EnableIPTables and EnableUserlandProxy
from networks to the driver.

Closes #242
Signed-off-by: Mohammad Banikazemi <MBanikazemi@gmail.com>

Mohammad Banikazemi authored on 2015/06/12 10:12:00
Showing 15 changed files
... ...
@@ -1680,6 +1680,11 @@ func TestHttpHandlerUninit(t *testing.T) {
1680 1680
 		t.Fatal(err)
1681 1681
 	}
1682 1682
 
1683
+	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
1684
+	if err != nil {
1685
+		t.Fatal(err)
1686
+	}
1687
+
1683 1688
 	h := &httpHandler{c: c}
1684 1689
 	h.initRouter()
1685 1690
 	if h.r == nil {
... ...
@@ -1777,6 +1782,11 @@ func TestEndToEnd(t *testing.T) {
1777 1777
 	if err != nil {
1778 1778
 		t.Fatal(err)
1779 1779
 	}
1780
+	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
1781
+	if err != nil {
1782
+		t.Fatal(err)
1783
+	}
1784
+
1780 1785
 	handleRequest := NewHTTPHandler(c)
1781 1786
 
1782 1787
 	ops := options.Generic{
... ...
@@ -40,7 +40,9 @@ var (
40 40
 
41 41
 // configuration info for the "bridge" driver.
42 42
 type configuration struct {
43
-	EnableIPForwarding bool
43
+	EnableIPForwarding  bool
44
+	EnableIPTables      bool
45
+	EnableUserlandProxy bool
44 46
 }
45 47
 
46 48
 // networkConfiguration for network specific configuration
... ...
@@ -50,7 +52,6 @@ type networkConfiguration struct {
50 50
 	FixedCIDR             *net.IPNet
51 51
 	FixedCIDRv6           *net.IPNet
52 52
 	EnableIPv6            bool
53
-	EnableIPTables        bool
54 53
 	EnableIPMasquerade    bool
55 54
 	EnableICC             bool
56 55
 	Mtu                   int
... ...
@@ -58,7 +59,6 @@ type networkConfiguration struct {
58 58
 	DefaultGatewayIPv6    net.IP
59 59
 	DefaultBindingIP      net.IP
60 60
 	AllowNonDefaultBridge bool
61
-	EnableUserlandProxy   bool
62 61
 }
63 62
 
64 63
 // endpointConfiguration represents the user specified configuration for the sandbox endpoint
... ...
@@ -91,13 +91,16 @@ type bridgeNetwork struct {
91 91
 	config     *networkConfiguration
92 92
 	endpoints  map[types.UUID]*bridgeEndpoint // key: endpoint id
93 93
 	portMapper *portmapper.PortMapper
94
+	driver     *driver // The network's driver
94 95
 	sync.Mutex
95 96
 }
96 97
 
97 98
 type driver struct {
98
-	config   *configuration
99
-	network  *bridgeNetwork
100
-	networks map[types.UUID]*bridgeNetwork
99
+	config      *configuration
100
+	network     *bridgeNetwork
101
+	natChain    *iptables.ChainInfo
102
+	filterChain *iptables.ChainInfo
103
+	networks    map[types.UUID]*bridgeNetwork
101 104
 	sync.Mutex
102 105
 }
103 106
 
... ...
@@ -223,16 +226,6 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
223 223
 		}
224 224
 	}
225 225
 
226
-	if i, ok := data["EnableIPTables"]; ok && i != nil {
227
-		if s, ok := i.(string); ok {
228
-			if c.EnableIPTables, err = strconv.ParseBool(s); err != nil {
229
-				return types.BadRequestErrorf("failed to parse EnableIPTables value: %s", err.Error())
230
-			}
231
-		} else {
232
-			return types.BadRequestErrorf("invalid type for EnableIPTables value")
233
-		}
234
-	}
235
-
236 226
 	if i, ok := data["EnableIPMasquerade"]; ok && i != nil {
237 227
 		if s, ok := i.(string); ok {
238 228
 			if c.EnableIPMasquerade, err = strconv.ParseBool(s); err != nil {
... ...
@@ -334,6 +327,25 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
334 334
 	return nil
335 335
 }
336 336
 
337
+func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
338
+	n.Lock()
339
+	defer n.Unlock()
340
+
341
+	if n.driver == nil {
342
+		return nil, nil, types.BadRequestErrorf("no driver found")
343
+	}
344
+
345
+	return n.driver.natChain, n.driver.filterChain, nil
346
+}
347
+
348
+func (n *bridgeNetwork) getNetworkBridgeName() string {
349
+	n.Lock()
350
+	config := n.config
351
+	n.Unlock()
352
+
353
+	return config.BridgeName
354
+}
355
+
337 356
 func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
338 357
 	n.Lock()
339 358
 	defer n.Unlock()
... ...
@@ -418,6 +430,7 @@ func (c *networkConfiguration) conflictsWithNetworks(id types.UUID, others []*br
418 418
 
419 419
 func (d *driver) Config(option map[string]interface{}) error {
420 420
 	var config *configuration
421
+	var err error
421 422
 
422 423
 	d.Lock()
423 424
 	defer d.Unlock()
... ...
@@ -444,10 +457,19 @@ func (d *driver) Config(option map[string]interface{}) error {
444 444
 		d.config = config
445 445
 	} else {
446 446
 		config = &configuration{}
447
+		d.config = config
447 448
 	}
448 449
 
449 450
 	if config.EnableIPForwarding {
450
-		return setupIPForwarding()
451
+		err = setupIPForwarding()
452
+		if err != nil {
453
+			return err
454
+		}
455
+	}
456
+
457
+	if config.EnableIPTables {
458
+		d.natChain, d.filterChain, err = setupIPChains(config)
459
+		return err
451 460
 	}
452 461
 
453 462
 	return nil
... ...
@@ -480,7 +502,6 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
480 480
 	case map[string]interface{}:
481 481
 		config = &networkConfiguration{
482 482
 			EnableICC:          true,
483
-			EnableIPTables:     true,
484 483
 			EnableIPMasquerade: true,
485 484
 		}
486 485
 		err = config.fromMap(opt)
... ...
@@ -578,6 +599,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
578 578
 		endpoints:  make(map[types.UUID]*bridgeEndpoint),
579 579
 		config:     config,
580 580
 		portMapper: portmapper.New(),
581
+		driver:     d,
581 582
 	}
582 583
 
583 584
 	d.Lock()
... ...
@@ -660,14 +682,14 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
660 660
 		{enableIPv6Forwarding, setupIPv6Forwarding},
661 661
 
662 662
 		// Setup Loopback Adresses Routing
663
-		{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},
663
+		{!d.config.EnableUserlandProxy, setupLoopbackAdressesRouting},
664 664
 
665 665
 		// Setup IPTables.
666
-		{config.EnableIPTables, network.setupIPTables},
666
+		{d.config.EnableIPTables, network.setupIPTables},
667 667
 
668 668
 		//We want to track firewalld configuration so that
669 669
 		//if it is started/reloaded, the rules can be applied correctly
670
-		{config.EnableIPTables, network.setupFirewalld},
670
+		{d.config.EnableIPTables, network.setupFirewalld},
671 671
 
672 672
 		// Setup DefaultGatewayIPv4
673 673
 		{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
... ...
@@ -676,10 +698,10 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
676 676
 		{config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},
677 677
 
678 678
 		// Add inter-network communication rules.
679
-		{config.EnableIPTables, setupNetworkIsolationRules},
679
+		{d.config.EnableIPTables, setupNetworkIsolationRules},
680 680
 
681 681
 		//Configure bridge networking filtering if ICC is off and IP tables are enabled
682
-		{!config.EnableICC && config.EnableIPTables, setupBridgeNetFiltering},
682
+		{!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering},
683 683
 	} {
684 684
 		if step.Condition {
685 685
 			bridgeSetup.queueStep(step.Fn)
... ...
@@ -838,6 +860,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
838 838
 	// Get the network handler and make sure it exists
839 839
 	d.Lock()
840 840
 	n, ok := d.networks[nid]
841
+	dconfig := d.config
841 842
 	d.Unlock()
842 843
 
843 844
 	if !ok {
... ...
@@ -950,7 +973,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
950 950
 		return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
951 951
 	}
952 952
 
953
-	if !config.EnableUserlandProxy {
953
+	if !dconfig.EnableUserlandProxy {
954 954
 		err = setHairpinMode(host, true)
955 955
 		if err != nil {
956 956
 			return err
... ...
@@ -1023,7 +1046,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
1023 1023
 	}
1024 1024
 
1025 1025
 	// Program any required port mapping and store them in the endpoint
1026
-	endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, config.EnableUserlandProxy)
1026
+	endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
1027 1027
 	if err != nil {
1028 1028
 		return err
1029 1029
 	}
... ...
@@ -21,6 +21,7 @@ func TestCreateFullOptions(t *testing.T) {
21 21
 
22 22
 	config := &configuration{
23 23
 		EnableIPForwarding: true,
24
+		EnableIPTables:     true,
24 25
 	}
25 26
 
26 27
 	// Test this scenario: Default gw address does not belong to
... ...
@@ -37,7 +38,6 @@ func TestCreateFullOptions(t *testing.T) {
37 37
 		FixedCIDR:          cnw,
38 38
 		DefaultGatewayIPv4: gw,
39 39
 		EnableIPv6:         true,
40
-		EnableIPTables:     true,
41 40
 	}
42 41
 	_, netConfig.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
43 42
 	genericOption := make(map[string]interface{})
... ...
@@ -71,9 +71,13 @@ func TestCreate(t *testing.T) {
71 71
 	defer netutils.SetupTestNetNS(t)()
72 72
 	d := newDriver()
73 73
 
74
-	config := &networkConfiguration{BridgeName: DefaultBridgeName}
74
+	if err := d.Config(nil); err != nil {
75
+		t.Fatalf("Failed to setup driver config: %v", err)
76
+	}
77
+
78
+	netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
75 79
 	genericOption := make(map[string]interface{})
76
-	genericOption[netlabel.GenericData] = config
80
+	genericOption[netlabel.GenericData] = netconfig
77 81
 
78 82
 	if err := d.CreateNetwork("dummy", genericOption); err != nil {
79 83
 		t.Fatalf("Failed to create bridge: %v", err)
... ...
@@ -100,9 +104,13 @@ func TestCreateFail(t *testing.T) {
100 100
 	defer netutils.SetupTestNetNS(t)()
101 101
 	d := newDriver()
102 102
 
103
-	config := &networkConfiguration{BridgeName: "dummy0"}
103
+	if err := d.Config(nil); err != nil {
104
+		t.Fatalf("Failed to setup driver config: %v", err)
105
+	}
106
+
107
+	netconfig := &networkConfiguration{BridgeName: "dummy0"}
104 108
 	genericOption := make(map[string]interface{})
105
-	genericOption[netlabel.GenericData] = config
109
+	genericOption[netlabel.GenericData] = netconfig
106 110
 
107 111
 	if err := d.CreateNetwork("dummy", genericOption); err == nil {
108 112
 		t.Fatal("Bridge creation was expected to fail")
... ...
@@ -114,20 +122,30 @@ func TestCreateMultipleNetworks(t *testing.T) {
114 114
 	d := newDriver()
115 115
 	dd, _ := d.(*driver)
116 116
 
117
-	config1 := &networkConfiguration{BridgeName: "net_test_1", AllowNonDefaultBridge: true, EnableIPTables: true}
117
+	config := &configuration{
118
+		EnableIPTables: true,
119
+	}
118 120
 	genericOption := make(map[string]interface{})
121
+	genericOption[netlabel.GenericData] = config
122
+
123
+	if err := d.Config(genericOption); err != nil {
124
+		t.Fatalf("Failed to setup driver config: %v", err)
125
+	}
126
+
127
+	config1 := &networkConfiguration{BridgeName: "net_test_1", AllowNonDefaultBridge: true}
128
+	genericOption = make(map[string]interface{})
119 129
 	genericOption[netlabel.GenericData] = config1
120 130
 	if err := d.CreateNetwork("1", genericOption); err != nil {
121 131
 		t.Fatalf("Failed to create bridge: %v", err)
122 132
 	}
123 133
 
124
-	config2 := &networkConfiguration{BridgeName: "net_test_2", AllowNonDefaultBridge: true, EnableIPTables: true}
134
+	config2 := &networkConfiguration{BridgeName: "net_test_2", AllowNonDefaultBridge: true}
125 135
 	genericOption[netlabel.GenericData] = config2
126 136
 	if err := d.CreateNetwork("2", genericOption); err != nil {
127 137
 		t.Fatalf("Failed to create bridge: %v", err)
128 138
 	}
129 139
 
130
-	config3 := &networkConfiguration{BridgeName: "net_test_3", AllowNonDefaultBridge: true, EnableIPTables: true}
140
+	config3 := &networkConfiguration{BridgeName: "net_test_3", AllowNonDefaultBridge: true}
131 141
 	genericOption[netlabel.GenericData] = config3
132 142
 	if err := d.CreateNetwork("3", genericOption); err != nil {
133 143
 		t.Fatalf("Failed to create bridge: %v", err)
... ...
@@ -136,7 +154,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
136 136
 	// Verify the network isolation rules are installed, each network subnet should appear 4 times
137 137
 	verifyV4INCEntries(dd.networks, 4, t)
138 138
 
139
-	config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true, EnableIPTables: true}
139
+	config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true}
140 140
 	genericOption[netlabel.GenericData] = config4
141 141
 	if err := d.CreateNetwork("4", genericOption); err != nil {
142 142
 		t.Fatalf("Failed to create bridge: %v", err)
... ...
@@ -278,15 +296,24 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
278 278
 	d := newDriver()
279 279
 	dd, _ := d.(*driver)
280 280
 
281
-	config := &networkConfiguration{
282
-		BridgeName:          DefaultBridgeName,
281
+	config := &configuration{
283 282
 		EnableIPTables:      true,
284
-		EnableICC:           false,
285 283
 		EnableUserlandProxy: ulPxyEnabled,
286 284
 	}
287 285
 	genericOption := make(map[string]interface{})
288 286
 	genericOption[netlabel.GenericData] = config
289 287
 
288
+	if err := d.Config(genericOption); err != nil {
289
+		t.Fatalf("Failed to setup driver config: %v", err)
290
+	}
291
+
292
+	netconfig := &networkConfiguration{
293
+		BridgeName: DefaultBridgeName,
294
+		EnableICC:  false,
295
+	}
296
+	genericOption = make(map[string]interface{})
297
+	genericOption[netlabel.GenericData] = netconfig
298
+
290 299
 	err := d.CreateNetwork("net1", genericOption)
291 300
 	if err != nil {
292 301
 		t.Fatalf("Failed to create bridge: %v", err)
... ...
@@ -339,9 +366,13 @@ func TestCreateLinkWithOptions(t *testing.T) {
339 339
 	defer netutils.SetupTestNetNS(t)()
340 340
 	d := newDriver()
341 341
 
342
-	config := &networkConfiguration{BridgeName: DefaultBridgeName}
342
+	if err := d.Config(nil); err != nil {
343
+		t.Fatalf("Failed to setup driver config: %v", err)
344
+	}
345
+
346
+	netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
343 347
 	netOptions := make(map[string]interface{})
344
-	netOptions[netlabel.GenericData] = config
348
+	netOptions[netlabel.GenericData] = netconfig
345 349
 
346 350
 	err := d.CreateNetwork("net1", netOptions)
347 351
 	if err != nil {
... ...
@@ -395,14 +426,23 @@ func TestLinkContainers(t *testing.T) {
395 395
 
396 396
 	d := newDriver()
397 397
 
398
-	config := &networkConfiguration{
399
-		BridgeName:     DefaultBridgeName,
398
+	config := &configuration{
400 399
 		EnableIPTables: true,
401
-		EnableICC:      false,
402 400
 	}
403 401
 	genericOption := make(map[string]interface{})
404 402
 	genericOption[netlabel.GenericData] = config
405 403
 
404
+	if err := d.Config(genericOption); err != nil {
405
+		t.Fatalf("Failed to setup driver config: %v", err)
406
+	}
407
+
408
+	netconfig := &networkConfiguration{
409
+		BridgeName: DefaultBridgeName,
410
+		EnableICC:  false,
411
+	}
412
+	genericOption = make(map[string]interface{})
413
+	genericOption[netlabel.GenericData] = netconfig
414
+
406 415
 	err := d.CreateNetwork("net1", genericOption)
407 416
 	if err != nil {
408 417
 		t.Fatalf("Failed to create bridge: %v", err)
... ...
@@ -602,6 +642,10 @@ func TestSetDefaultGw(t *testing.T) {
602 602
 	defer netutils.SetupTestNetNS(t)()
603 603
 	d := newDriver()
604 604
 
605
+	if err := d.Config(nil); err != nil {
606
+		t.Fatalf("Failed to setup driver config: %v", err)
607
+	}
608
+
605 609
 	_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")
606 610
 	gw4 := bridgeNetworks[0].IP.To4()
607 611
 	gw4[3] = 254
... ...
@@ -74,9 +74,9 @@ func linkContainers(action, parentIP, childIP string, ports []types.TransportPor
74 74
 		return InvalidLinkIPAddrError(childIP)
75 75
 	}
76 76
 
77
-	chain := iptables.Chain{Name: DockerChain, Bridge: bridge}
77
+	chain := iptables.ChainInfo{Name: DockerChain}
78 78
 	for _, port := range ports {
79
-		err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String())
79
+		err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
80 80
 		if !ignoreErrors && err != nil {
81 81
 			return err
82 82
 		}
... ...
@@ -14,6 +14,10 @@ func TestLinkCreate(t *testing.T) {
14 14
 	d := newDriver()
15 15
 	dr := d.(*driver)
16 16
 
17
+	if err := d.Config(nil); err != nil {
18
+		t.Fatalf("Failed to setup driver config: %v", err)
19
+	}
20
+
17 21
 	mtu := 1490
18 22
 	config := &networkConfiguration{
19 23
 		BridgeName: DefaultBridgeName,
... ...
@@ -108,6 +112,10 @@ func TestLinkCreateTwo(t *testing.T) {
108 108
 	defer netutils.SetupTestNetNS(t)()
109 109
 	d := newDriver()
110 110
 
111
+	if err := d.Config(nil); err != nil {
112
+		t.Fatalf("Failed to setup driver config: %v", err)
113
+	}
114
+
111 115
 	config := &networkConfiguration{
112 116
 		BridgeName: DefaultBridgeName,
113 117
 		EnableIPv6: true}
... ...
@@ -140,6 +148,10 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
140 140
 	defer netutils.SetupTestNetNS(t)()
141 141
 	d := newDriver()
142 142
 
143
+	if err := d.Config(nil); err != nil {
144
+		t.Fatalf("Failed to setup driver config: %v", err)
145
+	}
146
+
143 147
 	config := &networkConfiguration{
144 148
 		BridgeName: DefaultBridgeName}
145 149
 	genericOption := make(map[string]interface{})
... ...
@@ -170,6 +182,10 @@ func TestLinkDelete(t *testing.T) {
170 170
 	defer netutils.SetupTestNetNS(t)()
171 171
 	d := newDriver()
172 172
 
173
+	if err := d.Config(nil); err != nil {
174
+		t.Fatalf("Failed to setup driver config: %v", err)
175
+	}
176
+
173 177
 	config := &networkConfiguration{
174 178
 		BridgeName: DefaultBridgeName,
175 179
 		EnableIPv6: true}
... ...
@@ -21,6 +21,16 @@ func TestPortMappingConfig(t *testing.T) {
21 21
 	defer netutils.SetupTestNetNS(t)()
22 22
 	d := newDriver()
23 23
 
24
+	config := &configuration{
25
+		EnableIPTables: true,
26
+	}
27
+	genericOption := make(map[string]interface{})
28
+	genericOption[netlabel.GenericData] = config
29
+
30
+	if err := d.Config(genericOption); err != nil {
31
+		t.Fatalf("Failed to setup driver config: %v", err)
32
+	}
33
+
24 34
 	binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}
25 35
 	binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
26 36
 	portBindings := []types.PortBinding{binding1, binding2}
... ...
@@ -29,8 +39,7 @@ func TestPortMappingConfig(t *testing.T) {
29 29
 	epOptions[netlabel.PortMap] = portBindings
30 30
 
31 31
 	netConfig := &networkConfiguration{
32
-		BridgeName:     DefaultBridgeName,
33
-		EnableIPTables: true,
32
+		BridgeName: DefaultBridgeName,
34 33
 	}
35 34
 	netOptions := make(map[string]interface{})
36 35
 	netOptions[netlabel.GenericData] = netConfig
... ...
@@ -3,8 +3,13 @@ package bridge
3 3
 import "github.com/docker/libnetwork/iptables"
4 4
 
5 5
 func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
6
+	d := n.driver
7
+	d.Lock()
8
+	driverConfig := d.config
9
+	d.Unlock()
10
+
6 11
 	// Sanity check.
7
-	if config.EnableIPTables == false {
12
+	if driverConfig.EnableIPTables == false {
8 13
 		return IPTableCfgError(config.BridgeName)
9 14
 	}
10 15
 
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"net"
6 6
 
7
+	"github.com/Sirupsen/logrus"
7 8
 	"github.com/docker/libnetwork/iptables"
8 9
 	"github.com/docker/libnetwork/netutils"
9 10
 )
... ...
@@ -13,14 +14,48 @@ const (
13 13
 	DockerChain = "DOCKER"
14 14
 )
15 15
 
16
-func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
16
+func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, error) {
17 17
 	// Sanity check.
18 18
 	if config.EnableIPTables == false {
19
-		return IPTableCfgError(config.BridgeName)
19
+		return nil, nil, fmt.Errorf("Cannot create new chains, EnableIPTable is disabled")
20 20
 	}
21 21
 
22 22
 	hairpinMode := !config.EnableUserlandProxy
23 23
 
24
+	natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode)
25
+	if err != nil {
26
+		return nil, nil, fmt.Errorf("Failed to create NAT chain: %s", err.Error())
27
+	}
28
+	defer func() {
29
+		if err != nil {
30
+			if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
31
+				logrus.Warnf("Failed on removing iptables NAT chain on cleanup: %v", err)
32
+			}
33
+		}
34
+	}()
35
+
36
+	filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, hairpinMode)
37
+	if err != nil {
38
+		return nil, nil, fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
39
+	}
40
+
41
+	return natChain, filterChain, nil
42
+}
43
+
44
+func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
45
+	d := n.driver
46
+	d.Lock()
47
+	driverConfig := d.config
48
+	d.Unlock()
49
+
50
+	// Sanity check.
51
+	if driverConfig.EnableIPTables == false {
52
+		return fmt.Errorf("Cannot program chains, EnableIPTable is disabled")
53
+	}
54
+
55
+	// Pickup this configuraton option from driver
56
+	hairpinMode := !driverConfig.EnableUserlandProxy
57
+
24 58
 	addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
25 59
 	if err != nil {
26 60
 		return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
... ...
@@ -34,17 +69,22 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
34 34
 		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
35 35
 	}
36 36
 
37
-	_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat, hairpinMode)
37
+	natChain, filterChain, err := n.getDriverChains()
38
+	if err != nil {
39
+		return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
40
+	}
41
+
42
+	err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode)
38 43
 	if err != nil {
39
-		return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
44
+		return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
40 45
 	}
41 46
 
42
-	chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter, hairpinMode)
47
+	err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode)
43 48
 	if err != nil {
44
-		return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
49
+		return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
45 50
 	}
46 51
 
47
-	n.portMapper.SetIptablesChain(chain)
52
+	n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
48 53
 
49 54
 	return nil
50 55
 }
... ...
@@ -37,26 +37,32 @@ func TestProgramIPTable(t *testing.T) {
37 37
 	}
38 38
 }
39 39
 
40
-func TestSetupIPTables(t *testing.T) {
40
+func TestSetupIPChains(t *testing.T) {
41 41
 	// Create a test bridge with a basic bridge configuration (name + IPv4).
42 42
 	defer netutils.SetupTestNetNS(t)()
43
+
44
+	driverconfig := &configuration{
45
+		EnableIPTables: true,
46
+	}
47
+	d := &driver{
48
+		config: driverconfig,
49
+	}
50
+	assertChainConfig(d, t)
51
+
43 52
 	config := getBasicTestConfig()
44 53
 	br := &bridgeInterface{}
45
-
46 54
 	createTestBridge(config, br, t)
47 55
 
48
-	// Modify iptables params in base configuration and apply them.
49
-	config.EnableIPTables = true
50
-	assertBridgeConfig(config, br, t)
56
+	assertBridgeConfig(config, br, d, t)
51 57
 
52 58
 	config.EnableIPMasquerade = true
53
-	assertBridgeConfig(config, br, t)
59
+	assertBridgeConfig(config, br, d, t)
54 60
 
55 61
 	config.EnableICC = true
56
-	assertBridgeConfig(config, br, t)
62
+	assertBridgeConfig(config, br, d, t)
57 63
 
58 64
 	config.EnableIPMasquerade = false
59
-	assertBridgeConfig(config, br, t)
65
+	assertBridgeConfig(config, br, d, t)
60 66
 }
61 67
 
62 68
 func getBasicTestConfig() *networkConfiguration {
... ...
@@ -94,9 +100,22 @@ func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
94 94
 	}
95 95
 }
96 96
 
97
+// Assert function which create chains.
98
+func assertChainConfig(d *driver, t *testing.T) {
99
+	var err error
100
+
101
+	d.natChain, d.filterChain, err = setupIPChains(d.config)
102
+	if err != nil {
103
+		t.Fatal(err)
104
+	}
105
+}
106
+
97 107
 // Assert function which pushes chains based on bridge config parameters.
98
-func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
99
-	nw := bridgeNetwork{portMapper: portmapper.New()}
108
+func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, d *driver, t *testing.T) {
109
+	nw := bridgeNetwork{portMapper: portmapper.New(),
110
+		config: config}
111
+	nw.driver = d
112
+
100 113
 	// Attempt programming of ip tables.
101 114
 	err := nw.setupIPTables(config, br)
102 115
 	if err != nil {
... ...
@@ -17,9 +17,12 @@ func TestFirewalldInit(t *testing.T) {
17 17
 
18 18
 func TestReloaded(t *testing.T) {
19 19
 	var err error
20
-	var fwdChain *Chain
20
+	var fwdChain *ChainInfo
21 21
 
22
-	fwdChain, err = NewChain("FWD", "lo", Filter, false)
22
+	fwdChain, err = NewChain("FWD", Filter, false)
23
+	bridgeName := "lo"
24
+
25
+	err = ProgramChain(fwdChain, bridgeName, false)
23 26
 	if err != nil {
24 27
 		t.Fatal(err)
25 28
 	}
... ...
@@ -31,17 +34,17 @@ func TestReloaded(t *testing.T) {
31 31
 	port := 1234
32 32
 	proto := "tcp"
33 33
 
34
-	err = fwdChain.Link(Append, ip1, ip2, port, proto)
34
+	err = fwdChain.Link(Append, ip1, ip2, port, proto, bridgeName)
35 35
 	if err != nil {
36 36
 		t.Fatal(err)
37 37
 	} else {
38 38
 		// to be re-called again later
39
-		OnReloaded(func() { fwdChain.Link(Append, ip1, ip2, port, proto) })
39
+		OnReloaded(func() { fwdChain.Link(Append, ip1, ip2, port, proto, bridgeName) })
40 40
 	}
41 41
 
42 42
 	rule1 := []string{
43
-		"-i", fwdChain.Bridge,
44
-		"-o", fwdChain.Bridge,
43
+		"-i", bridgeName,
44
+		"-o", bridgeName,
45 45
 		"-p", proto,
46 46
 		"-s", ip1.String(),
47 47
 		"-d", ip2.String(),
... ...
@@ -42,10 +42,9 @@ var (
42 42
 	ErrIptablesNotFound = errors.New("Iptables not found")
43 43
 )
44 44
 
45
-// Chain defines the iptables chain.
46
-type Chain struct {
45
+// ChainInfo defines the iptables chain.
46
+type ChainInfo struct {
47 47
 	Name        string
48
-	Bridge      string
49 48
 	Table       Table
50 49
 	HairpinMode bool
51 50
 }
... ...
@@ -74,14 +73,12 @@ func initCheck() error {
74 74
 }
75 75
 
76 76
 // NewChain adds a new chain to ip table.
77
-func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error) {
78
-	c := &Chain{
77
+func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
78
+	c := &ChainInfo{
79 79
 		Name:        name,
80
-		Bridge:      bridge,
81 80
 		Table:       table,
82 81
 		HairpinMode: hairpinMode,
83 82
 	}
84
-
85 83
 	if string(c.Table) == "" {
86 84
 		c.Table = Filter
87 85
 	}
... ...
@@ -94,8 +91,16 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
94 94
 			return nil, fmt.Errorf("Could not create %s/%s chain: %s", c.Table, c.Name, output)
95 95
 		}
96 96
 	}
97
+	return c, nil
98
+}
99
+
100
+// ProgramChain is used to add rules to a chain
101
+func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
102
+	if c.Name == "" {
103
+		return fmt.Errorf("Could not program chain, missing chain name.")
104
+	}
97 105
 
98
-	switch table {
106
+	switch c.Table {
99 107
 	case Nat:
100 108
 		preroute := []string{
101 109
 			"-m", "addrtype",
... ...
@@ -103,7 +108,7 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
103 103
 			"-j", c.Name}
104 104
 		if !Exists(Nat, "PREROUTING", preroute...) {
105 105
 			if err := c.Prerouting(Append, preroute...); err != nil {
106
-				return nil, fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
106
+				return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
107 107
 			}
108 108
 		}
109 109
 		output := []string{
... ...
@@ -115,28 +120,32 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
115 115
 		}
116 116
 		if !Exists(Nat, "OUTPUT", output...) {
117 117
 			if err := c.Output(Append, output...); err != nil {
118
-				return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
118
+				return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
119 119
 			}
120 120
 		}
121 121
 	case Filter:
122
+		if bridgeName == "" {
123
+			return fmt.Errorf("Could not program chain %s/%s, missing bridge name.",
124
+				c.Table, c.Name)
125
+		}
122 126
 		link := []string{
123
-			"-o", c.Bridge,
127
+			"-o", bridgeName,
124 128
 			"-j", c.Name}
125 129
 		if !Exists(Filter, "FORWARD", link...) {
126 130
 			insert := append([]string{string(Insert), "FORWARD"}, link...)
127 131
 			if output, err := Raw(insert...); err != nil {
128
-				return nil, err
132
+				return err
129 133
 			} else if len(output) != 0 {
130
-				return nil, fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
134
+				return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
131 135
 			}
132 136
 		}
133 137
 	}
134
-	return c, nil
138
+	return nil
135 139
 }
136 140
 
137 141
 // RemoveExistingChain removes existing chain from the table.
138 142
 func RemoveExistingChain(name string, table Table) error {
139
-	c := &Chain{
143
+	c := &ChainInfo{
140 144
 		Name:  name,
141 145
 		Table: table,
142 146
 	}
... ...
@@ -147,7 +156,7 @@ func RemoveExistingChain(name string, table Table) error {
147 147
 }
148 148
 
149 149
 // Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
150
-func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int) error {
150
+func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
151 151
 	daddr := ip.String()
152 152
 	if ip.IsUnspecified() {
153 153
 		// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we
... ...
@@ -162,7 +171,7 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
162 162
 		"-j", "DNAT",
163 163
 		"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
164 164
 	if !c.HairpinMode {
165
-		args = append(args, "!", "-i", c.Bridge)
165
+		args = append(args, "!", "-i", bridgeName)
166 166
 	}
167 167
 	if output, err := Raw(args...); err != nil {
168 168
 		return err
... ...
@@ -171,8 +180,8 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
171 171
 	}
172 172
 
173 173
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
174
-		"!", "-i", c.Bridge,
175
-		"-o", c.Bridge,
174
+		"!", "-i", bridgeName,
175
+		"-o", bridgeName,
176 176
 		"-p", proto,
177 177
 		"-d", destAddr,
178 178
 		"--dport", strconv.Itoa(destPort),
... ...
@@ -198,9 +207,9 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
198 198
 
199 199
 // Link adds reciprocal ACCEPT rule for two supplied IP addresses.
200 200
 // Traffic is allowed from ip1 to ip2 and vice-versa
201
-func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) error {
201
+func (c *ChainInfo) Link(action Action, ip1, ip2 net.IP, port int, proto string, bridgeName string) error {
202 202
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
203
-		"-i", c.Bridge, "-o", c.Bridge,
203
+		"-i", bridgeName, "-o", bridgeName,
204 204
 		"-p", proto,
205 205
 		"-s", ip1.String(),
206 206
 		"-d", ip2.String(),
... ...
@@ -211,7 +220,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
211 211
 		return fmt.Errorf("Error iptables forward: %s", output)
212 212
 	}
213 213
 	if output, err := Raw("-t", string(Filter), string(action), c.Name,
214
-		"-i", c.Bridge, "-o", c.Bridge,
214
+		"-i", bridgeName, "-o", bridgeName,
215 215
 		"-p", proto,
216 216
 		"-s", ip2.String(),
217 217
 		"-d", ip1.String(),
... ...
@@ -225,7 +234,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
225 225
 }
226 226
 
227 227
 // Prerouting adds linking rule to nat/PREROUTING chain.
228
-func (c *Chain) Prerouting(action Action, args ...string) error {
228
+func (c *ChainInfo) Prerouting(action Action, args ...string) error {
229 229
 	a := []string{"-t", string(Nat), string(action), "PREROUTING"}
230 230
 	if len(args) > 0 {
231 231
 		a = append(a, args...)
... ...
@@ -239,7 +248,7 @@ func (c *Chain) Prerouting(action Action, args ...string) error {
239 239
 }
240 240
 
241 241
 // Output adds linking rule to an OUTPUT chain.
242
-func (c *Chain) Output(action Action, args ...string) error {
242
+func (c *ChainInfo) Output(action Action, args ...string) error {
243 243
 	a := []string{"-t", string(c.Table), string(action), "OUTPUT"}
244 244
 	if len(args) > 0 {
245 245
 		a = append(a, args...)
... ...
@@ -253,7 +262,7 @@ func (c *Chain) Output(action Action, args ...string) error {
253 253
 }
254 254
 
255 255
 // Remove removes the chain.
256
-func (c *Chain) Remove() error {
256
+func (c *ChainInfo) Remove() error {
257 257
 	// Ignore errors - This could mean the chains were never set up
258 258
 	if c.Table == Nat {
259 259
 		c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name)
... ...
@@ -13,18 +13,22 @@ import (
13 13
 
14 14
 const chainName = "DOCKEREST"
15 15
 
16
-var natChain *Chain
17
-var filterChain *Chain
16
+var natChain *ChainInfo
17
+var filterChain *ChainInfo
18
+var bridgeName string
18 19
 
19 20
 func TestNewChain(t *testing.T) {
20 21
 	var err error
21 22
 
22
-	natChain, err = NewChain(chainName, "lo", Nat, false)
23
+	bridgeName = "lo"
24
+	natChain, err = NewChain(chainName, Nat, false)
25
+	err = ProgramChain(natChain, bridgeName, false)
23 26
 	if err != nil {
24 27
 		t.Fatal(err)
25 28
 	}
26 29
 
27
-	filterChain, err = NewChain(chainName, "lo", Filter, false)
30
+	filterChain, err = NewChain(chainName, Filter, false)
31
+	err = ProgramChain(filterChain, bridgeName, false)
28 32
 	if err != nil {
29 33
 		t.Fatal(err)
30 34
 	}
... ...
@@ -37,7 +41,8 @@ func TestForward(t *testing.T) {
37 37
 	dstPort := 4321
38 38
 	proto := "tcp"
39 39
 
40
-	err := natChain.Forward(Insert, ip, port, proto, dstAddr, dstPort)
40
+	bridgeName := "lo"
41
+	err := natChain.Forward(Insert, ip, port, proto, dstAddr, dstPort, bridgeName)
41 42
 	if err != nil {
42 43
 		t.Fatal(err)
43 44
 	}
... ...
@@ -48,7 +53,7 @@ func TestForward(t *testing.T) {
48 48
 		"--dport", strconv.Itoa(port),
49 49
 		"-j", "DNAT",
50 50
 		"--to-destination", dstAddr + ":" + strconv.Itoa(dstPort),
51
-		"!", "-i", natChain.Bridge,
51
+		"!", "-i", bridgeName,
52 52
 	}
53 53
 
54 54
 	if !Exists(natChain.Table, natChain.Name, dnatRule...) {
... ...
@@ -56,8 +61,8 @@ func TestForward(t *testing.T) {
56 56
 	}
57 57
 
58 58
 	filterRule := []string{
59
-		"!", "-i", filterChain.Bridge,
60
-		"-o", filterChain.Bridge,
59
+		"!", "-i", bridgeName,
60
+		"-o", bridgeName,
61 61
 		"-d", dstAddr,
62 62
 		"-p", proto,
63 63
 		"--dport", strconv.Itoa(dstPort),
... ...
@@ -84,19 +89,20 @@ func TestForward(t *testing.T) {
84 84
 func TestLink(t *testing.T) {
85 85
 	var err error
86 86
 
87
+	bridgeName := "lo"
87 88
 	ip1 := net.ParseIP("192.168.1.1")
88 89
 	ip2 := net.ParseIP("192.168.1.2")
89 90
 	port := 1234
90 91
 	proto := "tcp"
91 92
 
92
-	err = filterChain.Link(Append, ip1, ip2, port, proto)
93
+	err = filterChain.Link(Append, ip1, ip2, port, proto, bridgeName)
93 94
 	if err != nil {
94 95
 		t.Fatal(err)
95 96
 	}
96 97
 
97 98
 	rule1 := []string{
98
-		"-i", filterChain.Bridge,
99
-		"-o", filterChain.Bridge,
99
+		"-i", bridgeName,
100
+		"-o", bridgeName,
100 101
 		"-p", proto,
101 102
 		"-s", ip1.String(),
102 103
 		"-d", ip2.String(),
... ...
@@ -108,8 +114,8 @@ func TestLink(t *testing.T) {
108 108
 	}
109 109
 
110 110
 	rule2 := []string{
111
-		"-i", filterChain.Bridge,
112
-		"-o", filterChain.Bridge,
111
+		"-i", bridgeName,
112
+		"-o", bridgeName,
113 113
 		"-p", proto,
114 114
 		"-s", ip2.String(),
115 115
 		"-d", ip1.String(),
... ...
@@ -192,7 +198,7 @@ func RunConcurrencyTest(t *testing.T, allowXlock bool) {
192 192
 		wg.Add(1)
193 193
 		go func() {
194 194
 			defer wg.Done()
195
-			err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort)
195
+			err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort, "lo")
196 196
 			if err != nil {
197 197
 				t.Fatal(err)
198 198
 			}
... ...
@@ -208,7 +214,7 @@ func TestCleanup(t *testing.T) {
208 208
 	// Cleanup filter/FORWARD first otherwise output of iptables-save is dirty
209 209
 	link := []string{"-t", string(filterChain.Table),
210 210
 		string(Delete), "FORWARD",
211
-		"-o", filterChain.Bridge,
211
+		"-o", bridgeName,
212 212
 		"-j", filterChain.Name}
213 213
 	if _, err = Raw(link...); err != nil {
214 214
 		t.Fatal(err)
... ...
@@ -251,10 +251,9 @@ func TestBridge(t *testing.T) {
251 251
 			"FixedCIDR":             cidr,
252 252
 			"FixedCIDRv6":           cidrv6,
253 253
 			"EnableIPv6":            true,
254
-			"EnableIPTables":        true,
255
-			"EnableIPMasquerade":    true,
256 254
 			"EnableICC":             true,
257 255
 			"AllowNonDefaultBridge": true,
256
+			"EnableIPMasquerade":    true,
258 257
 		},
259 258
 	}
260 259
 
... ...
@@ -31,7 +31,8 @@ var (
31 31
 
32 32
 // PortMapper manages the network address translation
33 33
 type PortMapper struct {
34
-	chain *iptables.Chain
34
+	chain      *iptables.ChainInfo
35
+	bridgeName string
35 36
 
36 37
 	// udp:ip:port
37 38
 	currentMappings map[string]*mapping
... ...
@@ -54,8 +55,9 @@ func NewWithPortAllocator(allocator *portallocator.PortAllocator) *PortMapper {
54 54
 }
55 55
 
56 56
 // SetIptablesChain sets the specified chain into portmapper
57
-func (pm *PortMapper) SetIptablesChain(c *iptables.Chain) {
57
+func (pm *PortMapper) SetIptablesChain(c *iptables.ChainInfo, bridgeName string) {
58 58
 	pm.chain = c
59
+	pm.bridgeName = bridgeName
59 60
 }
60 61
 
61 62
 // Map maps the specified container transport address to the host's network address and transport port
... ...
@@ -215,5 +217,5 @@ func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net
215 215
 	if pm.chain == nil {
216 216
 		return nil
217 217
 	}
218
-	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
218
+	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName)
219 219
 }
... ...
@@ -17,16 +17,15 @@ func init() {
17 17
 func TestSetIptablesChain(t *testing.T) {
18 18
 	pm := New()
19 19
 
20
-	c := &iptables.Chain{
21
-		Name:   "TEST",
22
-		Bridge: "192.168.1.1",
20
+	c := &iptables.ChainInfo{
21
+		Name: "TEST",
23 22
 	}
24 23
 
25 24
 	if pm.chain != nil {
26 25
 		t.Fatal("chain should be nil at init")
27 26
 	}
28 27
 
29
-	pm.SetIptablesChain(c)
28
+	pm.SetIptablesChain(c, "lo")
30 29
 	if pm.chain == nil {
31 30
 		t.Fatal("chain should not be nil after set")
32 31
 	}