in cmd/egress-v4-cni-plugin/cni.go [250:341]
func cmdAdd(args *skel.CmdArgs) error {
netConf, log, err := loadConf(args.StdinData)
if err != nil {
log.Debugf("Received Add request: Failed to parse config")
return fmt.Errorf("failed to parse config: %v", err)
}
if netConf.PrevResult == nil {
return fmt.Errorf("must be called as a chained plugin")
}
result, err := current.GetResult(netConf.PrevResult)
if err != nil {
return err
}
log.Debugf("Received an ADD request for: conf=%v; Plugin enabled=%s", netConf, netConf.Enabled)
//We will not be vending out this as a separate plugin by itself and it is only intended to be used as a
//chained plugin to VPC CNI in IPv6 mode. We only need this plugin to kick in if v6 is enabled in VPC CNI. So, the
//value of an env variable in VPC CNI determines whether this plugin should be enabled and this is an attempt to
//pass through the variable configured in VPC CNI.
if netConf.Enabled == "false" {
return types.PrintResult(result, netConf.CNIVersion)
}
chain := utils.MustFormatChainNameWithPrefix(netConf.Name, args.ContainerID, "E4-")
comment := utils.FormatComment(netConf.Name, args.ContainerID)
ipamResultI, err := ipam.ExecAdd(netConf.IPAM.Type, args.StdinData)
if err != nil {
return fmt.Errorf("running IPAM plugin failed: %v", err)
}
// Invoke ipam del if err to avoid ip leak
defer func() {
if err != nil {
ipam.ExecDel(netConf.IPAM.Type, args.StdinData)
}
}()
tmpResult, err := current.NewResultFromResult(ipamResultI)
if err != nil {
return err
}
if len(tmpResult.IPs) == 0 {
return fmt.Errorf("IPAM plugin returned zero IPs")
}
if err := ip.EnableForward(tmpResult.IPs); err != nil {
return fmt.Errorf("could not enable IP forwarding: %v", err)
}
netns, err := ns.GetNS(args.Netns)
if err != nil {
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
}
defer netns.Close()
// NB: This uses netConf.IfName NOT args.IfName.
hostInterface, _, err := setupContainerVeth(netns, netConf.IfName, netConf.MTU, tmpResult)
if err != nil {
log.Debugf("failed to setup container Veth: %v", err)
return err
}
if err = setupHostVeth(hostInterface.Name, tmpResult); err != nil {
return err
}
log.Debugf("Node IP: %s", netConf.NodeIP)
if netConf.NodeIP != nil {
for _, ipc := range tmpResult.IPs {
if ipc.Version == "4" {
//log.Printf("Configuring SNAT %s -> %s", ipc.Address.IP, netConf.SnatIP)
if err := snat.Snat4(netConf.NodeIP, ipc.Address.IP, chain, comment); err != nil {
return err
}
}
}
}
//Copy interfaces over to result, but not IPs.
result.Interfaces = append(result.Interfaces, tmpResult.Interfaces...)
//Note: Useful for debug, will do away with the below log prior to release
for _, v := range result.IPs {
log.Debugf("Interface Name: %v; IP: %s", v.Interface, v.Address)
}
// Pass through the previous result
return types.PrintResult(result, netConf.CNIVersion)
}