in cmd/routed-eni-cni-plugin/cni.go [124:283]
func add(args *skel.CmdArgs, cniTypes typeswrapper.CNITYPES, grpcClient grpcwrapper.GRPC,
rpcClient rpcwrapper.RPC, driverClient driver.NetworkAPIs) error {
conf, log, err := LoadNetConf(args.StdinData)
if err != nil {
return errors.Wrap(err, "add cmd: error loading config from args")
}
log.Infof("Received CNI add request: ContainerID(%s) Netns(%s) IfName(%s) Args(%s) Path(%s) argsStdinData(%s)",
args.ContainerID, args.Netns, args.IfName, args.Args, args.Path, args.StdinData)
log.Debugf("Prev Result: %v\n", conf.PrevResult)
var k8sArgs K8sArgs
if err := cniTypes.LoadArgs(args.Args, &k8sArgs); err != nil {
log.Errorf("Failed to load k8s config from arg: %v", err)
return errors.Wrap(err, "add cmd: failed to load k8s config from arg")
}
mtu := networkutils.GetEthernetMTU(conf.MTU)
log.Debugf("MTU value set is %d:", mtu)
// Set up a connection to the ipamD server.
conn, err := grpcClient.Dial(ipamdAddress, grpc.WithInsecure())
if err != nil {
log.Errorf("Failed to connect to backend server for container %s: %v",
args.ContainerID, err)
return errors.Wrap(err, "add cmd: failed to connect to backend server")
}
defer conn.Close()
c := rpcClient.NewCNIBackendClient(conn)
r, err := c.AddNetwork(context.Background(),
&pb.AddNetworkRequest{
ClientVersion: version,
K8S_POD_NAME: string(k8sArgs.K8S_POD_NAME),
K8S_POD_NAMESPACE: string(k8sArgs.K8S_POD_NAMESPACE),
K8S_POD_INFRA_CONTAINER_ID: string(k8sArgs.K8S_POD_INFRA_CONTAINER_ID),
Netns: args.Netns,
ContainerID: args.ContainerID,
NetworkName: conf.Name,
IfName: args.IfName,
})
if err != nil {
log.Errorf("Error received from AddNetwork grpc call for containerID %s: %v",
args.ContainerID,
err)
return errors.Wrap(err, "add cmd: Error received from AddNetwork gRPC call")
}
if !r.Success {
log.Errorf("Failed to assign an IP address to container %s",
args.ContainerID)
return errors.New("add cmd: failed to assign an IP address to container")
}
log.Infof("Received add network response for container %s interface %s: %+v",
args.ContainerID, args.IfName, r)
//We will let the values in result struct guide us in terms of IP Address Family configured.
var v4Addr, v6Addr, addr *net.IPNet
var addrFamily string
//We don't support dual stack mode currently so it has to be either v4 or v6 mode.
if r.IPv4Addr != "" {
v4Addr = &net.IPNet{
IP: net.ParseIP(r.IPv4Addr),
Mask: net.CIDRMask(32, 32),
}
addrFamily = "4"
addr = v4Addr
} else if r.IPv6Addr != "" {
v6Addr = &net.IPNet{
IP: net.ParseIP(r.IPv6Addr),
Mask: net.CIDRMask(128, 128),
}
addrFamily = "6"
addr = v6Addr
}
var hostVethName string
var dummyVlanInterface *current.Interface
// Non-zero value means pods are using branch ENI
if r.PodVlanId != 0 {
hostVethName = generateHostVethName(vlanInterfacePrefix, string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
err = driverClient.SetupPodENINetwork(hostVethName, args.IfName, args.Netns, v4Addr, v6Addr, int(r.PodVlanId), r.PodENIMAC,
r.PodENISubnetGW, int(r.ParentIfIndex), mtu, log)
// This is a dummyVlanInterfaceName generated to identify dummyVlanInterface
// which will be created for PPSG scenario to pass along the vlanId information
// as a part of the ADD cmd Result struct
// The podVlanId is used by DEL cmd, fetched from the prevResult struct to cleanup the pod network
dummyVlanInterfaceName := generateHostVethName(dummyVlanInterfacePrefix, string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
// The dummyVlanInterface is purely virtual and relevent only for ppsg, so we decided to keep it separate
// and not overload the already available hostVethInterface
dummyVlanInterface = ¤t.Interface{Name: dummyVlanInterfaceName, Mac: fmt.Sprint(r.PodVlanId)}
log.Debugf("Using dummy vlanInterface: %v", dummyVlanInterface)
} else {
// build hostVethName
// Note: the maximum length for linux interface name is 15
hostVethName = generateHostVethName(conf.VethPrefix, string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
err = driverClient.SetupNS(hostVethName, args.IfName, args.Netns, v4Addr, v6Addr, int(r.DeviceNumber), r.VPCv4CIDRs, r.UseExternalSNAT, mtu, log)
}
if err != nil {
log.Errorf("Failed SetupPodNetwork for container %s: %v",
args.ContainerID, err)
// return allocated IP back to IP pool
r, delErr := c.DelNetwork(context.Background(), &pb.DelNetworkRequest{
ClientVersion: version,
K8S_POD_NAME: string(k8sArgs.K8S_POD_NAME),
K8S_POD_NAMESPACE: string(k8sArgs.K8S_POD_NAMESPACE),
K8S_POD_INFRA_CONTAINER_ID: string(k8sArgs.K8S_POD_INFRA_CONTAINER_ID),
ContainerID: args.ContainerID,
IfName: args.IfName,
NetworkName: conf.Name,
Reason: "SetupNSFailed",
})
if delErr != nil {
log.Errorf("Error received from DelNetwork grpc call for container %s: %v",
args.ContainerID, delErr)
} else if !r.Success {
log.Errorf("Failed to release IP of container %s", args.ContainerID)
}
return errors.Wrap(err, "add command: failed to setup network")
}
containerInterfaceIndex := 1
ips := []*current.IPConfig{
{
Version: addrFamily,
Address: *addr,
Interface: &containerInterfaceIndex,
},
}
hostInterface := ¤t.Interface{Name: hostVethName}
containerInterface := ¤t.Interface{Name: args.IfName, Sandbox: args.Netns}
result := ¤t.Result{
IPs: ips,
Interfaces: []*current.Interface{
hostInterface,
containerInterface,
},
}
// We append dummyVlanInterface only for pods using branch ENI
if dummyVlanInterface != nil {
result.Interfaces = append(result.Interfaces, dummyVlanInterface)
}
return cniTypes.PrintResult(result, conf.CNIVersion)
}