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