diff --git a/pkg/ipam/ipam_test.go b/pkg/ipam/ipam_test.go index 11d0ba40db8..223df09826f 100644 --- a/pkg/ipam/ipam_test.go +++ b/pkg/ipam/ipam_test.go @@ -343,90 +343,284 @@ func TestReleaseAddressByPod(t *testing.T) { require.Equal(t, 0, dualSubnet.V6Using.Len()) } -func TestGetSubnetV4Mask(t *testing.T) { +func TestDeleteSubnet(t *testing.T) { ipam := NewIPAM() - // get mask for exist subnet + // new v4 subnet v4ExcludeIps := []string{ "10.0.0.2", "10.0.0.4", "10.0.0.100", "10.0.0.252", "10.0.0.253", "10.0.0.254", } v4SubnetName := "v4Subnet" - ipv4CIDR := "10.0.0.0/24" - v4Gw := "10.0.0.1" - v4SubnetMask := "24" - err := ipam.AddOrUpdateSubnet(v4SubnetName, ipv4CIDR, v4Gw, v4ExcludeIps) + v4Subnet, err := NewSubnet(v4SubnetName, "10.0.0.0/24", v4ExcludeIps) require.NoError(t, err) - mask, err := ipam.GetSubnetV4Mask(v4SubnetName) + require.NotNil(t, v4Subnet) + ipam.Subnets[v4SubnetName] = v4Subnet + + // new v6 subnet + v6ExcludeIps := []string{ + "2001:db8::2", "2001:db8::4", "2001:db8::100", + "2001:db8::252", "2001:db8::253", "2001:db8::254", + } + v6SubnetName := "v6Subnet" + v6Subnet, err := NewSubnet("v6Subnet", "2001:db8::/64", v6ExcludeIps) require.NoError(t, err) - require.Equal(t, mask, v4SubnetMask) + require.NotNil(t, v6Subnet) + ipam.Subnets[v6SubnetName] = v6Subnet - // get mask for non-exist subnet - nonExistSubnetName := "nonExistSubnet" - mask, err = ipam.GetSubnetV4Mask(nonExistSubnetName) - require.Equal(t, err, ErrNoAvailable) - require.Empty(t, mask) + // new dual stack subnet + dualExcludeIps := []string{ + "10.0.0.2", "10.0.0.4", "10.0.0.100", + "10.0.0.252", "10.0.0.253", "10.0.0.254", + "2001:db8::2", "2001:db8::4", "2001:db8::100", + "2001:db8::252", "2001:db8::253", "2001:db8::254", + } + dualSubnetName := "dualSubnet" + dualSubnet, err := NewSubnet(dualSubnetName, "10.0.0.0/24,2001:db8::/64", dualExcludeIps) + require.NoError(t, err) + require.NotNil(t, dualSubnet) + ipam.Subnets[dualSubnetName] = dualSubnet + + // test delete subnet + require.Len(t, ipam.Subnets, 3) + ipam.DeleteSubnet(v4SubnetName) + require.Len(t, ipam.Subnets, 2) + ipam.DeleteSubnet(v6SubnetName) + require.Len(t, ipam.Subnets, 1) + ipam.DeleteSubnet(dualSubnetName) + require.Len(t, ipam.Subnets, 0) } -func TestGetSubnetIPRangeString(t *testing.T) { - // test v4 exist subnet +func TestGetPodAddress(t *testing.T) { ipam := NewIPAM() + // test v4 subnet v4ExcludeIps := []string{ "10.0.0.2", "10.0.0.4", "10.0.0.100", "10.0.0.252", "10.0.0.253", "10.0.0.254", } v4SubnetName := "v4Subnet" - ipv4CIDR := "10.0.0.0/24" - v4Gw := "10.0.0.1" - err := ipam.AddOrUpdateSubnet(v4SubnetName, ipv4CIDR, v4Gw, v4ExcludeIps) + v4Subnet, err := NewSubnet(v4SubnetName, "10.0.0.0/24", v4ExcludeIps) require.NoError(t, err) - v4UsingIPStr, v6UsingIPStr, v4AvailableIPStr, v6AvailableIPStr := ipam.GetSubnetIPRangeString(v4SubnetName, v4ExcludeIps) - require.Equal(t, v4UsingIPStr, "") - require.Equal(t, v6UsingIPStr, "") - require.Equal(t, v4AvailableIPStr, "10.0.0.1,10.0.0.3,10.0.0.5-10.0.0.99,10.0.0.101-10.0.0.251") - require.Equal(t, v6AvailableIPStr, "") - - // test not exist subnet - nonExistSubnetName := "nonExistSubnet" - v4UsingIPStr, v6UsingIPStr, v4AvailableIPStr, v6AvailableIPStr = ipam.GetSubnetIPRangeString(nonExistSubnetName, v4ExcludeIps) - require.Equal(t, v4UsingIPStr, "") - require.Equal(t, v6UsingIPStr, "") - require.Equal(t, v4AvailableIPStr, "") - require.Equal(t, v6AvailableIPStr, "") + require.NotNil(t, v4Subnet) + ipam.Subnets[v4SubnetName] = v4Subnet + v4PodName := "pod1.default" + v4NicName := "pod1.default" + var mac *string + v4, v6, macStr, err := ipam.GetRandomAddress(v4PodName, v4NicName, mac, v4SubnetName, "", nil, true) + require.NoError(t, err) + require.Equal(t, "10.0.0.1", v4) + require.Empty(t, v6) + require.NotEmpty(t, macStr) + addresses := ipam.GetPodAddress(v4PodName) + require.Len(t, addresses, 1) - // test v6 exist subnet + // test v6 subnet v6ExcludeIps := []string{ "2001:db8::2", "2001:db8::4", "2001:db8::100", "2001:db8::252", "2001:db8::253", "2001:db8::254", } v6SubnetName := "v6Subnet" - ipv6CIDR := "2001:db8::/64" - v6Gw := "2001:db8::1" - err = ipam.AddOrUpdateSubnet(v6SubnetName, ipv6CIDR, v6Gw, v6ExcludeIps) + v6Subnet, err := NewSubnet("v6Subnet", "2001:db8::/64", v6ExcludeIps) require.NoError(t, err) - v4UsingIPStr, v6UsingIPStr, v4AvailableIPStr, v6AvailableIPStr = ipam.GetSubnetIPRangeString(v6SubnetName, v6ExcludeIps) - require.Equal(t, v4UsingIPStr, "") - require.Equal(t, v6UsingIPStr, "") - require.Equal(t, v4AvailableIPStr, "") - require.Equal(t, v6AvailableIPStr, "2001:db8::1,2001:db8::3,2001:db8::5-2001:db8::ff,2001:db8::101-2001:db8::251,2001:db8::255-2001:db8::ffff:ffff:ffff:fffe") + require.NotNil(t, v6Subnet) + ipam.Subnets[v6SubnetName] = v6Subnet + v6PodName := "pod2.default" + v6NicName := "pod2.default" + v4, v6, macStr, err = ipam.GetRandomAddress(v6PodName, v6NicName, mac, v6SubnetName, "", nil, true) + require.NoError(t, err) + require.Empty(t, v4) + require.Equal(t, "2001:db8::1", v6) + require.NotEmpty(t, macStr) + v6Addresses := ipam.GetPodAddress(v6PodName) + require.Len(t, v6Addresses, 1) // test dual stack subnet + dualExcludeIps := []string{ + "10.0.0.2", "10.0.0.4", "10.0.0.100", + "10.0.0.252", "10.0.0.253", "10.0.0.254", + "2001:db8::2", "2001:db8::4", "2001:db8::100", + "2001:db8::252", "2001:db8::253", "2001:db8::254", + } dualSubnetName := "dualSubnet" + dualSubnet, err := NewSubnet(dualSubnetName, "10.0.0.0/24,2001:db8::/64", dualExcludeIps) + require.NoError(t, err) + require.NotNil(t, dualSubnet) + ipam.Subnets[dualSubnetName] = dualSubnet + dualPodName := "pod3.default" + dualNicName := "pod3.default" + v4, v6, macStr, err = ipam.GetRandomAddress(dualPodName, dualNicName, mac, dualSubnetName, "", nil, true) + require.NoError(t, err) + require.Equal(t, "10.0.0.1", v4) + require.Equal(t, "2001:db8::1", v6) + require.NotEmpty(t, macStr) + dualAddresses := ipam.GetPodAddress(dualPodName) + require.Len(t, dualAddresses, 2) +} + +func TestContainAddress(t *testing.T) { + ipam := NewIPAM() + // test v4 subnet + v4ExcludeIps := []string{ + "10.0.0.2", "10.0.0.4", "10.0.0.100", + "10.0.0.252", "10.0.0.253", "10.0.0.254", + } + v4SubnetName := "v4Subnet" + v4Subnet, err := NewSubnet(v4SubnetName, "10.0.0.0/24", v4ExcludeIps) + require.NoError(t, err) + require.NotNil(t, v4Subnet) + ipam.Subnets[v4SubnetName] = v4Subnet + v4PodName := "pod1.default" + v4NicName := "pod1.default" + var mac *string + v4, v6, macStr, err := ipam.GetRandomAddress(v4PodName, v4NicName, mac, v4SubnetName, "", nil, true) + require.NoError(t, err) + require.Equal(t, "10.0.0.1", v4) + require.Empty(t, v6) + require.NotEmpty(t, macStr) + isContained := ipam.ContainAddress(v4) + require.True(t, isContained) + notExistV4 := "10.0.0.10" + isContained = ipam.ContainAddress(notExistV4) + require.False(t, isContained) + invalidV4 := "10.0.0.10.10" + isContained = ipam.ContainAddress(invalidV4) + require.False(t, isContained) + + // test v6 subnet + v6ExcludeIps := []string{ + "2001:db8::2", "2001:db8::4", "2001:db8::100", + "2001:db8::252", "2001:db8::253", "2001:db8::254", + } + v6SubnetName := "v6Subnet" + v6Subnet, err := NewSubnet("v6Subnet", "2001:db8::/64", v6ExcludeIps) + require.NoError(t, err) + require.NotNil(t, v6Subnet) + ipam.Subnets[v6SubnetName] = v6Subnet + v6PodName := "pod2.default" + v6NicName := "pod2.default" + v4, v6, macStr, err = ipam.GetRandomAddress(v6PodName, v6NicName, mac, v6SubnetName, "", nil, true) + require.NoError(t, err) + require.Empty(t, v4) + require.Equal(t, "2001:db8::1", v6) + require.NotEmpty(t, macStr) + isContained = ipam.ContainAddress(v6) + require.True(t, isContained) + notExistV6 := "2001:db8::10" + isContained = ipam.ContainAddress(notExistV6) + require.False(t, isContained) + invalidV6 := "2001:db8::10.10" + isContained = ipam.ContainAddress(invalidV6) + require.False(t, isContained) + + // test dual stack subnet dualExcludeIps := []string{ + "10.10.0.2", "10.10.0.4", "10.10.0.100", + "10.10.0.252", "10.10.0.253", "10.10.0.254", + "2001:db88::2", "2001:db88::4", "2001:db88::100", + "2001:db88::252", "2001:db88::253", "2001:db88::254", + } + dualSubnetName := "dualSubnet" + dualSubnet, err := NewSubnet(dualSubnetName, "10.10.0.0/24,2001:db88::/64", dualExcludeIps) + require.NoError(t, err) + require.NotNil(t, dualSubnet) + ipam.Subnets[dualSubnetName] = dualSubnet + dualPodName := "pod3.default" + dualNicName := "pod3.default" + v4, v6, macStr, err = ipam.GetRandomAddress(dualPodName, dualNicName, mac, dualSubnetName, "", nil, true) + require.NoError(t, err) + require.Equal(t, "10.10.0.1", v4) + require.Equal(t, "2001:db88::1", v6) + require.NotEmpty(t, macStr) + isContained = ipam.ContainAddress(v4) + require.True(t, isContained) + isContained = ipam.ContainAddress(v6) + require.True(t, isContained) + notExistDual := "10.10.0.10" + isContained = ipam.ContainAddress(notExistDual) + require.False(t, isContained) + notExistDual = "2001:db88::10" + isContained = ipam.ContainAddress(notExistDual) + require.False(t, isContained) + invalidDual := "10.10.0.10.10" + isContained = ipam.ContainAddress(invalidDual) + require.False(t, isContained) +} + +func TestIsIPAssignedToOtherPod(t *testing.T) { + ipam := NewIPAM() + // test v4 subnet + v4ExcludeIps := []string{ "10.0.0.2", "10.0.0.4", "10.0.0.100", "10.0.0.252", "10.0.0.253", "10.0.0.254", + } + v4SubnetName := "v4Subnet" + v4Subnet, err := NewSubnet(v4SubnetName, "10.0.0.0/24", v4ExcludeIps) + require.NoError(t, err) + require.NotNil(t, v4Subnet) + ipam.Subnets[v4SubnetName] = v4Subnet + v4PodName := "v4pod.default" + v4NicName := "v4pod.default" + var mac *string + v4, _, _, err := ipam.GetRandomAddress(v4PodName, v4NicName, mac, v4SubnetName, "", nil, true) + require.NoError(t, err) + v4Pod2Name := "pod2.default" + assignedPod, ok := ipam.IsIPAssignedToOtherPod(v4, v4SubnetName, v4Pod2Name) + require.True(t, ok) + require.Equal(t, v4PodName, assignedPod) + notUsingV4 := "10.0.0.10" + _, ok = ipam.IsIPAssignedToOtherPod(notUsingV4, v4SubnetName, v4Pod2Name) + require.False(t, ok) + + // test v6 subnet + v6ExcludeIps := []string{ "2001:db8::2", "2001:db8::4", "2001:db8::100", "2001:db8::252", "2001:db8::253", "2001:db8::254", } - cidr := "10.0.0.0/24,2001:db8::/64" - dualSubnet, err := NewSubnet(dualSubnetName, cidr, dualExcludeIps) + v6SubnetName := "v6Subnet" + v6Subnet, err := NewSubnet("v6Subnet", "2001:db8::/64", v6ExcludeIps) + require.NoError(t, err) + require.NotNil(t, v6Subnet) + ipam.Subnets[v6SubnetName] = v6Subnet + v6PodName := "v6pod.default" + v6NicName := "v6pod.default" + _, v6, _, err := ipam.GetRandomAddress(v6PodName, v6NicName, mac, v6SubnetName, "", nil, true) + require.NoError(t, err) + v6Pod2Name := "pod2.default" + assignedPod, ok = ipam.IsIPAssignedToOtherPod(v6, v6SubnetName, v6Pod2Name) + require.True(t, ok) + require.Equal(t, v6PodName, assignedPod) + notUsingV6 := "2001:db8::10" + _, ok = ipam.IsIPAssignedToOtherPod(notUsingV6, v6SubnetName, v6Pod2Name) + require.False(t, ok) + + // test dual stack subnet + dualExcludeIps := []string{ + "10.10.0.2", "10.10.0.4", "10.10.0.100", + "10.10.0.252", "10.10.0.253", "10.10.0.254", + "2001:db88::2", "2001:db88::4", "2001:db88::100", + "2001:db88::252", "2001:db88::253", "2001:db88::254", + } + dualSubnetName := "dualSubnet" + dualSubnet, err := NewSubnet(dualSubnetName, "10.10.0.0/24,2001:db88::/64", dualExcludeIps) require.NoError(t, err) require.NotNil(t, dualSubnet) ipam.Subnets[dualSubnetName] = dualSubnet - v4UsingIPStr, v6UsingIPStr, v4AvailableIPStr, v6AvailableIPStr = ipam.GetSubnetIPRangeString(dualSubnetName, dualExcludeIps) - require.Equal(t, v4UsingIPStr, "") - require.Equal(t, v6UsingIPStr, "") - require.Equal(t, v4AvailableIPStr, "10.0.0.1,10.0.0.3,10.0.0.5-10.0.0.99,10.0.0.101-10.0.0.251") - require.Equal(t, v6AvailableIPStr, "2001:db8::1,2001:db8::3,2001:db8::5-2001:db8::ff,2001:db8::101-2001:db8::251,2001:db8::255-2001:db8::ffff:ffff:ffff:fffe") + dualPodName := "dualpod.default" + dualNicName := "dualpod.default" + v4, v6, _, err = ipam.GetRandomAddress(dualPodName, dualNicName, mac, dualSubnetName, "", nil, true) + require.NoError(t, err) + dualPod2Name := "pod2.default" + assignedPod, ok = ipam.IsIPAssignedToOtherPod(v4, dualSubnetName, dualPod2Name) + require.True(t, ok) + require.Equal(t, dualPodName, assignedPod) + assignedPod, ok = ipam.IsIPAssignedToOtherPod(v6, dualSubnetName, dualPod2Name) + require.True(t, ok) + require.Equal(t, dualPodName, assignedPod) + notUsingDualV4 := "10.10.0.10" + _, ok = ipam.IsIPAssignedToOtherPod(notUsingDualV4, dualSubnetName, dualPod2Name) + require.False(t, ok) + notUsingDualV6 := "2001:db88::10" + _, ok = ipam.IsIPAssignedToOtherPod(notUsingDualV6, dualSubnetName, dualPod2Name) + require.False(t, ok) } func TestAddOrUpdateIPPool(t *testing.T) {