github.com/cilium/cilium@v1.16.2/pkg/ipam/cidrset/cidr_set_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  // Copyright The Kubernetes Authors.
     4  
     5  package cidrset
     6  
     7  import (
     8  	"math/big"
     9  	"net"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  func TestCIDRSetFullyAllocated(t *testing.T) {
    15  	cases := []struct {
    16  		clusterCIDRStr string
    17  		subNetMaskSize int
    18  		expectedCIDR   string
    19  		description    string
    20  	}{
    21  		{
    22  			clusterCIDRStr: "127.123.234.0/30",
    23  			subNetMaskSize: 30,
    24  			expectedCIDR:   "127.123.234.0/30",
    25  			description:    "Fully allocated CIDR with IPv4",
    26  		},
    27  		{
    28  			clusterCIDRStr: "beef:1234::/30",
    29  			subNetMaskSize: 30,
    30  			expectedCIDR:   "beef:1234::/30",
    31  			description:    "Fully allocated CIDR with IPv6",
    32  		},
    33  	}
    34  	for _, tc := range cases {
    35  		_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
    36  		a, err := NewCIDRSet(clusterCIDR, tc.subNetMaskSize)
    37  		if err != nil {
    38  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
    39  		}
    40  		p, err := a.AllocateNext()
    41  		if err != nil {
    42  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
    43  		}
    44  		if p.String() != tc.expectedCIDR {
    45  			t.Fatalf("unexpected allocated cidr: %v, expecting %v for %v",
    46  				p.String(), tc.expectedCIDR, tc.description)
    47  		}
    48  
    49  		_, err = a.AllocateNext()
    50  		if err == nil {
    51  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
    52  		}
    53  
    54  		a.Release(p)
    55  
    56  		p, err = a.AllocateNext()
    57  		if err != nil {
    58  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
    59  		}
    60  		if p.String() != tc.expectedCIDR {
    61  			t.Fatalf("unexpected allocated cidr: %v, expecting %v for %v",
    62  				p.String(), tc.expectedCIDR, tc.description)
    63  		}
    64  		_, err = a.AllocateNext()
    65  		if err == nil {
    66  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
    67  		}
    68  	}
    69  }
    70  
    71  func TestIndexToCIDRBlock(t *testing.T) {
    72  	cases := []struct {
    73  		clusterCIDRStr string
    74  		subnetMaskSize int
    75  		index          int
    76  		CIDRBlock      string
    77  		description    string
    78  	}{
    79  		{
    80  			clusterCIDRStr: "127.123.3.0/16",
    81  			subnetMaskSize: 24,
    82  			index:          0,
    83  			CIDRBlock:      "127.123.0.0/24",
    84  			description:    "1st IP address indexed with IPv4",
    85  		},
    86  		{
    87  			clusterCIDRStr: "127.123.0.0/16",
    88  			subnetMaskSize: 24,
    89  			index:          15,
    90  			CIDRBlock:      "127.123.15.0/24",
    91  			description:    "16th IP address indexed with IPv4",
    92  		},
    93  		{
    94  			clusterCIDRStr: "192.168.5.219/28",
    95  			subnetMaskSize: 32,
    96  			index:          5,
    97  			CIDRBlock:      "192.168.5.213/32",
    98  			description:    "5th IP address indexed with IPv4",
    99  		},
   100  		{
   101  			clusterCIDRStr: "2001:0db8:1234:3::/48",
   102  			subnetMaskSize: 64,
   103  			index:          0,
   104  			CIDRBlock:      "2001:db8:1234::/64",
   105  			description:    "1st IP address indexed with IPv6 /64",
   106  		},
   107  		{
   108  			clusterCIDRStr: "2001:0db8:1234::/48",
   109  			subnetMaskSize: 64,
   110  			index:          15,
   111  			CIDRBlock:      "2001:db8:1234:f::/64",
   112  			description:    "16th IP address indexed with IPv6 /64",
   113  		},
   114  		{
   115  			clusterCIDRStr: "2001:0db8:85a3::8a2e:0370:7334/50",
   116  			subnetMaskSize: 63,
   117  			index:          6425,
   118  			CIDRBlock:      "2001:db8:85a3:3232::/63",
   119  			description:    "6426th IP address indexed with IPv6 /63",
   120  		},
   121  		{
   122  			clusterCIDRStr: "2001:0db8::/32",
   123  			subnetMaskSize: 48,
   124  			index:          0,
   125  			CIDRBlock:      "2001:db8::/48",
   126  			description:    "1st IP address indexed with IPv6 /48",
   127  		},
   128  		{
   129  			clusterCIDRStr: "2001:0db8::/32",
   130  			subnetMaskSize: 48,
   131  			index:          15,
   132  			CIDRBlock:      "2001:db8:f::/48",
   133  			description:    "16th IP address indexed with IPv6 /48",
   134  		},
   135  		{
   136  			clusterCIDRStr: "2001:0db8:85a3::8a2e:0370:7334/32",
   137  			subnetMaskSize: 48,
   138  			index:          6425,
   139  			CIDRBlock:      "2001:db8:1919::/48",
   140  			description:    "6426th IP address indexed with IPv6 /48",
   141  		},
   142  		{
   143  			clusterCIDRStr: "2001:0db8:1234:ff00::/56",
   144  			subnetMaskSize: 72,
   145  			index:          0,
   146  			CIDRBlock:      "2001:db8:1234:ff00::/72",
   147  			description:    "1st IP address indexed with IPv6 /72",
   148  		},
   149  		{
   150  			clusterCIDRStr: "2001:0db8:1234:ff00::/56",
   151  			subnetMaskSize: 72,
   152  			index:          15,
   153  			CIDRBlock:      "2001:db8:1234:ff00:f00::/72",
   154  			description:    "16th IP address indexed with IPv6 /72",
   155  		},
   156  		{
   157  			clusterCIDRStr: "2001:0db8:1234:ff00::0370:7334/56",
   158  			subnetMaskSize: 72,
   159  			index:          6425,
   160  			CIDRBlock:      "2001:db8:1234:ff19:1900::/72",
   161  			description:    "6426th IP address indexed with IPv6 /72",
   162  		},
   163  		{
   164  			clusterCIDRStr: "2001:0db8:1234:0:1234::/80",
   165  			subnetMaskSize: 96,
   166  			index:          0,
   167  			CIDRBlock:      "2001:db8:1234:0:1234::/96",
   168  			description:    "1st IP address indexed with IPv6 /96",
   169  		},
   170  		{
   171  			clusterCIDRStr: "2001:0db8:1234:0:1234::/80",
   172  			subnetMaskSize: 96,
   173  			index:          15,
   174  			CIDRBlock:      "2001:db8:1234:0:1234:f::/96",
   175  			description:    "16th IP address indexed with IPv6 /96",
   176  		},
   177  		{
   178  			clusterCIDRStr: "2001:0db8:1234:ff00::0370:7334/80",
   179  			subnetMaskSize: 96,
   180  			index:          6425,
   181  			CIDRBlock:      "2001:db8:1234:ff00:0:1919::/96",
   182  			description:    "6426th IP address indexed with IPv6 /96",
   183  		},
   184  	}
   185  	for _, tc := range cases {
   186  		_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
   187  		a, err := NewCIDRSet(clusterCIDR, tc.subnetMaskSize)
   188  		if err != nil {
   189  			t.Fatalf("error for %v ", tc.description)
   190  		}
   191  		cidr := a.indexToCIDRBlock(tc.index)
   192  		if cidr.String() != tc.CIDRBlock {
   193  			t.Fatalf("error for %v index %d %s", tc.description, tc.index, cidr.String())
   194  		}
   195  	}
   196  }
   197  
   198  func TestCIDRSet_RandomishAllocation(t *testing.T) {
   199  	cases := []struct {
   200  		clusterCIDRStr string
   201  		description    string
   202  	}{
   203  		{
   204  			clusterCIDRStr: "127.123.234.0/16",
   205  			description:    "RandomishAllocation with IPv4",
   206  		},
   207  		{
   208  			clusterCIDRStr: "beef:1234::/16",
   209  			description:    "RandomishAllocation with IPv6",
   210  		},
   211  	}
   212  	for _, tc := range cases {
   213  		_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
   214  		a, err := NewCIDRSet(clusterCIDR, 24)
   215  		if err != nil {
   216  			t.Fatalf("Error allocating CIDRSet for %v", tc.description)
   217  		}
   218  		// allocate all the CIDRs
   219  		var cidrs []*net.IPNet
   220  
   221  		for i := 0; i < 256; i++ {
   222  			if c, err := a.AllocateNext(); err == nil {
   223  				cidrs = append(cidrs, c)
   224  			} else {
   225  				t.Fatalf("unexpected error: %v for %v", err, tc.description)
   226  			}
   227  		}
   228  
   229  		//var err error
   230  		_, err = a.AllocateNext()
   231  		if err == nil {
   232  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
   233  		}
   234  		// release them all
   235  		for i := 0; i < len(cidrs); i++ {
   236  			a.Release(cidrs[i])
   237  		}
   238  
   239  		// allocate the CIDRs again
   240  		var rcidrs []*net.IPNet
   241  		for i := 0; i < 256; i++ {
   242  			if c, err := a.AllocateNext(); err == nil {
   243  				rcidrs = append(rcidrs, c)
   244  			} else {
   245  				t.Fatalf("unexpected error: %d, %v for %v", i, err, tc.description)
   246  			}
   247  		}
   248  		_, err = a.AllocateNext()
   249  		if err == nil {
   250  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
   251  		}
   252  
   253  		if !reflect.DeepEqual(cidrs, rcidrs) {
   254  			t.Fatalf("expected re-allocated cidrs are the same collection for %v", tc.description)
   255  		}
   256  	}
   257  }
   258  
   259  func TestCIDRSet_AllocationOccupied(t *testing.T) {
   260  	cases := []struct {
   261  		clusterCIDRStr string
   262  		description    string
   263  	}{
   264  		{
   265  			clusterCIDRStr: "127.123.234.0/16",
   266  			description:    "AllocationOccupied with IPv4",
   267  		},
   268  		{
   269  			clusterCIDRStr: "beef:1234::/16",
   270  			description:    "AllocationOccupied with IPv6",
   271  		},
   272  	}
   273  	for _, tc := range cases {
   274  		_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
   275  		a, err := NewCIDRSet(clusterCIDR, 24)
   276  		if err != nil {
   277  			t.Fatalf("Error allocating CIDRSet for %v", tc.description)
   278  		}
   279  		// allocate all the CIDRs
   280  		var cidrs []*net.IPNet
   281  		var numCIDRs = 256
   282  
   283  		for i := 0; i < numCIDRs; i++ {
   284  			if c, err := a.AllocateNext(); err == nil {
   285  				cidrs = append(cidrs, c)
   286  			} else {
   287  				t.Fatalf("unexpected error: %v for %v", err, tc.description)
   288  			}
   289  		}
   290  
   291  		//var err error
   292  		_, err = a.AllocateNext()
   293  		if err == nil {
   294  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
   295  		}
   296  		// release them all
   297  		for i := 0; i < len(cidrs); i++ {
   298  			a.Release(cidrs[i])
   299  		}
   300  		// occupy the last 128 CIDRs
   301  		for i := numCIDRs / 2; i < numCIDRs; i++ {
   302  			a.Occupy(cidrs[i])
   303  		}
   304  
   305  		// allocate the first 128 CIDRs again
   306  		var rcidrs []*net.IPNet
   307  		for i := 0; i < numCIDRs/2; i++ {
   308  			if c, err := a.AllocateNext(); err == nil {
   309  				rcidrs = append(rcidrs, c)
   310  			} else {
   311  				t.Fatalf("unexpected error: %d, %v for %v", i, err, tc.description)
   312  			}
   313  		}
   314  		_, err = a.AllocateNext()
   315  		if err == nil {
   316  			t.Fatalf("expected error because of fully-allocated range for %v", tc.description)
   317  		}
   318  
   319  		// check Occupy() work properly
   320  		for i := numCIDRs / 2; i < numCIDRs; i++ {
   321  			rcidrs = append(rcidrs, cidrs[i])
   322  		}
   323  		if !reflect.DeepEqual(cidrs, rcidrs) {
   324  			t.Fatalf("expected re-allocated cidrs are the same collection for %v", tc.description)
   325  		}
   326  	}
   327  }
   328  
   329  func TestGetBitforCIDR(t *testing.T) {
   330  	cases := []struct {
   331  		clusterCIDRStr string
   332  		subNetMaskSize int
   333  		subNetCIDRStr  string
   334  		expectedBit    int
   335  		expectErr      bool
   336  		description    string
   337  	}{
   338  		{
   339  			clusterCIDRStr: "127.0.0.0/8",
   340  			subNetMaskSize: 16,
   341  			subNetCIDRStr:  "127.0.0.0/16",
   342  			expectedBit:    0,
   343  			expectErr:      false,
   344  			description:    "Get 0 Bit with IPv4",
   345  		},
   346  		{
   347  			clusterCIDRStr: "be00::/8",
   348  			subNetMaskSize: 16,
   349  			subNetCIDRStr:  "be00::/16",
   350  			expectedBit:    0,
   351  			expectErr:      false,
   352  			description:    "Get 0 Bit with IPv6",
   353  		},
   354  		{
   355  			clusterCIDRStr: "127.0.0.0/8",
   356  			subNetMaskSize: 16,
   357  			subNetCIDRStr:  "127.123.0.0/16",
   358  			expectedBit:    123,
   359  			expectErr:      false,
   360  			description:    "Get 123rd Bit with IPv4",
   361  		},
   362  		{
   363  			clusterCIDRStr: "be00::/8",
   364  			subNetMaskSize: 16,
   365  			subNetCIDRStr:  "beef::/16",
   366  			expectedBit:    0xef,
   367  			expectErr:      false,
   368  			description:    "Get xef Bit with IPv6",
   369  		},
   370  		{
   371  			clusterCIDRStr: "127.0.0.0/8",
   372  			subNetMaskSize: 16,
   373  			subNetCIDRStr:  "127.168.0.0/16",
   374  			expectedBit:    168,
   375  			expectErr:      false,
   376  			description:    "Get 168th Bit with IPv4",
   377  		},
   378  		{
   379  			clusterCIDRStr: "be00::/8",
   380  			subNetMaskSize: 16,
   381  			subNetCIDRStr:  "be68::/16",
   382  			expectedBit:    0x68,
   383  			expectErr:      false,
   384  			description:    "Get x68th Bit with IPv6",
   385  		},
   386  		{
   387  			clusterCIDRStr: "127.0.0.0/8",
   388  			subNetMaskSize: 16,
   389  			subNetCIDRStr:  "127.224.0.0/16",
   390  			expectedBit:    224,
   391  			expectErr:      false,
   392  			description:    "Get 224th Bit with IPv4",
   393  		},
   394  		{
   395  			clusterCIDRStr: "be00::/8",
   396  			subNetMaskSize: 16,
   397  			subNetCIDRStr:  "be24::/16",
   398  			expectedBit:    0x24,
   399  			expectErr:      false,
   400  			description:    "Get x24th Bit with IPv6",
   401  		},
   402  		{
   403  			clusterCIDRStr: "192.168.0.0/16",
   404  			subNetMaskSize: 24,
   405  			subNetCIDRStr:  "192.168.12.0/24",
   406  			expectedBit:    12,
   407  			expectErr:      false,
   408  			description:    "Get 12th Bit with IPv4",
   409  		},
   410  		{
   411  			clusterCIDRStr: "beef::/16",
   412  			subNetMaskSize: 24,
   413  			subNetCIDRStr:  "beef:1200::/24",
   414  			expectedBit:    0x12,
   415  			expectErr:      false,
   416  			description:    "Get x12th Bit with IPv6",
   417  		},
   418  		{
   419  			clusterCIDRStr: "192.168.0.0/16",
   420  			subNetMaskSize: 24,
   421  			subNetCIDRStr:  "192.168.151.0/24",
   422  			expectedBit:    151,
   423  			expectErr:      false,
   424  			description:    "Get 151st Bit with IPv4",
   425  		},
   426  		{
   427  			clusterCIDRStr: "beef::/16",
   428  			subNetMaskSize: 24,
   429  			subNetCIDRStr:  "beef:9700::/24",
   430  			expectedBit:    0x97,
   431  			expectErr:      false,
   432  			description:    "Get x97st Bit with IPv6",
   433  		},
   434  		{
   435  			clusterCIDRStr: "192.168.0.0/16",
   436  			subNetMaskSize: 24,
   437  			subNetCIDRStr:  "127.168.224.0/24",
   438  			expectErr:      true,
   439  			description:    "Get error with IPv4",
   440  		},
   441  		{
   442  			clusterCIDRStr: "beef::/16",
   443  			subNetMaskSize: 24,
   444  			subNetCIDRStr:  "2001:db00::/24",
   445  			expectErr:      true,
   446  			description:    "Get error with IPv6",
   447  		},
   448  	}
   449  
   450  	for _, tc := range cases {
   451  		_, clusterCIDR, err := net.ParseCIDR(tc.clusterCIDRStr)
   452  		if err != nil {
   453  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
   454  		}
   455  
   456  		cs, err := NewCIDRSet(clusterCIDR, tc.subNetMaskSize)
   457  		if err != nil {
   458  			t.Fatalf("Error allocating CIDRSet for %v", tc.description)
   459  		}
   460  		_, subnetCIDR, err := net.ParseCIDR(tc.subNetCIDRStr)
   461  		if err != nil {
   462  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
   463  		}
   464  
   465  		got, err := cs.getIndexForIP(subnetCIDR.IP)
   466  		if err == nil && tc.expectErr {
   467  			t.Errorf("expected error but got null for %v", tc.description)
   468  			continue
   469  		}
   470  
   471  		if err != nil && !tc.expectErr {
   472  			t.Errorf("unexpected error: %v for %v", err, tc.description)
   473  			continue
   474  		}
   475  
   476  		if got != tc.expectedBit {
   477  			t.Errorf("expected %v, but got %v for %v", tc.expectedBit, got, tc.description)
   478  		}
   479  	}
   480  }
   481  
   482  func TestOccupy(t *testing.T) {
   483  	cases := []struct {
   484  		clusterCIDRStr    string
   485  		subNetMaskSize    int
   486  		subNetCIDRStr     string
   487  		expectedUsedBegin int
   488  		expectedUsedEnd   int
   489  		expectErr         bool
   490  		description       string
   491  	}{
   492  		{
   493  			clusterCIDRStr:    "127.0.0.0/8",
   494  			subNetMaskSize:    16,
   495  			subNetCIDRStr:     "127.0.0.0/8",
   496  			expectedUsedBegin: 0,
   497  			expectedUsedEnd:   255,
   498  			expectErr:         false,
   499  			description:       "Occupy all Bits with IPv4",
   500  		},
   501  		{
   502  			clusterCIDRStr:    "2001:beef:1200::/40",
   503  			subNetMaskSize:    48,
   504  			subNetCIDRStr:     "2001:beef:1200::/40",
   505  			expectedUsedBegin: 0,
   506  			expectedUsedEnd:   255,
   507  			expectErr:         false,
   508  			description:       "Occupy all Bits with IPv6",
   509  		},
   510  		{
   511  			clusterCIDRStr:    "127.0.0.0/8",
   512  			subNetMaskSize:    16,
   513  			subNetCIDRStr:     "127.0.0.0/2",
   514  			expectedUsedBegin: 0,
   515  			expectedUsedEnd:   255,
   516  			expectErr:         false,
   517  			description:       "Occupy every Bit with IPv4",
   518  		},
   519  		{
   520  			clusterCIDRStr:    "2001:beef:1200::/40",
   521  			subNetMaskSize:    48,
   522  			subNetCIDRStr:     "2001:beef:1234::/34",
   523  			expectedUsedBegin: 0,
   524  			expectedUsedEnd:   255,
   525  			expectErr:         false,
   526  			description:       "Occupy every Bit with IPv6",
   527  		},
   528  		{
   529  			clusterCIDRStr:    "127.0.0.0/8",
   530  			subNetMaskSize:    16,
   531  			subNetCIDRStr:     "127.0.0.0/16",
   532  			expectedUsedBegin: 0,
   533  			expectedUsedEnd:   0,
   534  			expectErr:         false,
   535  			description:       "Occupy 1st Bit with IPv4",
   536  		},
   537  		{
   538  			clusterCIDRStr:    "2001:beef:1200::/40",
   539  			subNetMaskSize:    48,
   540  			subNetCIDRStr:     "2001:beef:1200::/48",
   541  			expectedUsedBegin: 0,
   542  			expectedUsedEnd:   0,
   543  			expectErr:         false,
   544  			description:       "Occupy 1st Bit with IPv6",
   545  		},
   546  		{
   547  			clusterCIDRStr:    "127.0.0.0/8",
   548  			subNetMaskSize:    32,
   549  			subNetCIDRStr:     "127.0.0.0/16",
   550  			expectedUsedBegin: 0,
   551  			expectedUsedEnd:   65535,
   552  			expectErr:         false,
   553  			description:       "Occupy 65535 Bits with IPv4",
   554  		},
   555  		{
   556  			clusterCIDRStr:    "2001:beef:1200::/48",
   557  			subNetMaskSize:    64,
   558  			subNetCIDRStr:     "2001:beef:1200::/48",
   559  			expectedUsedBegin: 0,
   560  			expectedUsedEnd:   65535,
   561  			expectErr:         false,
   562  			description:       "Occupy 65535 Bits with IPv6",
   563  		},
   564  		{
   565  			clusterCIDRStr:    "127.0.0.0/7",
   566  			subNetMaskSize:    16,
   567  			subNetCIDRStr:     "127.0.0.0/15",
   568  			expectedUsedBegin: 256,
   569  			expectedUsedEnd:   257,
   570  			expectErr:         false,
   571  			description:       "Occupy 257th Bit with IPv4",
   572  		},
   573  		{
   574  			clusterCIDRStr:    "2001:beef:7f00::/39",
   575  			subNetMaskSize:    48,
   576  			subNetCIDRStr:     "2001:beef:7f00::/47",
   577  			expectedUsedBegin: 256,
   578  			expectedUsedEnd:   257,
   579  			expectErr:         false,
   580  			description:       "Occupy 257th Bit with IPv6",
   581  		},
   582  		{
   583  			clusterCIDRStr:    "127.0.0.0/7",
   584  			subNetMaskSize:    15,
   585  			subNetCIDRStr:     "127.0.0.0/15",
   586  			expectedUsedBegin: 128,
   587  			expectedUsedEnd:   128,
   588  			expectErr:         false,
   589  			description:       "Occupy 128th Bit with IPv4",
   590  		},
   591  		{
   592  			clusterCIDRStr:    "2001:beef:7f00::/39",
   593  			subNetMaskSize:    47,
   594  			subNetCIDRStr:     "2001:beef:7f00::/47",
   595  			expectedUsedBegin: 128,
   596  			expectedUsedEnd:   128,
   597  			expectErr:         false,
   598  			description:       "Occupy 128th Bit with IPv6",
   599  		},
   600  		{
   601  			clusterCIDRStr:    "127.0.0.0/7",
   602  			subNetMaskSize:    18,
   603  			subNetCIDRStr:     "127.0.0.0/15",
   604  			expectedUsedBegin: 1024,
   605  			expectedUsedEnd:   1031,
   606  			expectErr:         false,
   607  			description:       "Occupy 1031st Bit with IPv4",
   608  		},
   609  		{
   610  			clusterCIDRStr:    "2001:beef:7f00::/39",
   611  			subNetMaskSize:    50,
   612  			subNetCIDRStr:     "2001:beef:7f00::/47",
   613  			expectedUsedBegin: 1024,
   614  			expectedUsedEnd:   1031,
   615  			expectErr:         false,
   616  			description:       "Occupy 1031st Bit with IPv6",
   617  		},
   618  	}
   619  
   620  	for _, tc := range cases {
   621  		_, clusterCIDR, err := net.ParseCIDR(tc.clusterCIDRStr)
   622  		if err != nil {
   623  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
   624  		}
   625  
   626  		cs, err := NewCIDRSet(clusterCIDR, tc.subNetMaskSize)
   627  		if err != nil {
   628  			t.Fatalf("Error allocating CIDRSet for %v", tc.description)
   629  		}
   630  
   631  		_, subnetCIDR, err := net.ParseCIDR(tc.subNetCIDRStr)
   632  		if err != nil {
   633  			t.Fatalf("unexpected error: %v for %v", err, tc.description)
   634  		}
   635  
   636  		err = cs.Occupy(subnetCIDR)
   637  		if err == nil && tc.expectErr {
   638  			t.Errorf("expected error but got none for %v", tc.description)
   639  			continue
   640  		}
   641  		if err != nil && !tc.expectErr {
   642  			t.Errorf("unexpected error: %v for %v", err, tc.description)
   643  			continue
   644  		}
   645  
   646  		expectedUsed := big.Int{}
   647  		for i := tc.expectedUsedBegin; i <= tc.expectedUsedEnd; i++ {
   648  			expectedUsed.SetBit(&expectedUsed, i, 1)
   649  		}
   650  		if expectedUsed.Cmp(&cs.used) != 0 {
   651  			t.Errorf("error for %v", tc.description)
   652  		}
   653  	}
   654  }
   655  
   656  func TestCIDRSetv6(t *testing.T) {
   657  	cases := []struct {
   658  		clusterCIDRStr string
   659  		subNetMaskSize int
   660  		expectedCIDR   string
   661  		expectedCIDR2  string
   662  		expectErr      bool
   663  		description    string
   664  	}{
   665  		{
   666  			clusterCIDRStr: "127.0.0.0/8",
   667  			subNetMaskSize: 32,
   668  			expectErr:      false,
   669  			expectedCIDR:   "127.0.0.0/32",
   670  			expectedCIDR2:  "127.0.0.1/32",
   671  			description:    "Max cluster subnet size with IPv4",
   672  		},
   673  		{
   674  			clusterCIDRStr: "beef:1234::/32",
   675  			subNetMaskSize: 49,
   676  			expectErr:      true,
   677  			description:    "Max cluster subnet size with IPv6",
   678  		},
   679  		{
   680  			clusterCIDRStr: "2001:beef:1234:369b::/60",
   681  			subNetMaskSize: 64,
   682  			expectedCIDR:   "2001:beef:1234:3690::/64",
   683  			expectedCIDR2:  "2001:beef:1234:3691::/64",
   684  			expectErr:      false,
   685  			description:    "Allocate a few IPv6",
   686  		},
   687  	}
   688  	for _, tc := range cases {
   689  		t.Run(tc.description, func(t *testing.T) {
   690  			_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
   691  			a, err := NewCIDRSet(clusterCIDR, tc.subNetMaskSize)
   692  			if gotErr := err != nil; gotErr != tc.expectErr {
   693  				t.Fatalf("NewCIDRSet(%v, %v) = %v, %v; gotErr = %t, want %t", clusterCIDR, tc.subNetMaskSize, a, err, gotErr, tc.expectErr)
   694  			}
   695  			if a == nil {
   696  				return
   697  			}
   698  			p, err := a.AllocateNext()
   699  			if err == nil && tc.expectErr {
   700  				t.Errorf("a.AllocateNext() = nil, want error")
   701  			}
   702  			if err != nil && !tc.expectErr {
   703  				t.Errorf("a.AllocateNext() = %+v, want no error", err)
   704  			}
   705  			if !tc.expectErr {
   706  				if p != nil && p.String() != tc.expectedCIDR {
   707  					t.Fatalf("a.AllocateNext() got %+v, want %+v", p.String(), tc.expectedCIDR)
   708  				}
   709  			}
   710  			p2, err := a.AllocateNext()
   711  			if err == nil && tc.expectErr {
   712  				t.Errorf("a.AllocateNext() = nil, want error")
   713  			}
   714  			if err != nil && !tc.expectErr {
   715  				t.Errorf("a.AllocateNext() = %+v, want no error", err)
   716  			}
   717  			if !tc.expectErr {
   718  				if p2 != nil && p2.String() != tc.expectedCIDR2 {
   719  					t.Fatalf("a.AllocateNext() got %+v, want %+v", p2.String(), tc.expectedCIDR)
   720  				}
   721  			}
   722  		})
   723  	}
   724  }
   725  
   726  func TestInvalidSubNetMaskSize(t *testing.T) {
   727  	cases := []struct {
   728  		clusterCIDRStr string
   729  		subNetMaskSize int
   730  		expectErr      bool
   731  		description    string
   732  	}{
   733  		{
   734  			clusterCIDRStr: "10.0.0.0/24",
   735  			subNetMaskSize: 32,
   736  			expectErr:      false,
   737  			description:    "Check valid subnet mask size with IPv4",
   738  		},
   739  		{
   740  			clusterCIDRStr: "2001:beef:1234:369b::/60",
   741  			subNetMaskSize: 64,
   742  			expectErr:      false,
   743  			description:    "Check valid subnet mask size with IPv6",
   744  		},
   745  		{
   746  			clusterCIDRStr: "10.0.0.0/24",
   747  			subNetMaskSize: 64,
   748  			expectErr:      true,
   749  			description:    "Check invalid subnet mask size with IPv4",
   750  		},
   751  		{
   752  			clusterCIDRStr: "2001:beef:1234:369b::/60",
   753  			subNetMaskSize: 130,
   754  			expectErr:      true,
   755  			description:    "Check invalid subnet mask size with IPv6",
   756  		},
   757  	}
   758  	for _, tc := range cases {
   759  		t.Run(tc.description, func(t *testing.T) {
   760  			_, clusterCIDR, _ := net.ParseCIDR(tc.clusterCIDRStr)
   761  			a, err := NewCIDRSet(clusterCIDR, tc.subNetMaskSize)
   762  			if gotErr := err != nil; gotErr != tc.expectErr {
   763  				t.Fatalf("NewCIDRSet(%v, %v) = %v, %v; gotErr = %t, want %t", clusterCIDR, tc.subNetMaskSize, a, err, gotErr, tc.expectErr)
   764  			}
   765  		})
   766  	}
   767  }