const ControllerName … type Allocator … var _ … // NewIPAllocator returns an IP allocator associated to a network range // that use the IPAddress objectto track the assigned IP addresses, // using an informer cache as storage. func NewIPAllocator( cidr *net.IPNet, client networkingv1beta1client.NetworkingV1beta1Interface, ipAddressInformer networkingv1beta1informers.IPAddressInformer, ) (*Allocator, error) { … } func (a *Allocator) createIPAddress(name string, svc *api.Service, scope string) error { … } // Allocate attempts to reserve the provided IP. ErrNotInRange or // ErrAllocated will be returned if the IP is not valid for this range // or has already been reserved. ErrFull will be returned if there // are no addresses left. // Only for testing, it will fail to create the IPAddress object because // the Service reference is required. func (a *Allocator) Allocate(ip net.IP) error { … } // AllocateService attempts to reserve the provided IP. ErrNotInRange or // ErrAllocated will be returned if the IP is not valid for this range // or has already been reserved. ErrFull will be returned if there // are no addresses left. func (a *Allocator) AllocateService(svc *api.Service, ip net.IP) error { … } func (a *Allocator) allocateService(svc *api.Service, ip net.IP, dryRun bool) error { … } // AllocateNext return an IP address that wasn't allocated yet. // Only for testing, it will fail to create the IPAddress object because // the Service reference is required. func (a *Allocator) AllocateNext() (net.IP, error) { … } // AllocateNext return an IP address that wasn't allocated yet. func (a *Allocator) AllocateNextService(svc *api.Service) (net.IP, error) { … } // allocateNextService tries to allocate a free IP address within the subnet. // If the subnet is big enough, it partitions the subnet into two subranges, // delimited by a.rangeOffset. // It tries to allocate a free IP address from the upper subnet first and // falls back to the lower subnet. // It starts allocating from a random IP within each range. func (a *Allocator) allocateNextService(svc *api.Service, dryRun bool) (net.IP, error) { … } // IP iterator allows to iterate over all the IP addresses // in a range defined by the start and last address. // It starts iterating at the address position defined by the offset. // It returns an invalid address to indicate it hasfinished. func ipIterator(first netip.Addr, last netip.Addr, offset uint64) func() netip.Addr { … } // allocateFromRange allocates an empty IP address from the range of // IPs between the first and last address (both included), starting // from the start address. // TODO: this is a linear search, it can be optimized. func (a *Allocator) allocateFromRange(iterator func() netip.Addr, svc *api.Service) (net.IP, error) { … } // Release releases the IP back to the pool. Releasing an // unallocated IP or an IP out of the range is a no-op and // returns no error. func (a *Allocator) Release(ip net.IP) error { … } func (a *Allocator) release(ip net.IP, dryRun bool) error { … } // ForEach executes the function on each allocated IP // This is required to satisfy the Allocator Interface only func (a *Allocator) ForEach(f func(net.IP)) { … } func (a *Allocator) CIDR() net.IPNet { … } // for testing func (a *Allocator) Has(ip net.IP) bool { … } func (a *Allocator) IPFamily() api.IPFamily { … } // for testing, it assumes this is the allocator is unique for the ipFamily func (a *Allocator) Used() int { … } // for testing, it assumes this is the allocator is unique for the ipFamily func (a *Allocator) Free() int { … } // Destroy func (a *Allocator) Destroy() { … } // DryRun func (a *Allocator) DryRun() Interface { … } // EnableMetrics func (a *Allocator) EnableMetrics() { … } type dryRunAllocator … func (dry dryRunAllocator) Allocate(ip net.IP) error { … } func (dry dryRunAllocator) AllocateNext() (net.IP, error) { … } func (dry dryRunAllocator) Release(ip net.IP) error { … } func (dry dryRunAllocator) ForEach(cb func(net.IP)) { … } func (dry dryRunAllocator) CIDR() net.IPNet { … } func (dry dryRunAllocator) IPFamily() api.IPFamily { … } func (dry dryRunAllocator) DryRun() Interface { … } func (dry dryRunAllocator) Has(ip net.IP) bool { … } func (dry dryRunAllocator) Destroy() { … } func (dry dryRunAllocator) EnableMetrics() { … } // addOffsetAddress returns the address at the provided offset within the subnet // TODO: move it to k8s.io/utils/net, this is the same as current AddIPOffset() // but using netip.Addr instead of net.IP func addOffsetAddress(address netip.Addr, offset uint64) (netip.Addr, error) { … } // hostsPerNetwork returns the number of available hosts in a subnet. // The max number is limited by the size of an uint64. // Number of hosts is calculated with the formula: // IPv4: 2^x – 2, not consider network and broadcast address // IPv6: 2^x - 1, not consider network address // where x is the number of host bits in the subnet. func hostsPerNetwork(subnet *net.IPNet) uint64 { … } // broadcastAddress returns the broadcast address of the subnet // The broadcast address is obtained by setting all the host bits // in a subnet to 1. // network 192.168.0.0/24 : subnet bits 24 host bits 32 - 24 = 8 // broadcast address 192.168.0.255 func broadcastAddress(subnet netip.Prefix) (netip.Addr, error) { … } // serviceToRef obtain the Service Parent Reference func serviceToRef(svc *api.Service) *networkingv1beta1.ParentReference { … }