@@ -351,7 +351,7 @@ func getIPv6RangeFromLinodeInterface(iface linodego.LinodeInterface) string {
351351 return ""
352352}
353353
354- // computeStableIPv6PodCIDR attempts to compute a stable IPv6 /112 PodCIDR
354+ // getIPv6PodCIDR attempts to compute a stable IPv6 /112 PodCIDR
355355// within the provided base IPv6 range using the mnemonic subprefix :0:c::/112.
356356//
357357// The mnemonic subprefix :0:c::/112 is constructed by setting hextets 5..7 to 0, c, 0
@@ -361,51 +361,37 @@ func getIPv6RangeFromLinodeInterface(iface linodego.LinodeInterface) string {
361361// - For a /64 base, return {base64}:0:c::/112
362362// - Only applies when desiredMask is /112 and the result is fully contained
363363// in the base range. Otherwise, returns (nil, false) to signal fallback.
364- func computeStableIPv6PodCIDR (base * net.IPNet , desiredMask int ) (* net.IPNet , bool ) {
364+ func getIPv6PodCIDR (base * net.IPNet , desiredMask int ) (* net.IPNet , bool ) {
365+ // Some validation checks
365366 if base == nil || desiredMask != 112 {
366367 return nil , false
367368 }
368-
369- ones , bits := base .Mask .Size ()
370- if bits != ipv6BitLen {
369+ prefixLen , addrBits := base .Mask .Size ()
370+ if addrBits != ipv6BitLen || prefixLen != ipv6PrefixLen64 { // must be a /64
371371 return nil , false
372372 }
373373
374- ip := base .IP .To16 ()
375- if ip == nil {
376- return nil , false
377- }
378-
379- // Safety: only handle /64 base ranges
380- if ones != ipv6PrefixLen64 {
381- return nil , false
382- }
383-
384- // Start from the network address of the base range
385- baseIP := ip .Mask (base .Mask )
386- out := make (net.IP , len (baseIP ))
387- copy (out , baseIP )
374+ // create a copy to avoid modifying the original
375+ ip := make (net.IP , len (base .IP ))
376+ copy (ip , base .IP )
388377
389378 // Keep first 64 bits (bytes 0..7) and set hextets 5..7 to 0, c, 0 respectively
390379 // Hextet index to byte mapping: h5->[8,9], h6->[10,11], h7->[12,13]
391- out [8 ], out [9 ] = 0x00 , 0x00 // :0
392- out [10 ], out [11 ] = 0x00 , 0x0c // :c
393- out [12 ], out [13 ] = 0x00 , 0x00 // :0
380+ ip [8 ], ip [9 ] = 0x00 , 0x00 // :0
381+ ip [10 ], ip [11 ] = 0x00 , 0x0c // :c
382+ ip [12 ], ip [13 ] = 0x00 , 0x00 // :0
394383 // last hextet (bytes 14..15) will be zeroed by mask below
395384
396- mask := net .CIDRMask (desiredMask , ipv6BitLen )
385+ podMask := net .CIDRMask (desiredMask , ipv6BitLen )
397386 // Ensure the address is the network address for the desired mask
398- out = out .Mask (mask )
399- pod := & net.IPNet {IP : out , Mask : mask }
400-
401- // Containment check: both start and end of the /112 must be inside base
402- end := make (net.IP , len (out ))
403- copy (end , out )
404- end [14 ], end [15 ] = 0xff , 0xff
405- if ! base .Contains (out ) || ! base .Contains (end ) {
387+ ip = ip .Mask (podMask )
388+ podCIDR := & net.IPNet {IP : ip , Mask : podMask }
389+
390+ if ! base .Contains (ip ) {
406391 return nil , false
407392 }
408- return pod , true
393+
394+ return podCIDR , true
409395}
410396
411397// allocateIPv6CIDR allocates an IPv6 CIDR for the given node.
@@ -479,7 +465,7 @@ func (c *cloudAllocator) allocateIPv6CIDR(ctx context.Context, node *v1.Node) (*
479465 }
480466
481467 // Try stable subprefix selection first.
482- if podCIDR , ok := computeStableIPv6PodCIDR (base , c .nodeCIDRMaskSizeIPv6 ); ok {
468+ if podCIDR , ok := getIPv6PodCIDR (base , c .nodeCIDRMaskSizeIPv6 ); ok {
483469 logger .V (4 ).Info ("Using stable IPv6 PodCIDR subprefix :0:c::/112" , "base" , base , "podCIDR" , podCIDR )
484470 return podCIDR , nil
485471 }
0 commit comments