func cmdAdd()

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)
}