func()

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
}