in pkg/ipamd/rpc_handler.go [63:196]
func (s *server) AddNetwork(ctx context.Context, in *rpc.AddNetworkRequest) (*rpc.AddNetworkReply, error) {
log.Infof("Received AddNetwork for NS %s, Sandbox %s, ifname %s",
in.Netns, in.ContainerID, in.IfName)
log.Debugf("AddNetworkRequest: %s", in)
addIPCnt.Inc()
// Do this early, but after logging trace
if err := s.validateVersion(in.ClientVersion); err != nil {
log.Warnf("Rejecting AddNetwork request: %v", err)
return nil, err
}
failureResponse := rpc.AddNetworkReply{Success: false}
var deviceNumber, vlanID, trunkENILinkIndex int
var ipv4Addr, ipv6Addr, branchENIMAC, podENISubnetGW string
var err error
if !s.ipamContext.enableIPv6 && s.ipamContext.enablePodENI {
// Check pod spec for Branch ENI
pod, err := s.ipamContext.GetPod(in.K8S_POD_NAME, in.K8S_POD_NAMESPACE)
if err != nil {
log.Warnf("Send AddNetworkReply: Failed to get pod: %v", err)
return &failureResponse, nil
}
limits := pod.Spec.Containers[0].Resources.Limits
for resName := range limits {
if strings.HasPrefix(string(resName), "vpc.amazonaws.com/pod-eni") {
// Check that we have a trunk
trunkENI := s.ipamContext.dataStore.GetTrunkENI()
if trunkENI == "" {
log.Warn("Send AddNetworkReply: No trunk ENI found, cannot add a pod ENI")
return &failureResponse, nil
}
trunkENILinkIndex, err = s.ipamContext.getTrunkLinkIndex()
if err != nil {
log.Warn("Send AddNetworkReply: No trunk ENI Link Index found, cannot add a pod ENI")
return &failureResponse, nil
}
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 &failureResponse, nil
}
firstENI := podENIData[0]
ipv4Addr = firstENI.PrivateIP
branchENIMAC = firstENI.IfAddress
vlanID = firstENI.VlanID
log.Debugf("Pod vlandId: %d", vlanID)
if ipv4Addr == "" || branchENIMAC == "" || vlanID == 0 {
log.Errorf("Failed to parse pod-ENI annotation: %s", val)
return &failureResponse, nil
}
currentGW := strings.Split(firstENI.SubnetCIDR, "/")[0]
// Increment value CIDR value
nextGWIP, err := networkutils.IncrementIPv4Addr(net.ParseIP(currentGW))
if err != nil {
log.Errorf("Unable to get next Gateway IP for branch ENI from %s: %v", currentGW, err)
return &failureResponse, nil
}
podENISubnetGW = nextGWIP.String()
deviceNumber = -1 // Not needed for branch ENI, they depend on trunkENIDeviceIndex
} else {
log.Infof("Send AddNetworkReply: failed to get Branch ENI resource")
return &failureResponse, nil
}
}
}
}
if s.ipamContext.enableIPv4 && ipv4Addr == "" ||
s.ipamContext.enableIPv6 && ipv6Addr == "" {
if in.ContainerID == "" || in.IfName == "" || in.NetworkName == "" {
log.Errorf("Unable to generate IPAMKey from %+v", in)
return &failureResponse, nil
}
ipamKey := datastore.IPAMKey{
ContainerID: in.ContainerID,
IfName: in.IfName,
NetworkName: in.NetworkName,
}
ipv4Addr, ipv6Addr, deviceNumber, err = s.ipamContext.dataStore.AssignPodIPAddress(ipamKey, s.ipamContext.enableIPv4, s.ipamContext.enableIPv6)
}
var pbVPCV4cidrs, pbVPCV6cidrs []string
var useExternalSNAT bool
if s.ipamContext.enableIPv4 && ipv4Addr != "" {
pbVPCV4cidrs, err = s.ipamContext.awsClient.GetVPCIPv4CIDRs()
if err != nil {
return nil, err
}
for _, cidr := range pbVPCV4cidrs {
log.Debugf("VPC CIDR %s", cidr)
}
useExternalSNAT = s.ipamContext.networkClient.UseExternalSNAT()
if !useExternalSNAT {
for _, cidr := range s.ipamContext.networkClient.GetExcludeSNATCIDRs() {
log.Debugf("CIDR SNAT Exclusion %s", cidr)
pbVPCV4cidrs = append(pbVPCV4cidrs, cidr)
}
}
} else if s.ipamContext.enableIPv6 && ipv6Addr != "" {
pbVPCV6cidrs, err = s.ipamContext.awsClient.GetVPCIPv6CIDRs()
if err != nil {
return nil, err
}
for _, cidr := range pbVPCV6cidrs {
log.Debugf("VPC V6 CIDR %s", cidr)
}
}
if s.ipamContext.enablePodIPAnnotation {
s.ipamContext.AnnotatePod(in.K8S_POD_NAME, in.K8S_POD_NAMESPACE, vpccniPodIPKey, ipv4Addr)
}
resp := rpc.AddNetworkReply{
Success: err == nil,
IPv4Addr: ipv4Addr,
IPv6Addr: ipv6Addr,
DeviceNumber: int32(deviceNumber),
UseExternalSNAT: useExternalSNAT,
VPCv4CIDRs: pbVPCV4cidrs,
VPCv6CIDRs: pbVPCV6cidrs,
PodVlanId: int32(vlanID),
PodENIMAC: branchENIMAC,
PodENISubnetGW: podENISubnetGW,
ParentIfIndex: int32(trunkENILinkIndex),
}
log.Infof("Send AddNetworkReply: IPv4Addr %s, IPv6Addr: %s, DeviceNumber: %d, err: %v", ipv4Addr, ipv6Addr, deviceNumber, err)
return &resp, nil
}