Code change:
Is this a BUG REPORT or FEATURE REQUEST?: /kind bug What happened: When creating an IPv6 cluster, the --pod-network-cidr needs to be a /66, it cannot be for a larger network (smaller value) What you expected to happen: Should be able to use values smaller then /66, /64 or a /48 How to reproduce it (as minimally and precisely as possible): Create a cluster with Kubeadm, and set the podSubnet as below networking: podSubnet: "fd00:1:2:3::/64" Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g. from /etc/os-release): Kernel (e.g. ): Install tools: Others: /area ipv6 /sig network
/assign rpothier

Related discussion:
text: ) func TestAllocate(t *testing.T) { <del> _, cidr, err := net.ParseCIDR("192.168.1.0/24") if err != nil { t.Fatal(err) } r := NewCIDRRange(cidr) t.Logf("base: %v", r.base.Bytes()) if f := r.Free(); f != 254 { t.Errorf("unexpected free %d", f) } if f := r.Used(); f != 0 { t.Errorf("unexpected used %d", f) </del> <ins> testCases := []struct { name             string cidr             string free             int released         string outOfRange1      string outOfRange2      string outOfRange3      string alreadyAllocated string }{ { name:             "IPv4", cidr:             "192.168.1.0/24", free:             254, released:         "192.168.1.5", outOfRange1:      "192.168.0.1", outOfRange2:      "192.168.1.0", outOfRange3:      "192.168.1.255", alreadyAllocated: "192.168.1.1", }, { name:             "IPv6", cidr:             "2001:db8:1::/48", free:             65534, released:         "2001:db8:1::5", outOfRange1:      "2001:db8::1", outOfRange2:      "2001:db8:1::", outOfRange3:      "2001:db8:1::ffff", alreadyAllocated: "2001:db8:1::1", }, </ins> } <del> found := sets.NewString() count := 0 for r.Free() > 0 { ip, err := r.AllocateNext() </del> <ins> for _, tc := range testCases { _, cidr, err := net.ParseCIDR(tc.cidr) </ins> if err != nil { <del> t.Fatalf("error @ %d: %v", count, err) </del> <ins> t.Fatal(err) </ins> } <del> count++ if !cidr.Contains(ip) { t.Fatalf("allocated %s which is outside of %s", ip, cidr) </del> <ins> r := NewCIDRRange(cidr) t.Logf("base: %v", r.base.Bytes()) if f := r.Free(); f != tc.free { t.Errorf("Test %s unexpected free %d", tc.name, f) </ins> } <del> if found.Has(ip.String()) { t.Fatalf("allocated %s twice @ %d", ip, count) </del> <ins> if f := r.Used(); f != 0 { t.Errorf("Test %s unexpected used %d", tc.name, f) } found := sets.NewString() count := 0 for r.Free() > 0 { ip, err := r.AllocateNext() if err != nil { t.Fatalf("Test %s error @ %d: %v", tc.name, count, err) } count++ if !cidr.Contains(ip) { t.Fatalf("Test %s allocated %s which is outside of %s", tc.name, ip, cidr) } if found.Has(ip.String()) { t.Fatalf("Test %s allocated %s twice @ %d", tc.name, ip, count) } found.Insert(ip.String()) } if _, err := r.AllocateNext(); err != ErrFull { t.Fatal(err) </ins> } <del> found.Insert(ip.String()) } if _, err := r.AllocateNext(); err != ErrFull { t.Fatal(err) } released := net.ParseIP("192.168.1.5") if err := r.Release(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } if f := r.Used(); f != 253 { t.Errorf("unexpected free %d", f) } ip, err := r.AllocateNext() if err != nil { t.Fatal(err) } if !released.Equal(ip) { t.Errorf("unexpected %s : %s", ip, released) } </del> <ins> released := net.ParseIP(tc.released) if err := r.Release(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("Test %s unexpected free %d", tc.name, f) } if f := r.Used(); f != (tc.free - 1) { t.Errorf("Test %s unexpected free %d", tc.name, f) } ip, err := r.AllocateNext() if err != nil { t.Fatal(err) } if !released.Equal(ip) { t.Errorf("Test %s unexpected %s : %s", tc.name, ip, released) } </ins> <del> if err := r.Release(released); err != nil { t.Fatal(err) } err = r.Allocate(net.ParseIP("192.168.0.1")) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } if err := r.Allocate(net.ParseIP("192.168.1.1")); err != ErrAllocated { t.Fatal(err) } err = r.Allocate(net.ParseIP("192.168.1.0")) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } err = r.Allocate(net.ParseIP("192.168.1.255")) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } if f := r.Used(); f != 253 { t.Errorf("unexpected free %d", f) } if err := r.Allocate(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 0 { t.Errorf("unexpected free %d", f) } if f := r.Used(); f != 254 { t.Errorf("unexpected free %d", f) </del> <ins> if err := r.Release(released); err != nil { t.Fatal(err) } err = r.Allocate(net.ParseIP(tc.outOfRange1)) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } if err := r.Allocate(net.ParseIP(tc.alreadyAllocated)); err != ErrAllocated { t.Fatal(err) } err = r.Allocate(net.ParseIP(tc.outOfRange2)) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } err = r.Allocate(net.ParseIP(tc.outOfRange3)) if _, ok := err.(*ErrNotInRange); !ok { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("Test %s unexpected free %d", tc.name, f) } if f := r.Used(); f != (tc.free - 1) { t.Errorf("Test %s unexpected free %d", tc.name, f) } if err := r.Allocate(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 0 { t.Errorf("Test %s unexpected free %d", tc.name, f) } if f := r.Used(); f != tc.free { t.Errorf("Test %s unexpected free %d", tc.name, f) } </ins> } }