Merge pull request #138385 from hoskeri/automated-cherry-pick-of-#134193-upstream-release-1.34

Automated cherry pick of #134193: Fix IPv6 allocator for /64 CIDRs
This commit is contained in:
Kubernetes Prow Robot
2026-05-08 18:35:19 +05:30
committed by GitHub
2 changed files with 59 additions and 3 deletions

View File

@@ -73,7 +73,7 @@ type Allocator struct {
var _ Interface = &Allocator{}
// NewIPAllocator returns an IP allocator associated to a network range
// that use the IPAddress objectto track the assigned IP addresses,
// that use the IPAddress object to track the assigned IP addresses,
// using an informer cache as storage.
func NewIPAllocator(
cidr *net.IPNet,
@@ -253,7 +253,11 @@ func (a *Allocator) allocateNextService(svc *api.Service, dryRun bool) (net.IP,
var offset uint64
switch {
case rangeSize >= math.MaxInt64:
offset = rand.Uint64()
offset = a.rand.Uint64()
// a.offsetAddress + offset should not overflow a 64 bit CIDR.
if math.MaxUint64-offset < uint64(a.rangeOffset) {
offset -= uint64(a.rangeOffset)
}
case rangeSize == 0:
return net.IP{}, ErrFull
default:
@@ -493,7 +497,7 @@ func (dry dryRunAllocator) EnableMetrics() {
func addOffsetAddress(address netip.Addr, offset uint64) (netip.Addr, error) {
addressBytes := address.AsSlice()
addressBig := big.NewInt(0).SetBytes(addressBytes)
r := big.NewInt(0).Add(addressBig, big.NewInt(int64(offset))).Bytes()
r := big.NewInt(0).Add(addressBig, big.NewInt(0).SetUint64(offset)).Bytes()
// r must be 4 or 16 bytes depending of the ip family
// bigInt conversion to bytes will not take this into consideration
// and drop the leading zeros, so we have to take this into account.

View File

@@ -198,6 +198,58 @@ func TestAllocateIPAllocator(t *testing.T) {
}
}
func TestAddOffsetAddress(t *testing.T) {
baseAddr := netip.MustParseAddr("fd54:ceea:51ad:2f00::0")
for _, tc := range []struct {
offset uint64
wantAddr netip.Addr
}{
{
offset: 0,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00::0"),
},
{
offset: 1,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00::1"),
},
{
offset: math.MaxInt64,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00:7fff:ffff:ffff:ffff"),
},
{
offset: math.MaxInt64 + 1,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00:8000::"),
},
{
offset: math.MaxUint64,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00:ffff:ffff:ffff:ffff"),
},
{
offset: math.MaxUint64 - 1,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00:ffff:ffff:ffff:fffe"),
},
{
offset: math.MaxUint64>>13 - 1,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00:7:ffff:ffff:fffe"),
},
{
offset: math.MaxUint64 >> 59,
wantAddr: netip.MustParseAddr("fd54:ceea:51ad:2f00::1f"),
},
} {
t.Run(fmt.Sprintf("base:%s,offset:%x,want:%s", baseAddr, tc.offset, tc.wantAddr), func(t *testing.T) {
gotAddr, err := addOffsetAddress(baseAddr, tc.offset)
if err != nil {
t.Fatalf("err: %v", err)
}
if gotAddr.Compare(tc.wantAddr) != 0 {
t.Fatalf("compareAddr: got %s, want %s", gotAddr, tc.wantAddr)
}
})
}
}
func TestAllocateTinyIPAllocator(t *testing.T) {
_, cidr, err := netutils.ParseCIDRSloppy("192.168.1.0/32")
if err != nil {