github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/bridge/bridge_test.go (about) 1 // +build linux 2 3 package bridge 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "net" 10 "regexp" 11 "strconv" 12 "testing" 13 14 "github.com/docker/docker/libnetwork/driverapi" 15 "github.com/docker/docker/libnetwork/iptables" 16 "github.com/docker/docker/libnetwork/netlabel" 17 "github.com/docker/docker/libnetwork/netutils" 18 "github.com/docker/docker/libnetwork/options" 19 "github.com/docker/docker/libnetwork/testutils" 20 "github.com/docker/docker/libnetwork/types" 21 "github.com/vishvananda/netlink" 22 ) 23 24 func TestEndpointMarshalling(t *testing.T) { 25 ip1, _ := types.ParseCIDR("172.22.0.9/16") 26 ip2, _ := types.ParseCIDR("2001:db8::9") 27 mac, _ := net.ParseMAC("ac:bd:24:57:66:77") 28 e := &bridgeEndpoint{ 29 id: "d2c015a1fe5930650cbcd50493efba0500bcebd8ee1f4401a16319f8a567de33", 30 nid: "ee33fbb43c323f1920b6b35a0101552ac22ede960d0e5245e9738bccc68b2415", 31 addr: ip1, 32 addrv6: ip2, 33 macAddress: mac, 34 srcName: "veth123456", 35 config: &endpointConfiguration{MacAddress: mac}, 36 containerConfig: &containerConfiguration{ 37 ParentEndpoints: []string{"one", "due", "three"}, 38 ChildEndpoints: []string{"four", "five", "six"}, 39 }, 40 extConnConfig: &connectivityConfiguration{ 41 ExposedPorts: []types.TransportPort{ 42 { 43 Proto: 6, 44 Port: uint16(18), 45 }, 46 }, 47 PortBindings: []types.PortBinding{ 48 { 49 Proto: 6, 50 IP: net.ParseIP("17210.33.9.56"), 51 Port: uint16(18), 52 HostPort: uint16(3000), 53 HostPortEnd: uint16(14000), 54 }, 55 }, 56 }, 57 portMapping: []types.PortBinding{ 58 { 59 Proto: 17, 60 IP: net.ParseIP("172.33.9.56"), 61 Port: uint16(99), 62 HostIP: net.ParseIP("10.10.100.2"), 63 HostPort: uint16(9900), 64 HostPortEnd: uint16(10000), 65 }, 66 { 67 Proto: 6, 68 IP: net.ParseIP("171.33.9.56"), 69 Port: uint16(55), 70 HostIP: net.ParseIP("10.11.100.2"), 71 HostPort: uint16(5500), 72 HostPortEnd: uint16(55000), 73 }, 74 }, 75 } 76 77 b, err := json.Marshal(e) 78 if err != nil { 79 t.Fatal(err) 80 } 81 82 ee := &bridgeEndpoint{} 83 err = json.Unmarshal(b, ee) 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 if e.id != ee.id || e.nid != ee.nid || e.srcName != ee.srcName || !bytes.Equal(e.macAddress, ee.macAddress) || 89 !types.CompareIPNet(e.addr, ee.addr) || !types.CompareIPNet(e.addrv6, ee.addrv6) || 90 !compareEpConfig(e.config, ee.config) || 91 !compareContainerConfig(e.containerConfig, ee.containerConfig) || 92 !compareConnConfig(e.extConnConfig, ee.extConnConfig) || 93 !compareBindings(e.portMapping, ee.portMapping) { 94 t.Fatalf("JSON marsh/unmarsh failed.\nOriginal:\n%#v\nDecoded:\n%#v", e, ee) 95 } 96 } 97 98 func compareEpConfig(a, b *endpointConfiguration) bool { 99 if a == b { 100 return true 101 } 102 if a == nil || b == nil { 103 return false 104 } 105 return bytes.Equal(a.MacAddress, b.MacAddress) 106 } 107 108 func compareContainerConfig(a, b *containerConfiguration) bool { 109 if a == b { 110 return true 111 } 112 if a == nil || b == nil { 113 return false 114 } 115 if len(a.ParentEndpoints) != len(b.ParentEndpoints) || 116 len(a.ChildEndpoints) != len(b.ChildEndpoints) { 117 return false 118 } 119 for i := 0; i < len(a.ParentEndpoints); i++ { 120 if a.ParentEndpoints[i] != b.ParentEndpoints[i] { 121 return false 122 } 123 } 124 for i := 0; i < len(a.ChildEndpoints); i++ { 125 if a.ChildEndpoints[i] != b.ChildEndpoints[i] { 126 return false 127 } 128 } 129 return true 130 } 131 132 func compareConnConfig(a, b *connectivityConfiguration) bool { 133 if a == b { 134 return true 135 } 136 if a == nil || b == nil { 137 return false 138 } 139 if len(a.ExposedPorts) != len(b.ExposedPorts) || 140 len(a.PortBindings) != len(b.PortBindings) { 141 return false 142 } 143 for i := 0; i < len(a.ExposedPorts); i++ { 144 if !a.ExposedPorts[i].Equal(&b.ExposedPorts[i]) { 145 return false 146 } 147 } 148 for i := 0; i < len(a.PortBindings); i++ { 149 if !a.PortBindings[i].Equal(&b.PortBindings[i]) { 150 return false 151 } 152 } 153 return true 154 } 155 156 func compareBindings(a, b []types.PortBinding) bool { 157 if len(a) != len(b) { 158 return false 159 } 160 for i := 0; i < len(a); i++ { 161 if !a[i].Equal(&b[i]) { 162 return false 163 } 164 } 165 return true 166 } 167 168 func getIPv4Data(t *testing.T, iface string) []driverapi.IPAMData { 169 ipd := driverapi.IPAMData{AddressSpace: "full"} 170 nws, _, err := netutils.ElectInterfaceAddresses(iface) 171 if err != nil { 172 t.Fatal(err) 173 } 174 ipd.Pool = nws[0] 175 // Set network gateway to X.X.X.1 176 ipd.Gateway = types.GetIPNetCopy(nws[0]) 177 ipd.Gateway.IP[len(ipd.Gateway.IP)-1] = 1 178 return []driverapi.IPAMData{ipd} 179 } 180 181 func TestCreateFullOptions(t *testing.T) { 182 if !testutils.IsRunningInContainer() { 183 defer testutils.SetupTestOSContext(t)() 184 } 185 d := newDriver() 186 187 config := &configuration{ 188 EnableIPForwarding: true, 189 EnableIPTables: true, 190 } 191 192 // Test this scenario: Default gw address does not belong to 193 // container network and it's greater than bridge address 194 cnw, _ := types.ParseCIDR("172.16.122.0/24") 195 bnw, _ := types.ParseCIDR("172.16.0.0/24") 196 br, _ := types.ParseCIDR("172.16.0.1/16") 197 defgw, _ := types.ParseCIDR("172.16.0.100/16") 198 199 genericOption := make(map[string]interface{}) 200 genericOption[netlabel.GenericData] = config 201 202 if err := d.configure(genericOption); err != nil { 203 t.Fatalf("Failed to setup driver config: %v", err) 204 } 205 206 netOption := make(map[string]interface{}) 207 netOption[netlabel.EnableIPv6] = true 208 netOption[netlabel.GenericData] = &networkConfiguration{ 209 BridgeName: DefaultBridgeName, 210 } 211 212 ipdList := []driverapi.IPAMData{ 213 { 214 Pool: bnw, 215 Gateway: br, 216 AuxAddresses: map[string]*net.IPNet{DefaultGatewayV4AuxKey: defgw}, 217 }, 218 } 219 err := d.CreateNetwork("dummy", netOption, nil, ipdList, nil) 220 if err != nil { 221 t.Fatalf("Failed to create bridge: %v", err) 222 } 223 224 // Verify the IP address allocated for the endpoint belongs to the container network 225 epOptions := make(map[string]interface{}) 226 te := newTestEndpoint(cnw, 10) 227 err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions) 228 if err != nil { 229 t.Fatalf("Failed to create an endpoint : %s", err.Error()) 230 } 231 232 if !cnw.Contains(te.Interface().Address().IP) { 233 t.Fatalf("endpoint got assigned address outside of container network(%s): %s", cnw.String(), te.Interface().Address()) 234 } 235 } 236 237 func TestCreateNoConfig(t *testing.T) { 238 if !testutils.IsRunningInContainer() { 239 defer testutils.SetupTestOSContext(t)() 240 } 241 d := newDriver() 242 243 netconfig := &networkConfiguration{BridgeName: DefaultBridgeName} 244 genericOption := make(map[string]interface{}) 245 genericOption[netlabel.GenericData] = netconfig 246 247 if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 248 t.Fatalf("Failed to create bridge: %v", err) 249 } 250 } 251 252 func TestCreateFullOptionsLabels(t *testing.T) { 253 if !testutils.IsRunningInContainer() { 254 defer testutils.SetupTestOSContext(t)() 255 } 256 d := newDriver() 257 258 config := &configuration{ 259 EnableIPForwarding: true, 260 } 261 genericOption := make(map[string]interface{}) 262 genericOption[netlabel.GenericData] = config 263 264 if err := d.configure(genericOption); err != nil { 265 t.Fatalf("Failed to setup driver config: %v", err) 266 } 267 268 bndIPs := "127.0.0.1" 269 testHostIP := "1.2.3.4" 270 nwV6s := "2001:db8:2600:2700:2800::/80" 271 gwV6s := "2001:db8:2600:2700:2800::25/80" 272 nwV6, _ := types.ParseCIDR(nwV6s) 273 gwV6, _ := types.ParseCIDR(gwV6s) 274 275 labels := map[string]string{ 276 BridgeName: DefaultBridgeName, 277 DefaultBridge: "true", 278 EnableICC: "true", 279 EnableIPMasquerade: "true", 280 DefaultBindingIP: bndIPs, 281 netlabel.HostIP: testHostIP, 282 } 283 284 netOption := make(map[string]interface{}) 285 netOption[netlabel.EnableIPv6] = true 286 netOption[netlabel.GenericData] = labels 287 288 ipdList := getIPv4Data(t, "") 289 ipd6List := []driverapi.IPAMData{ 290 { 291 Pool: nwV6, 292 AuxAddresses: map[string]*net.IPNet{ 293 DefaultGatewayV6AuxKey: gwV6, 294 }, 295 }, 296 } 297 298 err := d.CreateNetwork("dummy", netOption, nil, ipdList, ipd6List) 299 if err != nil { 300 t.Fatalf("Failed to create bridge: %v", err) 301 } 302 303 nw, ok := d.networks["dummy"] 304 if !ok { 305 t.Fatal("Cannot find dummy network in bridge driver") 306 } 307 308 if nw.config.BridgeName != DefaultBridgeName { 309 t.Fatal("incongruent name in bridge network") 310 } 311 312 if !nw.config.EnableIPv6 { 313 t.Fatal("incongruent EnableIPv6 in bridge network") 314 } 315 316 if !nw.config.EnableICC { 317 t.Fatal("incongruent EnableICC in bridge network") 318 } 319 320 if !nw.config.EnableIPMasquerade { 321 t.Fatal("incongruent EnableIPMasquerade in bridge network") 322 } 323 324 bndIP := net.ParseIP(bndIPs) 325 if !bndIP.Equal(nw.config.DefaultBindingIP) { 326 t.Fatalf("Unexpected: %v", nw.config.DefaultBindingIP) 327 } 328 329 hostIP := net.ParseIP(testHostIP) 330 if !hostIP.Equal(nw.config.HostIP) { 331 t.Fatalf("Unexpected: %v", nw.config.HostIP) 332 } 333 334 if !types.CompareIPNet(nw.config.AddressIPv6, nwV6) { 335 t.Fatalf("Unexpected: %v", nw.config.AddressIPv6) 336 } 337 338 if !gwV6.IP.Equal(nw.config.DefaultGatewayIPv6) { 339 t.Fatalf("Unexpected: %v", nw.config.DefaultGatewayIPv6) 340 } 341 342 // In short here we are testing --fixed-cidr-v6 daemon option 343 // plus --mac-address run option 344 mac, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff") 345 epOptions := map[string]interface{}{netlabel.MacAddress: mac} 346 te := newTestEndpoint(ipdList[0].Pool, 20) 347 err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions) 348 if err != nil { 349 t.Fatal(err) 350 } 351 352 if !nwV6.Contains(te.Interface().AddressIPv6().IP) { 353 t.Fatalf("endpoint got assigned address outside of container network(%s): %s", nwV6.String(), te.Interface().AddressIPv6()) 354 } 355 if te.Interface().AddressIPv6().IP.String() != "2001:db8:2600:2700:2800:aabb:ccdd:eeff" { 356 t.Fatalf("Unexpected endpoint IPv6 address: %v", te.Interface().AddressIPv6().IP) 357 } 358 } 359 360 func TestCreate(t *testing.T) { 361 if !testutils.IsRunningInContainer() { 362 defer testutils.SetupTestOSContext(t)() 363 } 364 365 d := newDriver() 366 367 if err := d.configure(nil); err != nil { 368 t.Fatalf("Failed to setup driver config: %v", err) 369 } 370 371 netconfig := &networkConfiguration{BridgeName: DefaultBridgeName} 372 genericOption := make(map[string]interface{}) 373 genericOption[netlabel.GenericData] = netconfig 374 375 if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 376 t.Fatalf("Failed to create bridge: %v", err) 377 } 378 379 err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t, ""), nil) 380 if err == nil { 381 t.Fatal("Expected bridge driver to refuse creation of second network with default name") 382 } 383 if _, ok := err.(types.ForbiddenError); !ok { 384 t.Fatal("Creation of second network with default name failed with unexpected error type") 385 } 386 } 387 388 func TestCreateFail(t *testing.T) { 389 if !testutils.IsRunningInContainer() { 390 defer testutils.SetupTestOSContext(t)() 391 } 392 393 d := newDriver() 394 395 if err := d.configure(nil); err != nil { 396 t.Fatalf("Failed to setup driver config: %v", err) 397 } 398 399 netconfig := &networkConfiguration{BridgeName: "dummy0", DefaultBridge: true} 400 genericOption := make(map[string]interface{}) 401 genericOption[netlabel.GenericData] = netconfig 402 403 if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t, ""), nil); err == nil { 404 t.Fatal("Bridge creation was expected to fail") 405 } 406 } 407 408 func TestCreateMultipleNetworks(t *testing.T) { 409 if !testutils.IsRunningInContainer() { 410 defer testutils.SetupTestOSContext(t)() 411 } 412 413 d := newDriver() 414 415 config := &configuration{ 416 EnableIPTables: true, 417 } 418 genericOption := make(map[string]interface{}) 419 genericOption[netlabel.GenericData] = config 420 421 if err := d.configure(genericOption); err != nil { 422 t.Fatalf("Failed to setup driver config: %v", err) 423 } 424 425 config1 := &networkConfiguration{BridgeName: "net_test_1"} 426 genericOption = make(map[string]interface{}) 427 genericOption[netlabel.GenericData] = config1 428 if err := d.CreateNetwork("1", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 429 t.Fatalf("Failed to create bridge: %v", err) 430 } 431 432 verifyV4INCEntries(d.networks, t) 433 434 config2 := &networkConfiguration{BridgeName: "net_test_2"} 435 genericOption[netlabel.GenericData] = config2 436 if err := d.CreateNetwork("2", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 437 t.Fatalf("Failed to create bridge: %v", err) 438 } 439 440 verifyV4INCEntries(d.networks, t) 441 442 config3 := &networkConfiguration{BridgeName: "net_test_3"} 443 genericOption[netlabel.GenericData] = config3 444 if err := d.CreateNetwork("3", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 445 t.Fatalf("Failed to create bridge: %v", err) 446 } 447 448 verifyV4INCEntries(d.networks, t) 449 450 config4 := &networkConfiguration{BridgeName: "net_test_4"} 451 genericOption[netlabel.GenericData] = config4 452 if err := d.CreateNetwork("4", genericOption, nil, getIPv4Data(t, ""), nil); err != nil { 453 t.Fatalf("Failed to create bridge: %v", err) 454 } 455 456 verifyV4INCEntries(d.networks, t) 457 458 if err := d.DeleteNetwork("1"); err != nil { 459 t.Log(err) 460 } 461 verifyV4INCEntries(d.networks, t) 462 463 if err := d.DeleteNetwork("2"); err != nil { 464 t.Log(err) 465 } 466 verifyV4INCEntries(d.networks, t) 467 468 if err := d.DeleteNetwork("3"); err != nil { 469 t.Log(err) 470 } 471 verifyV4INCEntries(d.networks, t) 472 473 if err := d.DeleteNetwork("4"); err != nil { 474 t.Log(err) 475 } 476 verifyV4INCEntries(d.networks, t) 477 } 478 479 // Verify the network isolation rules are installed for each network 480 func verifyV4INCEntries(networks map[string]*bridgeNetwork, t *testing.T) { 481 iptable := iptables.GetIptable(iptables.IPv4) 482 out1, err := iptable.Raw("-S", IsolationChain1) 483 if err != nil { 484 t.Fatal(err) 485 } 486 out2, err := iptable.Raw("-S", IsolationChain2) 487 if err != nil { 488 t.Fatal(err) 489 } 490 491 for _, n := range networks { 492 re := regexp.MustCompile(fmt.Sprintf("-i %s ! -o %s -j %s", n.config.BridgeName, n.config.BridgeName, IsolationChain2)) 493 matches := re.FindAllString(string(out1[:]), -1) 494 if len(matches) != 1 { 495 t.Fatalf("Cannot find expected inter-network isolation rules in IP Tables for network %s:\n%s.", n.id, string(out1[:])) 496 } 497 re = regexp.MustCompile(fmt.Sprintf("-o %s -j DROP", n.config.BridgeName)) 498 matches = re.FindAllString(string(out2[:]), -1) 499 if len(matches) != 1 { 500 t.Fatalf("Cannot find expected inter-network isolation rules in IP Tables for network %s:\n%s.", n.id, string(out2[:])) 501 } 502 } 503 } 504 505 type testInterface struct { 506 mac net.HardwareAddr 507 addr *net.IPNet 508 addrv6 *net.IPNet 509 srcName string 510 dstName string 511 } 512 513 type testEndpoint struct { 514 iface *testInterface 515 gw net.IP 516 gw6 net.IP 517 routes []types.StaticRoute 518 } 519 520 func newTestEndpoint(nw *net.IPNet, ordinal byte) *testEndpoint { 521 addr := types.GetIPNetCopy(nw) 522 addr.IP[len(addr.IP)-1] = ordinal 523 return &testEndpoint{iface: &testInterface{addr: addr}} 524 } 525 526 func (te *testEndpoint) Interface() driverapi.InterfaceInfo { 527 if te.iface != nil { 528 return te.iface 529 } 530 531 return nil 532 } 533 534 func (i *testInterface) MacAddress() net.HardwareAddr { 535 return i.mac 536 } 537 538 func (i *testInterface) Address() *net.IPNet { 539 return i.addr 540 } 541 542 func (i *testInterface) AddressIPv6() *net.IPNet { 543 return i.addrv6 544 } 545 546 func (i *testInterface) SetMacAddress(mac net.HardwareAddr) error { 547 if i.mac != nil { 548 return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", i.mac, mac) 549 } 550 if mac == nil { 551 return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface") 552 } 553 i.mac = types.GetMacCopy(mac) 554 return nil 555 } 556 557 func (i *testInterface) SetIPAddress(address *net.IPNet) error { 558 if address.IP == nil { 559 return types.BadRequestErrorf("tried to set nil IP address to endpoint interface") 560 } 561 if address.IP.To4() == nil { 562 return setAddress(&i.addrv6, address) 563 } 564 return setAddress(&i.addr, address) 565 } 566 567 func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error { 568 if *ifaceAddr != nil { 569 return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address) 570 } 571 *ifaceAddr = types.GetIPNetCopy(address) 572 return nil 573 } 574 575 func (i *testInterface) SetNames(srcName string, dstName string) error { 576 i.srcName = srcName 577 i.dstName = dstName 578 return nil 579 } 580 581 func (te *testEndpoint) InterfaceName() driverapi.InterfaceNameInfo { 582 if te.iface != nil { 583 return te.iface 584 } 585 586 return nil 587 } 588 589 func (te *testEndpoint) SetGateway(gw net.IP) error { 590 te.gw = gw 591 return nil 592 } 593 594 func (te *testEndpoint) SetGatewayIPv6(gw6 net.IP) error { 595 te.gw6 = gw6 596 return nil 597 } 598 599 func (te *testEndpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error { 600 te.routes = append(te.routes, types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop}) 601 return nil 602 } 603 604 func (te *testEndpoint) AddTableEntry(tableName string, key string, value []byte) error { 605 return nil 606 } 607 608 func (te *testEndpoint) DisableGatewayService() {} 609 610 func TestQueryEndpointInfo(t *testing.T) { 611 testQueryEndpointInfo(t, true) 612 } 613 614 func TestQueryEndpointInfoHairpin(t *testing.T) { 615 testQueryEndpointInfo(t, false) 616 } 617 618 func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) { 619 if !testutils.IsRunningInContainer() { 620 defer testutils.SetupTestOSContext(t)() 621 } 622 d := newDriver() 623 624 config := &configuration{ 625 EnableIPTables: true, 626 EnableUserlandProxy: ulPxyEnabled, 627 } 628 genericOption := make(map[string]interface{}) 629 genericOption[netlabel.GenericData] = config 630 631 if err := d.configure(genericOption); err != nil { 632 t.Fatalf("Failed to setup driver config: %v", err) 633 } 634 635 netconfig := &networkConfiguration{ 636 BridgeName: DefaultBridgeName, 637 EnableICC: false, 638 } 639 genericOption = make(map[string]interface{}) 640 genericOption[netlabel.GenericData] = netconfig 641 642 ipdList := getIPv4Data(t, "") 643 err := d.CreateNetwork("net1", genericOption, nil, ipdList, nil) 644 if err != nil { 645 t.Fatalf("Failed to create bridge: %v", err) 646 } 647 648 sbOptions := make(map[string]interface{}) 649 sbOptions[netlabel.PortMap] = getPortMapping() 650 651 te := newTestEndpoint(ipdList[0].Pool, 11) 652 err = d.CreateEndpoint("net1", "ep1", te.Interface(), nil) 653 if err != nil { 654 t.Fatalf("Failed to create an endpoint : %s", err.Error()) 655 } 656 657 err = d.Join("net1", "ep1", "sbox", te, sbOptions) 658 if err != nil { 659 t.Fatalf("Failed to join the endpoint: %v", err) 660 } 661 662 err = d.ProgramExternalConnectivity("net1", "ep1", sbOptions) 663 if err != nil { 664 t.Fatalf("Failed to program external connectivity: %v", err) 665 } 666 667 network, ok := d.networks["net1"] 668 if !ok { 669 t.Fatalf("Cannot find network %s inside driver", "net1") 670 } 671 ep := network.endpoints["ep1"] 672 data, err := d.EndpointOperInfo(network.id, ep.id) 673 if err != nil { 674 t.Fatalf("Failed to ask for endpoint operational data: %v", err) 675 } 676 pmd, ok := data[netlabel.PortMap] 677 if !ok { 678 t.Fatal("Endpoint operational data does not contain port mapping data") 679 } 680 pm, ok := pmd.([]types.PortBinding) 681 if !ok { 682 t.Fatal("Unexpected format for port mapping in endpoint operational data") 683 } 684 if len(ep.portMapping) != len(pm) { 685 t.Fatal("Incomplete data for port mapping in endpoint operational data") 686 } 687 for i, pb := range ep.portMapping { 688 if !pb.Equal(&pm[i]) { 689 t.Fatal("Unexpected data for port mapping in endpoint operational data") 690 } 691 } 692 693 err = d.RevokeExternalConnectivity("net1", "ep1") 694 if err != nil { 695 t.Fatal(err) 696 } 697 698 // release host mapped ports 699 err = d.Leave("net1", "ep1") 700 if err != nil { 701 t.Fatal(err) 702 } 703 } 704 705 func getExposedPorts() []types.TransportPort { 706 return []types.TransportPort{ 707 {Proto: types.TCP, Port: uint16(5000)}, 708 {Proto: types.UDP, Port: uint16(400)}, 709 {Proto: types.TCP, Port: uint16(600)}, 710 } 711 } 712 713 func getPortMapping() []types.PortBinding { 714 return []types.PortBinding{ 715 {Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)}, 716 {Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)}, 717 {Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)}, 718 } 719 } 720 721 func TestLinkContainers(t *testing.T) { 722 if !testutils.IsRunningInContainer() { 723 defer testutils.SetupTestOSContext(t)() 724 } 725 726 d := newDriver() 727 iptable := iptables.GetIptable(iptables.IPv4) 728 729 config := &configuration{ 730 EnableIPTables: true, 731 } 732 genericOption := make(map[string]interface{}) 733 genericOption[netlabel.GenericData] = config 734 735 if err := d.configure(genericOption); err != nil { 736 t.Fatalf("Failed to setup driver config: %v", err) 737 } 738 739 netconfig := &networkConfiguration{ 740 BridgeName: DefaultBridgeName, 741 EnableICC: false, 742 } 743 genericOption = make(map[string]interface{}) 744 genericOption[netlabel.GenericData] = netconfig 745 746 ipdList := getIPv4Data(t, "") 747 err := d.CreateNetwork("net1", genericOption, nil, ipdList, nil) 748 if err != nil { 749 t.Fatalf("Failed to create bridge: %v", err) 750 } 751 752 te1 := newTestEndpoint(ipdList[0].Pool, 11) 753 err = d.CreateEndpoint("net1", "ep1", te1.Interface(), nil) 754 if err != nil { 755 t.Fatalf("Failed to create an endpoint : %s", err.Error()) 756 } 757 758 exposedPorts := getExposedPorts() 759 sbOptions := make(map[string]interface{}) 760 sbOptions[netlabel.ExposedPorts] = exposedPorts 761 762 err = d.Join("net1", "ep1", "sbox", te1, sbOptions) 763 if err != nil { 764 t.Fatalf("Failed to join the endpoint: %v", err) 765 } 766 767 err = d.ProgramExternalConnectivity("net1", "ep1", sbOptions) 768 if err != nil { 769 t.Fatalf("Failed to program external connectivity: %v", err) 770 } 771 772 addr1 := te1.iface.addr 773 if addr1.IP.To4() == nil { 774 t.Fatal("No Ipv4 address assigned to the endpoint: ep1") 775 } 776 777 te2 := newTestEndpoint(ipdList[0].Pool, 22) 778 err = d.CreateEndpoint("net1", "ep2", te2.Interface(), nil) 779 if err != nil { 780 t.Fatalf("Failed to create an endpoint : %s", err.Error()) 781 } 782 783 addr2 := te2.iface.addr 784 if addr2.IP.To4() == nil { 785 t.Fatal("No Ipv4 address assigned to the endpoint: ep2") 786 } 787 788 sbOptions = make(map[string]interface{}) 789 sbOptions[netlabel.GenericData] = options.Generic{ 790 "ChildEndpoints": []string{"ep1"}, 791 } 792 793 err = d.Join("net1", "ep2", "", te2, sbOptions) 794 if err != nil { 795 t.Fatal("Failed to link ep1 and ep2") 796 } 797 798 err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions) 799 if err != nil { 800 t.Fatalf("Failed to program external connectivity: %v", err) 801 } 802 803 out, _ := iptable.Raw("-L", DockerChain) 804 for _, pm := range exposedPorts { 805 regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port) 806 re := regexp.MustCompile(regex) 807 matches := re.FindAllString(string(out[:]), -1) 808 if len(matches) != 1 { 809 t.Fatalf("IP Tables programming failed %s", string(out[:])) 810 } 811 812 regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port) 813 matched, _ := regexp.MatchString(regex, string(out[:])) 814 if !matched { 815 t.Fatalf("IP Tables programming failed %s", string(out[:])) 816 } 817 } 818 819 err = d.RevokeExternalConnectivity("net1", "ep2") 820 if err != nil { 821 t.Fatalf("Failed to revoke external connectivity: %v", err) 822 } 823 824 err = d.Leave("net1", "ep2") 825 if err != nil { 826 t.Fatal("Failed to unlink ep1 and ep2") 827 } 828 829 out, _ = iptable.Raw("-L", DockerChain) 830 for _, pm := range exposedPorts { 831 regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port) 832 re := regexp.MustCompile(regex) 833 matches := re.FindAllString(string(out[:]), -1) 834 if len(matches) != 0 { 835 t.Fatalf("Leave should have deleted relevant IPTables rules %s", string(out[:])) 836 } 837 838 regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port) 839 matched, _ := regexp.MatchString(regex, string(out[:])) 840 if matched { 841 t.Fatalf("Leave should have deleted relevant IPTables rules %s", string(out[:])) 842 } 843 } 844 845 // Error condition test with an invalid endpoint-id "ep4" 846 sbOptions = make(map[string]interface{}) 847 sbOptions[netlabel.GenericData] = options.Generic{ 848 "ChildEndpoints": []string{"ep1", "ep4"}, 849 } 850 851 err = d.Join("net1", "ep2", "", te2, sbOptions) 852 if err != nil { 853 t.Fatal(err) 854 } 855 err = d.ProgramExternalConnectivity("net1", "ep2", sbOptions) 856 if err != nil { 857 out, _ = iptable.Raw("-L", DockerChain) 858 for _, pm := range exposedPorts { 859 regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port) 860 re := regexp.MustCompile(regex) 861 matches := re.FindAllString(string(out[:]), -1) 862 if len(matches) != 0 { 863 t.Fatalf("Error handling should rollback relevant IPTables rules %s", string(out[:])) 864 } 865 866 regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port) 867 matched, _ := regexp.MatchString(regex, string(out[:])) 868 if matched { 869 t.Fatalf("Error handling should rollback relevant IPTables rules %s", string(out[:])) 870 } 871 } 872 } else { 873 t.Fatal("Expected Join to fail given link conditions are not satisfied") 874 } 875 } 876 877 func TestValidateConfig(t *testing.T) { 878 if !testutils.IsRunningInContainer() { 879 defer testutils.SetupTestOSContext(t)() 880 } 881 882 // Test mtu 883 c := networkConfiguration{Mtu: -2} 884 err := c.Validate() 885 if err == nil { 886 t.Fatal("Failed to detect invalid MTU number") 887 } 888 889 c.Mtu = 9000 890 err = c.Validate() 891 if err != nil { 892 t.Fatal("unexpected validation error on MTU number") 893 } 894 895 // Bridge network 896 _, network, _ := net.ParseCIDR("172.28.0.0/16") 897 c = networkConfiguration{ 898 AddressIPv4: network, 899 } 900 901 err = c.Validate() 902 if err != nil { 903 t.Fatal(err) 904 } 905 906 // Test v4 gw 907 c.DefaultGatewayIPv4 = net.ParseIP("172.27.30.234") 908 err = c.Validate() 909 if err == nil { 910 t.Fatal("Failed to detect invalid default gateway") 911 } 912 913 c.DefaultGatewayIPv4 = net.ParseIP("172.28.30.234") 914 err = c.Validate() 915 if err != nil { 916 t.Fatal("Unexpected validation error on default gateway") 917 } 918 919 // Test v6 gw 920 _, v6nw, _ := net.ParseCIDR("2001:db8:ae:b004::/64") 921 c = networkConfiguration{ 922 EnableIPv6: true, 923 AddressIPv6: v6nw, 924 DefaultGatewayIPv6: net.ParseIP("2001:db8:ac:b004::bad:a55"), 925 } 926 err = c.Validate() 927 if err == nil { 928 t.Fatal("Failed to detect invalid v6 default gateway") 929 } 930 931 c.DefaultGatewayIPv6 = net.ParseIP("2001:db8:ae:b004::bad:a55") 932 err = c.Validate() 933 if err != nil { 934 t.Fatal("Unexpected validation error on v6 default gateway") 935 } 936 937 c.AddressIPv6 = nil 938 err = c.Validate() 939 if err == nil { 940 t.Fatal("Failed to detect invalid v6 default gateway") 941 } 942 943 c.AddressIPv6 = nil 944 err = c.Validate() 945 if err == nil { 946 t.Fatal("Failed to detect invalid v6 default gateway") 947 } 948 } 949 950 func TestSetDefaultGw(t *testing.T) { 951 if !testutils.IsRunningInContainer() { 952 defer testutils.SetupTestOSContext(t)() 953 } 954 955 d := newDriver() 956 957 if err := d.configure(nil); err != nil { 958 t.Fatalf("Failed to setup driver config: %v", err) 959 } 960 961 _, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80") 962 963 ipdList := getIPv4Data(t, "") 964 gw4 := types.GetIPCopy(ipdList[0].Pool.IP).To4() 965 gw4[3] = 254 966 gw6 := net.ParseIP("2001:db8:ea9:9abc:b0c4::254") 967 968 config := &networkConfiguration{ 969 BridgeName: DefaultBridgeName, 970 AddressIPv6: subnetv6, 971 DefaultGatewayIPv4: gw4, 972 DefaultGatewayIPv6: gw6, 973 } 974 975 genericOption := make(map[string]interface{}) 976 genericOption[netlabel.EnableIPv6] = true 977 genericOption[netlabel.GenericData] = config 978 979 err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil) 980 if err != nil { 981 t.Fatalf("Failed to create bridge: %v", err) 982 } 983 984 te := newTestEndpoint(ipdList[0].Pool, 10) 985 err = d.CreateEndpoint("dummy", "ep", te.Interface(), nil) 986 if err != nil { 987 t.Fatalf("Failed to create endpoint: %v", err) 988 } 989 990 err = d.Join("dummy", "ep", "sbox", te, nil) 991 if err != nil { 992 t.Fatalf("Failed to join endpoint: %v", err) 993 } 994 995 if !gw4.Equal(te.gw) { 996 t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw4, te.gw) 997 } 998 999 if !gw6.Equal(te.gw6) { 1000 t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw6, te.gw6) 1001 } 1002 } 1003 1004 func TestCleanupIptableRules(t *testing.T) { 1005 defer testutils.SetupTestOSContext(t)() 1006 bridgeChain := []iptables.ChainInfo{ 1007 {Name: DockerChain, Table: iptables.Nat}, 1008 {Name: DockerChain, Table: iptables.Filter}, 1009 {Name: IsolationChain1, Table: iptables.Filter}, 1010 } 1011 1012 ipVersions := []iptables.IPVersion{iptables.IPv4, iptables.IPv6} 1013 1014 for _, version := range ipVersions { 1015 if _, _, _, _, err := setupIPChains(&configuration{EnableIPTables: true}, version); err != nil { 1016 t.Fatalf("Error setting up ip chains for %s: %v", version, err) 1017 } 1018 1019 iptable := iptables.GetIptable(version) 1020 for _, chainInfo := range bridgeChain { 1021 if !iptable.ExistChain(chainInfo.Name, chainInfo.Table) { 1022 t.Fatalf("iptables version %s chain %s of %s table should have been created", version, chainInfo.Name, chainInfo.Table) 1023 } 1024 } 1025 removeIPChains(version) 1026 for _, chainInfo := range bridgeChain { 1027 if iptable.ExistChain(chainInfo.Name, chainInfo.Table) { 1028 t.Fatalf("iptables version %s chain %s of %s table should have been deleted", version, chainInfo.Name, chainInfo.Table) 1029 } 1030 } 1031 } 1032 } 1033 1034 func TestCreateWithExistingBridge(t *testing.T) { 1035 defer testutils.SetupTestOSContext(t)() 1036 d := newDriver() 1037 1038 if err := d.configure(nil); err != nil { 1039 t.Fatalf("Failed to setup driver config: %v", err) 1040 } 1041 1042 brName := "br111" 1043 br := &netlink.Bridge{ 1044 LinkAttrs: netlink.LinkAttrs{ 1045 Name: brName, 1046 }, 1047 } 1048 if err := netlink.LinkAdd(br); err != nil { 1049 t.Fatalf("Failed to create bridge interface: %v", err) 1050 } 1051 defer netlink.LinkDel(br) 1052 if err := netlink.LinkSetUp(br); err != nil { 1053 t.Fatalf("Failed to set bridge interface up: %v", err) 1054 } 1055 1056 ip := net.IP{192, 168, 122, 1} 1057 addr := &netlink.Addr{IPNet: &net.IPNet{ 1058 IP: ip, 1059 Mask: net.IPv4Mask(255, 255, 255, 0), 1060 }} 1061 if err := netlink.AddrAdd(br, addr); err != nil { 1062 t.Fatalf("Failed to add IP address to bridge: %v", err) 1063 } 1064 1065 netconfig := &networkConfiguration{BridgeName: brName} 1066 genericOption := make(map[string]interface{}) 1067 genericOption[netlabel.GenericData] = netconfig 1068 1069 if err := d.CreateNetwork(brName, genericOption, nil, getIPv4Data(t, brName), nil); err != nil { 1070 t.Fatalf("Failed to create bridge network: %v", err) 1071 } 1072 1073 nw, err := d.getNetwork(brName) 1074 if err != nil { 1075 t.Fatalf("Failed to getNetwork(%s): %v", brName, err) 1076 } 1077 1078 addrs4, _, err := nw.bridge.addresses() 1079 if err != nil { 1080 t.Fatalf("Failed to get the bridge network's address: %v", err) 1081 } 1082 1083 if !addrs4[0].IP.Equal(ip) { 1084 t.Fatal("Creating bridge network with existing bridge interface unexpectedly modified the IP address of the bridge") 1085 } 1086 1087 if err := d.DeleteNetwork(brName); err != nil { 1088 t.Fatalf("Failed to delete network %s: %v", brName, err) 1089 } 1090 1091 if _, err := netlink.LinkByName(brName); err != nil { 1092 t.Fatal("Deleting bridge network that using existing bridge interface unexpectedly deleted the bridge interface") 1093 } 1094 } 1095 1096 func TestCreateParallel(t *testing.T) { 1097 if !testutils.IsRunningInContainer() { 1098 defer testutils.SetupTestOSContext(t)() 1099 } 1100 1101 d := newDriver() 1102 1103 if err := d.configure(nil); err != nil { 1104 t.Fatalf("Failed to setup driver config: %v", err) 1105 } 1106 1107 ch := make(chan error, 100) 1108 for i := 0; i < 100; i++ { 1109 go func(name string, ch chan<- error) { 1110 config := &networkConfiguration{BridgeName: name} 1111 genericOption := make(map[string]interface{}) 1112 genericOption[netlabel.GenericData] = config 1113 if err := d.CreateNetwork(name, genericOption, nil, getIPv4Data(t, "docker0"), nil); err != nil { 1114 ch <- fmt.Errorf("failed to create %s", name) 1115 return 1116 } 1117 if err := d.CreateNetwork(name, genericOption, nil, getIPv4Data(t, "docker0"), nil); err == nil { 1118 ch <- fmt.Errorf("failed was able to create overlap %s", name) 1119 return 1120 } 1121 ch <- nil 1122 }("net"+strconv.Itoa(i), ch) 1123 } 1124 // wait for the go routines 1125 var success int 1126 for i := 0; i < 100; i++ { 1127 val := <-ch 1128 if val == nil { 1129 success++ 1130 } 1131 } 1132 if success != 1 { 1133 t.Fatalf("Success should be 1 instead: %d", success) 1134 } 1135 }