diff --git a/integration/network/ipvlan/ipvlan_test.go b/integration/network/ipvlan/ipvlan_test.go index 130b60d953204..37e3dd0b303bd 100644 --- a/integration/network/ipvlan/ipvlan_test.go +++ b/integration/network/ipvlan/ipvlan_test.go @@ -58,7 +58,7 @@ func TestDockerNetworkIpvlan(t *testing.T) { for _, tc := range []struct { name string - test func(context.Context, dclient.APIClient) func(*testing.T) + test func(*testing.T, context.Context, dclient.APIClient) }{ { name: "Subinterface", @@ -96,326 +96,308 @@ func TestDockerNetworkIpvlan(t *testing.T) { t.Cleanup(func() { d.Stop(t) }) d.StartWithBusybox(ctx, t) c := d.NewClientT(t) - tc.test(ctx, c) + tc.test(t, ctx, c) }) // FIXME(vdemeester) clean network } } -func testIpvlanSubinterface(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - master := "di-dummy0" - n.CreateMasterDummy(ctx, t, master) - defer n.DeleteInterface(ctx, t, master) - - netName := "di-subinterface" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("di-dummy0.60", ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - // delete the network while preserving the parent link - err := client.NetworkRemove(ctx, netName) - assert.NilError(t, err) - - assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) - // verify the network delete did not delete the predefined link - n.LinkExists(ctx, t, "di-dummy0") - } +func testIpvlanSubinterface(t *testing.T, ctx context.Context, client dclient.APIClient) { + master := "di-dummy0" + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + + netName := "di-subinterface" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("di-dummy0.60", ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + // delete the network while preserving the parent link + err := client.NetworkRemove(ctx, netName) + assert.NilError(t, err) + + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) + // verify the network delete did not delete the predefined link + n.LinkExists(ctx, t, "di-dummy0") } -func testIpvlanOverlapParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - // verify the same parent interface cannot be used if already in use by an existing network - master := "di-dummy0" - parent := master + ".30" - n.CreateMasterDummy(ctx, t, master) - defer n.DeleteInterface(ctx, t, master) - n.CreateVlanInterface(ctx, t, master, parent, "30") - - netName := "di-subinterface" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan(parent, ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - _, err := net.Create(ctx, client, netName, - net.WithIPvlan(parent, ""), - ) - // verify that the overlap returns an error - assert.Check(t, err != nil) - } +func testIpvlanOverlapParent(t *testing.T, ctx context.Context, client dclient.APIClient) { + // verify the same parent interface cannot be used if already in use by an existing network + master := "di-dummy0" + parent := master + ".30" + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + n.CreateVlanInterface(ctx, t, master, parent, "30") + + netName := "di-subinterface" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan(parent, ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + _, err := net.Create(ctx, client, netName, + net.WithIPvlan(parent, ""), + ) + // verify that the overlap returns an error + assert.Check(t, err != nil) } -func testIpvlanL2NilParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - // ipvlan l2 mode - dummy parent interface is provisioned dynamically - netName := "di-nil-parent" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) +func testIpvlanL2NilParent(t *testing.T, ctx context.Context, client dclient.APIClient) { + // ipvlan l2 mode - dummy parent interface is provisioned dynamically + netName := "di-nil-parent" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.NilError(t, err) - } + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.NilError(t, err) } -func testIpvlanL2InternalMode(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "di-internal" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", ""), - net.WithInternal(), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) +func testIpvlanL2InternalMode(t *testing.T, ctx context.Context, client dclient.APIClient) { + netName := "di-internal" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", ""), + net.WithInternal(), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) - assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) + result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) + assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.NilError(t, err) - } + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.NilError(t, err) } -func testIpvlanL3NilParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "di-nil-parent-l3" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", "l3"), - net.WithIPAM("172.28.230.0/24", ""), - net.WithIPAM("172.28.220.0/24", ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - id1 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.220.10"), - ) - id2 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.230.10"), - ) - - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.NilError(t, err) - } +func testIpvlanL3NilParent(t *testing.T, ctx context.Context, client dclient.APIClient) { + netName := "di-nil-parent-l3" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", "l3"), + net.WithIPAM("172.28.230.0/24", ""), + net.WithIPAM("172.28.220.0/24", ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + id1 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.220.10"), + ) + id2 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.230.10"), + ) + + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.NilError(t, err) } -func testIpvlanL3InternalMode(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "di-internal-l3" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", "l3"), - net.WithInternal(), - net.WithIPAM("172.28.230.0/24", ""), - net.WithIPAM("172.28.220.0/24", ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - id1 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.220.10"), - ) - id2 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.230.10"), - ) - - result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) - assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) - - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.NilError(t, err) - } +func testIpvlanL3InternalMode(t *testing.T, ctx context.Context, client dclient.APIClient) { + netName := "di-internal-l3" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", "l3"), + net.WithInternal(), + net.WithIPAM("172.28.230.0/24", ""), + net.WithIPAM("172.28.220.0/24", ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + id1 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.220.10"), + ) + id2 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.230.10"), + ) + + result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) + assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) + + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.NilError(t, err) } -func testIpvlanL2MultiSubnet(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "dualstackl2" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", ""), - net.WithIPv6(), - net.WithIPAM("172.28.200.0/24", ""), - net.WithIPAM("172.28.202.0/24", "172.28.202.254"), - net.WithIPAM("2001:db8:abc8::/64", ""), - net.WithIPAM("2001:db8:abc6::/64", "2001:db8:abc6::254"), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - id1 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.200.20"), - container.WithIPv6(netName, "2001:db8:abc8::20"), - ) - id2 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.200.21"), - container.WithIPv6(netName, "2001:db8:abc8::21"), - ) - c1, err := client.ContainerInspect(ctx, id1) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks[netName].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks[netName].GlobalIPv6Address}) - assert.NilError(t, err) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 - id3 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.202.20"), - container.WithIPv6(netName, "2001:db8:abc6::20"), - ) - id4 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.202.21"), - container.WithIPv6(netName, "2001:db8:abc6::21"), - ) - c3, err := client.ContainerInspect(ctx, id3) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks[netName].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks[netName].GlobalIPv6Address}) - assert.NilError(t, err) - - // Inspect the v4 gateway to ensure the proper default GW was assigned - assert.Equal(t, c1.NetworkSettings.Networks[netName].Gateway, "172.28.200.1") - // Inspect the v6 gateway to ensure the proper default GW was assigned - assert.Equal(t, c1.NetworkSettings.Networks[netName].IPv6Gateway, "2001:db8:abc8::1") - // Inspect the v4 gateway to ensure the proper explicitly assigned default GW was assigned - assert.Equal(t, c3.NetworkSettings.Networks[netName].Gateway, "172.28.202.254") - // Inspect the v6 gateway to ensure the proper explicitly assigned default GW was assigned - assert.Equal(t, c3.NetworkSettings.Networks[netName].IPv6Gateway, "2001:db8:abc6::254") - } +func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, client dclient.APIClient) { + netName := "dualstackl2" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", ""), + net.WithIPv6(), + net.WithIPAM("172.28.200.0/24", ""), + net.WithIPAM("172.28.202.0/24", "172.28.202.254"), + net.WithIPAM("2001:db8:abc8::/64", ""), + net.WithIPAM("2001:db8:abc6::/64", "2001:db8:abc6::254"), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 + id1 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.200.20"), + container.WithIPv6(netName, "2001:db8:abc8::20"), + ) + id2 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.200.21"), + container.WithIPv6(netName, "2001:db8:abc8::21"), + ) + c1, err := client.ContainerInspect(ctx, id1) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks[netName].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks[netName].GlobalIPv6Address}) + assert.NilError(t, err) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 + id3 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.202.20"), + container.WithIPv6(netName, "2001:db8:abc6::20"), + ) + id4 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.202.21"), + container.WithIPv6(netName, "2001:db8:abc6::21"), + ) + c3, err := client.ContainerInspect(ctx, id3) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks[netName].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks[netName].GlobalIPv6Address}) + assert.NilError(t, err) + + // Inspect the v4 gateway to ensure the proper default GW was assigned + assert.Equal(t, c1.NetworkSettings.Networks[netName].Gateway, "172.28.200.1") + // Inspect the v6 gateway to ensure the proper default GW was assigned + assert.Equal(t, c1.NetworkSettings.Networks[netName].IPv6Gateway, "2001:db8:abc8::1") + // Inspect the v4 gateway to ensure the proper explicitly assigned default GW was assigned + assert.Equal(t, c3.NetworkSettings.Networks[netName].Gateway, "172.28.202.254") + // Inspect the v6 gateway to ensure the proper explicitly assigned default GW was assigned + assert.Equal(t, c3.NetworkSettings.Networks[netName].IPv6Gateway, "2001:db8:abc6::254") } -func testIpvlanL3MultiSubnet(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "dualstackl3" - net.CreateNoError(ctx, t, client, netName, - net.WithIPvlan("", "l3"), - net.WithIPv6(), - net.WithIPAM("172.28.10.0/24", ""), - net.WithIPAM("172.28.12.0/24", "172.28.12.254"), - net.WithIPAM("2001:db8:abc9::/64", ""), - net.WithIPAM("2001:db8:abc7::/64", "2001:db8:abc7::254"), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - id1 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.10.20"), - container.WithIPv6(netName, "2001:db8:abc9::20"), - ) - id2 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.10.21"), - container.WithIPv6(netName, "2001:db8:abc9::21"), - ) - c1, err := client.ContainerInspect(ctx, id1) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks[netName].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks[netName].GlobalIPv6Address}) - assert.NilError(t, err) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 - id3 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.12.20"), - container.WithIPv6(netName, "2001:db8:abc7::20"), - ) - id4 := container.Run(ctx, t, client, - container.WithNetworkMode(netName), - container.WithIPv4(netName, "172.28.12.21"), - container.WithIPv6(netName, "2001:db8:abc7::21"), - ) - c3, err := client.ContainerInspect(ctx, id3) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks[netName].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks[netName].GlobalIPv6Address}) - assert.NilError(t, err) - - // Inspect the v4 gateway to ensure no next hop is assigned in L3 mode - assert.Equal(t, c1.NetworkSettings.Networks[netName].Gateway, "") - // Inspect the v6 gateway to ensure the explicitly specified default GW is ignored per L3 mode enabled - assert.Equal(t, c1.NetworkSettings.Networks[netName].IPv6Gateway, "") - // Inspect the v4 gateway to ensure no next hop is assigned in L3 mode - assert.Equal(t, c3.NetworkSettings.Networks[netName].Gateway, "") - // Inspect the v6 gateway to ensure the explicitly specified default GW is ignored per L3 mode enabled - assert.Equal(t, c3.NetworkSettings.Networks[netName].IPv6Gateway, "") - } +func testIpvlanL3MultiSubnet(t *testing.T, ctx context.Context, client dclient.APIClient) { + netName := "dualstackl3" + net.CreateNoError(ctx, t, client, netName, + net.WithIPvlan("", "l3"), + net.WithIPv6(), + net.WithIPAM("172.28.10.0/24", ""), + net.WithIPAM("172.28.12.0/24", "172.28.12.254"), + net.WithIPAM("2001:db8:abc9::/64", ""), + net.WithIPAM("2001:db8:abc7::/64", "2001:db8:abc7::254"), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 + id1 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.10.20"), + container.WithIPv6(netName, "2001:db8:abc9::20"), + ) + id2 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.10.21"), + container.WithIPv6(netName, "2001:db8:abc9::21"), + ) + c1, err := client.ContainerInspect(ctx, id1) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks[netName].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks[netName].GlobalIPv6Address}) + assert.NilError(t, err) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 + id3 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.12.20"), + container.WithIPv6(netName, "2001:db8:abc7::20"), + ) + id4 := container.Run(ctx, t, client, + container.WithNetworkMode(netName), + container.WithIPv4(netName, "172.28.12.21"), + container.WithIPv6(netName, "2001:db8:abc7::21"), + ) + c3, err := client.ContainerInspect(ctx, id3) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks[netName].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks[netName].GlobalIPv6Address}) + assert.NilError(t, err) + + // Inspect the v4 gateway to ensure no next hop is assigned in L3 mode + assert.Equal(t, c1.NetworkSettings.Networks[netName].Gateway, "") + // Inspect the v6 gateway to ensure the explicitly specified default GW is ignored per L3 mode enabled + assert.Equal(t, c1.NetworkSettings.Networks[netName].IPv6Gateway, "") + // Inspect the v4 gateway to ensure no next hop is assigned in L3 mode + assert.Equal(t, c3.NetworkSettings.Networks[netName].Gateway, "") + // Inspect the v6 gateway to ensure the explicitly specified default GW is ignored per L3 mode enabled + assert.Equal(t, c3.NetworkSettings.Networks[netName].IPv6Gateway, "") } -func testIpvlanAddressing(ctx context.Context, client dclient.APIClient) func(*testing.T) { - return func(t *testing.T) { - // Verify ipvlan l2 mode sets the proper default gateway routes via netlink - // for either an explicitly set route by the user or inferred via default IPAM - netNameL2 := "dualstackl2" - net.CreateNoError(ctx, t, client, netNameL2, - net.WithIPvlan("", "l2"), - net.WithIPv6(), - net.WithIPAM("172.28.140.0/24", "172.28.140.254"), - net.WithIPAM("2001:db8:abcb::/64", ""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL2)) - - id1 := container.Run(ctx, t, client, - container.WithNetworkMode(netNameL2), - ) - // Validate ipvlan l2 mode defaults gateway sets the default IPAM next-hop inferred from the subnet - result, err := container.Exec(ctx, client, id1, []string{"ip", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default via 172.28.140.254 dev eth0")) - // Validate ipvlan l2 mode sets the v6 gateway to the user specified default gateway/next-hop - result, err = container.Exec(ctx, client, id1, []string{"ip", "-6", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abcb::1 dev eth0")) - - // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops - netNameL3 := "dualstackl3" - net.CreateNoError(ctx, t, client, netNameL3, - net.WithIPvlan("", "l3"), - net.WithIPv6(), - net.WithIPAM("172.28.160.0/24", "172.28.160.254"), - net.WithIPAM("2001:db8:abcd::/64", "2001:db8:abcd::254"), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL3)) - - id2 := container.Run(ctx, t, client, - container.WithNetworkMode(netNameL3), - ) - // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops - result, err = container.Exec(ctx, client, id2, []string{"ip", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default dev eth0")) - // Validate ipvlan l3 mode sets the v6 gateway to dev eth0 and disregards any explicit or inferred next-hops - result, err = container.Exec(ctx, client, id2, []string{"ip", "-6", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default dev eth0")) - } +func testIpvlanAddressing(t *testing.T, ctx context.Context, client dclient.APIClient) { + // Verify ipvlan l2 mode sets the proper default gateway routes via netlink + // for either an explicitly set route by the user or inferred via default IPAM + netNameL2 := "dualstackl2" + net.CreateNoError(ctx, t, client, netNameL2, + net.WithIPvlan("", "l2"), + net.WithIPv6(), + net.WithIPAM("172.28.140.0/24", "172.28.140.254"), + net.WithIPAM("2001:db8:abcb::/64", ""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL2)) + + id1 := container.Run(ctx, t, client, + container.WithNetworkMode(netNameL2), + ) + // Validate ipvlan l2 mode defaults gateway sets the default IPAM next-hop inferred from the subnet + result, err := container.Exec(ctx, client, id1, []string{"ip", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default via 172.28.140.254 dev eth0")) + // Validate ipvlan l2 mode sets the v6 gateway to the user specified default gateway/next-hop + result, err = container.Exec(ctx, client, id1, []string{"ip", "-6", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abcb::1 dev eth0")) + + // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops + netNameL3 := "dualstackl3" + net.CreateNoError(ctx, t, client, netNameL3, + net.WithIPvlan("", "l3"), + net.WithIPv6(), + net.WithIPAM("172.28.160.0/24", "172.28.160.254"), + net.WithIPAM("2001:db8:abcd::/64", "2001:db8:abcd::254"), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL3)) + + id2 := container.Run(ctx, t, client, + container.WithNetworkMode(netNameL3), + ) + // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops + result, err = container.Exec(ctx, client, id2, []string{"ip", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default dev eth0")) + // Validate ipvlan l3 mode sets the v6 gateway to dev eth0 and disregards any explicit or inferred next-hops + result, err = container.Exec(ctx, client, id2, []string{"ip", "-6", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default dev eth0")) } var ( diff --git a/integration/network/macvlan/macvlan_test.go b/integration/network/macvlan/macvlan_test.go index c41373c5cad26..5b0a174eecce5 100644 --- a/integration/network/macvlan/macvlan_test.go +++ b/integration/network/macvlan/macvlan_test.go @@ -51,7 +51,7 @@ func TestDockerNetworkMacvlan(t *testing.T) { for _, tc := range []struct { name string - test func(context.Context, client.APIClient) func(*testing.T) + test func(*testing.T, context.Context, client.APIClient) }{ { name: "Subinterface", @@ -82,196 +82,184 @@ func TestDockerNetworkMacvlan(t *testing.T) { d.StartWithBusybox(ctx, t) c := d.NewClientT(t) - tc.test(ctx, c) + tc.test(t, ctx, c) }) // FIXME(vdemeester) clean network } } -func testMacvlanOverlapParent(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - // verify the same parent interface cannot be used if already in use by an existing network - master := "dm-dummy0" - n.CreateMasterDummy(ctx, t, master) - defer n.DeleteInterface(ctx, t, master) - - netName := "dm-subinterface" - parentName := "dm-dummy0.40" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(parentName), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - _, err := net.Create(ctx, client, "dm-parent-net-overlap", - net.WithMacvlan(parentName), - ) - assert.Check(t, err != nil) - - // delete the network while preserving the parent link - err = client.NetworkRemove(ctx, netName) - assert.NilError(t, err) - - assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) - // verify the network delete did not delete the predefined link - n.LinkExists(ctx, t, master) - } +func testMacvlanOverlapParent(t *testing.T, ctx context.Context, client client.APIClient) { + // verify the same parent interface cannot be used if already in use by an existing network + master := "dm-dummy0" + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + + netName := "dm-subinterface" + parentName := "dm-dummy0.40" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(parentName), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + _, err := net.Create(ctx, client, "dm-parent-net-overlap", + net.WithMacvlan(parentName), + ) + assert.Check(t, err != nil) + + // delete the network while preserving the parent link + err = client.NetworkRemove(ctx, netName) + assert.NilError(t, err) + + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) + // verify the network delete did not delete the predefined link + n.LinkExists(ctx, t, master) } -func testMacvlanSubinterface(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - // verify the same parent interface cannot be used if already in use by an existing network - master := "dm-dummy0" - parentName := "dm-dummy0.20" - n.CreateMasterDummy(ctx, t, master) - defer n.DeleteInterface(ctx, t, master) - n.CreateVlanInterface(ctx, t, master, parentName, "20") - - netName := "dm-subinterface" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(parentName), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - // delete the network while preserving the parent link - err := client.NetworkRemove(ctx, netName) - assert.NilError(t, err) - - assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) - // verify the network delete did not delete the predefined link - n.LinkExists(ctx, t, parentName) - } +func testMacvlanSubinterface(t *testing.T, ctx context.Context, client client.APIClient) { + // verify the same parent interface cannot be used if already in use by an existing network + master := "dm-dummy0" + parentName := "dm-dummy0.20" + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + n.CreateVlanInterface(ctx, t, master, parentName, "20") + + netName := "dm-subinterface" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(parentName), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + // delete the network while preserving the parent link + err := client.NetworkRemove(ctx, netName) + assert.NilError(t, err) + + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) + // verify the network delete did not delete the predefined link + n.LinkExists(ctx, t, parentName) } -func testMacvlanNilParent(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - // macvlan bridge mode - dummy parent interface is provisioned dynamically - netName := "dm-nil-parent" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(""), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) +func testMacvlanNilParent(t *testing.T, ctx context.Context, client client.APIClient) { + // macvlan bridge mode - dummy parent interface is provisioned dynamically + netName := "dm-nil-parent" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(""), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.Check(t, err == nil) - } + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.Check(t, err == nil) } -func testMacvlanInternalMode(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - // macvlan bridge mode - dummy parent interface is provisioned dynamically - netName := "dm-internal" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(""), - net.WithInternal(), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) +func testMacvlanInternalMode(t *testing.T, ctx context.Context, client client.APIClient) { + // macvlan bridge mode - dummy parent interface is provisioned dynamically + netName := "dm-internal" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(""), + net.WithInternal(), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) + id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) - result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) - assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) + result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) + assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) - _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) - assert.Check(t, err == nil) - } + _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) + assert.Check(t, err == nil) } -func testMacvlanMultiSubnet(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - netName := "dualstackbridge" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(""), - net.WithIPv6(), - net.WithIPAM("172.28.100.0/24", ""), - net.WithIPAM("172.28.102.0/24", "172.28.102.254"), - net.WithIPAM("2001:db8:abc2::/64", ""), - net.WithIPAM("2001:db8:abc4::/64", "2001:db8:abc4::254"), - ) - - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - id1 := container.Run(ctx, t, client, - container.WithNetworkMode("dualstackbridge"), - container.WithIPv4("dualstackbridge", "172.28.100.20"), - container.WithIPv6("dualstackbridge", "2001:db8:abc2::20"), - ) - id2 := container.Run(ctx, t, client, - container.WithNetworkMode("dualstackbridge"), - container.WithIPv4("dualstackbridge", "172.28.100.21"), - container.WithIPv6("dualstackbridge", "2001:db8:abc2::21"), - ) - c1, err := client.ContainerInspect(ctx, id1) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address second to first - _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) - assert.NilError(t, err) - - // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 - id3 := container.Run(ctx, t, client, - container.WithNetworkMode("dualstackbridge"), - container.WithIPv4("dualstackbridge", "172.28.102.20"), - container.WithIPv6("dualstackbridge", "2001:db8:abc4::20"), - ) - id4 := container.Run(ctx, t, client, - container.WithNetworkMode("dualstackbridge"), - container.WithIPv4("dualstackbridge", "172.28.102.21"), - container.WithIPv6("dualstackbridge", "2001:db8:abc4::21"), - ) - c3, err := client.ContainerInspect(ctx, id3) - assert.NilError(t, err) - - // verify ipv4 connectivity to the explicit --ipv address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].IPAddress}) - assert.NilError(t, err) - // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth - _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) - assert.NilError(t, err) - - // Inspect the v4 gateway to ensure the proper default GW was assigned - assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.100.1") - // Inspect the v6 gateway to ensure the proper default GW was assigned - assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc2::1") - // Inspect the v4 gateway to ensure the proper explicitly assigned default GW was assigned - assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.102.254") - // Inspect the v6 gateway to ensure the proper explicitly assigned default GW was assigned - assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc4::254") - } +func testMacvlanMultiSubnet(t *testing.T, ctx context.Context, client client.APIClient) { + netName := "dualstackbridge" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(""), + net.WithIPv6(), + net.WithIPAM("172.28.100.0/24", ""), + net.WithIPAM("172.28.102.0/24", "172.28.102.254"), + net.WithIPAM("2001:db8:abc2::/64", ""), + net.WithIPAM("2001:db8:abc4::/64", "2001:db8:abc4::254"), + ) + + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 + id1 := container.Run(ctx, t, client, + container.WithNetworkMode("dualstackbridge"), + container.WithIPv4("dualstackbridge", "172.28.100.20"), + container.WithIPv6("dualstackbridge", "2001:db8:abc2::20"), + ) + id2 := container.Run(ctx, t, client, + container.WithNetworkMode("dualstackbridge"), + container.WithIPv4("dualstackbridge", "172.28.100.21"), + container.WithIPv6("dualstackbridge", "2001:db8:abc2::21"), + ) + c1, err := client.ContainerInspect(ctx, id1) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address second to first + _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) + assert.NilError(t, err) + + // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 + id3 := container.Run(ctx, t, client, + container.WithNetworkMode("dualstackbridge"), + container.WithIPv4("dualstackbridge", "172.28.102.20"), + container.WithIPv6("dualstackbridge", "2001:db8:abc4::20"), + ) + id4 := container.Run(ctx, t, client, + container.WithNetworkMode("dualstackbridge"), + container.WithIPv4("dualstackbridge", "172.28.102.21"), + container.WithIPv6("dualstackbridge", "2001:db8:abc4::21"), + ) + c3, err := client.ContainerInspect(ctx, id3) + assert.NilError(t, err) + + // verify ipv4 connectivity to the explicit --ipv address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].IPAddress}) + assert.NilError(t, err) + // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth + _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) + assert.NilError(t, err) + + // Inspect the v4 gateway to ensure the proper default GW was assigned + assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.100.1") + // Inspect the v6 gateway to ensure the proper default GW was assigned + assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc2::1") + // Inspect the v4 gateway to ensure the proper explicitly assigned default GW was assigned + assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.102.254") + // Inspect the v6 gateway to ensure the proper explicitly assigned default GW was assigned + assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc4::254") } -func testMacvlanAddressing(ctx context.Context, client client.APIClient) func(*testing.T) { - return func(t *testing.T) { - // Ensure the default gateways, next-hops and default dev devices are properly set - netName := "dualstackbridge" - net.CreateNoError(ctx, t, client, netName, - net.WithMacvlan(""), - net.WithIPv6(), - net.WithOption("macvlan_mode", "bridge"), - net.WithIPAM("172.28.130.0/24", ""), - net.WithIPAM("2001:db8:abca::/64", "2001:db8:abca::254"), - ) - assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - - id1 := container.Run(ctx, t, client, - container.WithNetworkMode("dualstackbridge"), - ) - - // Validate macvlan bridge mode defaults gateway sets the default IPAM next-hop inferred from the subnet - result, err := container.Exec(ctx, client, id1, []string{"ip", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default via 172.28.130.1 dev eth0")) - // Validate macvlan bridge mode sets the v6 gateway to the user specified default gateway/next-hop - result, err = container.Exec(ctx, client, id1, []string{"ip", "-6", "route"}) - assert.NilError(t, err) - assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abca::254 dev eth0")) - } +func testMacvlanAddressing(t *testing.T, ctx context.Context, client client.APIClient) { + // Ensure the default gateways, next-hops and default dev devices are properly set + netName := "dualstackbridge" + net.CreateNoError(ctx, t, client, netName, + net.WithMacvlan(""), + net.WithIPv6(), + net.WithOption("macvlan_mode", "bridge"), + net.WithIPAM("172.28.130.0/24", ""), + net.WithIPAM("2001:db8:abca::/64", "2001:db8:abca::254"), + ) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) + + id1 := container.Run(ctx, t, client, + container.WithNetworkMode("dualstackbridge"), + ) + + // Validate macvlan bridge mode defaults gateway sets the default IPAM next-hop inferred from the subnet + result, err := container.Exec(ctx, client, id1, []string{"ip", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default via 172.28.130.1 dev eth0")) + // Validate macvlan bridge mode sets the v6 gateway to the user specified default gateway/next-hop + result, err = container.Exec(ctx, client, id1, []string{"ip", "-6", "route"}) + assert.NilError(t, err) + assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abca::254 dev eth0")) }