in pkg/ipamd/datastore/data_store.go [615:665]
func (ds *DataStore) AssignPodIPv6Address(ipamKey IPAMKey, ipamMetadata IPAMMetadata) (ipv6Address string, deviceNumber int, err error) {
ds.lock.Lock()
defer ds.lock.Unlock()
if !ds.isPDEnabled {
return "", -1, fmt.Errorf("PD is not enabled. V6 is only supported in PD mode")
}
ds.log.Debugf("AssignPodIPv6Address: IPv6 address pool stats: assigned %d", ds.assigned)
if eni, _, addr := ds.eniPool.FindAddressForSandbox(ipamKey); addr != nil {
ds.log.Infof("AssignPodIPv6Address: duplicate pod assign for sandbox %s", ipamKey)
return addr.Address, eni.DeviceNumber, nil
}
// In IPv6 Prefix Delegation mode, eniPool will only have Primary ENI.
for _, eni := range ds.eniPool {
if len(eni.IPv6Cidrs) == 0 {
continue
}
for _, V6Cidr := range eni.IPv6Cidrs {
if !V6Cidr.IsPrefix {
continue
}
ipv6Address, err = ds.getFreeIPv6AddrFromCidr(V6Cidr)
if err != nil {
ds.log.Debugf("Unable to get IP address from prefix: %v", err)
//In v6 mode, we (should) only have one CIDR/Prefix. So, we can bail out but we will let the loop
//exit instead.
continue
}
ds.log.Debugf("New v6 IP from PD pool- %s", ipv6Address)
addr := &AddressInfo{Address: ipv6Address}
V6Cidr.IPAddresses[ipv6Address] = addr
ds.assignPodIPAddressUnsafe(addr, ipamKey, ipamMetadata, time.Now())
if err := ds.writeBackingStoreUnsafe(); err != nil {
ds.log.Warnf("Failed to update backing store: %v", err)
// Important! Unwind assignment
ds.unassignPodIPAddressUnsafe(addr)
//Remove the IP from eni DB
delete(V6Cidr.IPAddresses, addr.Address)
return "", -1, err
}
// Increment ENI IP usage on pod IPv6 allocation
prometheusmetrics.EniIPsInUse.WithLabelValues(eni.ID).Inc()
return addr.Address, eni.DeviceNumber, nil
}
}
prometheusmetrics.NoAvailableIPAddrs.Inc()
return "", -1, errors.New("AssignPodIPv6Address: no available IP addresses")
}