in pkg/ipamd/rpc_handler.go [245:323]
func (s *server) DelNetwork(ctx context.Context, in *rpc.DelNetworkRequest) (*rpc.DelNetworkReply, error) {
log.Infof("Received DelNetwork for Sandbox %s", in.ContainerID)
log.Debugf("DelNetworkRequest: %s", in)
prometheusmetrics.DelIPCnt.With(prometheus.Labels{"reason": in.Reason}).Inc()
var ipv4Addr, ipv6Addr, cidrStr string
// Do this early, but after logging trace
if err := s.validateVersion(in.ClientVersion); err != nil {
log.Warnf("Rejecting DelNetwork request: %v", err)
return nil, err
}
ipamKey := datastore.IPAMKey{
ContainerID: in.ContainerID,
IfName: in.IfName,
NetworkName: in.NetworkName,
}
eni, ip, deviceNumber, err := s.ipamContext.dataStore.UnassignPodIPAddress(ipamKey)
if s.ipamContext.enableIPv4 {
ipv4Addr = ip
cidr := net.IPNet{IP: net.ParseIP(ip), Mask: net.IPv4Mask(255, 255, 255, 255)}
cidrStr = cidr.String()
} else if s.ipamContext.enableIPv6 {
ipv6Addr = ip
}
if s.ipamContext.enableIPv4 && eni != nil {
//cidrStr will be pod IP i.e, IP/32 for v4 (or) IP/128 for v6.
// Case 1: PD is enabled but IP/32 key in AvailableIPv4Cidrs[cidrStr] exists, this means it is a secondary IP. Added IsPrefix check just for sanity.
// So this IP should be released immediately.
// Case 2: PD is disabled then IP/32 key in AvailableIPv4Cidrs[cidrStr] will not exists since key to AvailableIPv4Cidrs will be either /28 prefix or /32
// secondary IP. Hence now see if we need free up a prefix is no other pods are using it.
if s.ipamContext.enablePrefixDelegation && eni.AvailableIPv4Cidrs[cidrStr] != nil && eni.AvailableIPv4Cidrs[cidrStr].IsPrefix == false {
log.Debugf("IP belongs to secondary pool with PD enabled so free IP from EC2")
s.ipamContext.tryUnassignIPFromENI(eni.ID)
} else if !s.ipamContext.enablePrefixDelegation && eni.AvailableIPv4Cidrs[cidrStr] == nil {
log.Debugf("IP belongs to prefix pool with PD disabled so try free prefix from EC2")
s.ipamContext.tryUnassignPrefixFromENI(eni.ID)
}
}
if err == datastore.ErrUnknownPod && s.ipamContext.enablePodENI {
pod, err := s.ipamContext.GetPod(in.K8S_POD_NAME, in.K8S_POD_NAMESPACE)
if err != nil {
if k8serror.IsNotFound(err) {
log.Warn("Send DelNetworkReply: pod not found")
return &rpc.DelNetworkReply{Success: true}, nil
}
log.Warnf("Send DelNetworkReply: Failed to get pod spec: %v", err)
return &rpc.DelNetworkReply{Success: false}, err
}
val, branch := pod.Annotations["vpc.amazonaws.com/pod-eni"]
if branch {
// Parse JSON data
var podENIData []PodENIData
err := json.Unmarshal([]byte(val), &podENIData)
if err != nil || len(podENIData) < 1 {
log.Errorf("Failed to unmarshal PodENIData JSON: %v", err)
}
return &rpc.DelNetworkReply{
Success: true,
PodVlanId: int32(podENIData[0].VlanID),
IPv4Addr: podENIData[0].PrivateIP,
NetworkPolicyMode: s.ipamContext.networkPolicyMode}, err
}
}
if s.ipamContext.enablePodIPAnnotation {
// On DEL, we pass IP being released
err = s.ipamContext.AnnotatePod(in.K8S_POD_NAME, in.K8S_POD_NAMESPACE, vpccniPodIPKey, "", ip)
if err != nil {
log.Errorf("Failed to delete the pod annotation: %v", err)
}
}
log.Infof("Send DelNetworkReply: IPv4Addr: %s, IPv6Addr: %s, DeviceNumber: %d, NetworkPolicyMode: %s, err: %v", ipv4Addr, ipv6Addr, deviceNumber, s.ipamContext.networkPolicyMode, err)
return &rpc.DelNetworkReply{Success: err == nil, IPv4Addr: ipv4Addr, IPv6Addr: ipv6Addr, DeviceNumber: int32(deviceNumber), NetworkPolicyMode: s.ipamContext.networkPolicyMode}, err
}