func()

in plugins/vpc-branch-pat-eni/plugin/commands.go [56:152]


func (plugin *Plugin) Add(args *cniSkel.CmdArgs) error {
	// Parse network configuration.
	netConfig, err := config.New(args, true)
	if err != nil {
		log.Errorf("Failed to parse netconfig from args: %v.", err)
		return err
	}

	log.Infof("Executing ADD with netconfig: %+v.", netConfig)

	// Derive names from CNI network config.
	patNetNSName := fmt.Sprintf(patNetNSNameFormat, netConfig.BranchVlanID)
	tapBridgeName := fmt.Sprintf(tapBridgeNameFormat, netConfig.BranchVlanID)
	tapLinkName := args.IfName
	targetNetNSName := args.Netns

	// Search for the target network namespace.
	log.Infof("Searching for target netns %s.", targetNetNSName)
	targetNetNS, err := netns.GetNetNSByName(targetNetNSName)
	if err != nil {
		log.Errorf("Failed to find target netns %s.", targetNetNSName)
		return err
	}

	// Create the trunk ENI.
	trunk, err := eni.NewTrunk(netConfig.TrunkName, netConfig.TrunkMACAddress, eni.TrunkIsolationModeVLAN)
	if err != nil {
		log.Errorf("Failed to find trunk interface %s: %v.", netConfig.TrunkName, err)
		return err
	}

	// Search for the PAT network namespace.
	log.Infof("Searching for PAT netns %s.", patNetNSName)
	patNetNS, err := netns.GetNetNSByName(patNetNSName)
	if err != nil {
		// This is the first PAT interface request on this VLAN ID.
		// Create the PAT network namespace.
		branchName := fmt.Sprintf(branchLinkNameFormat, trunk.GetLinkName(), netConfig.BranchVlanID)

		// Compute the branch ENI's VPC subnet.
		branchSubnetPrefix := vpc.GetSubnetPrefix(&netConfig.BranchIPAddress)
		branchSubnet, _ := vpc.NewSubnet(branchSubnetPrefix)
		bridgeIPAddress, _ := vpc.GetIPAddressFromString(bridgeIPAddressString)

		patNetNS, err = plugin.createPATNetworkNamespace(
			patNetNSName, trunk,
			branchName, netConfig.BranchMACAddress, netConfig.BranchVlanID,
			&netConfig.BranchIPAddress, branchSubnet, bridgeIPAddress)

		if err != nil {
			log.Errorf("Failed to setup PAT netns %s: %v.", patNetNSName, err)
			return err
		}
	} else {
		// Reuse the PAT network namespace that was setup on this VLAN ID during a previous request.
		log.Infof("Found PAT netns %s.", patNetNSName)
	}

	// Create the veth pair in PAT network namespace.
	var vethPeerName string
	err = patNetNS.Run(func() error {
		var verr error
		vethPeerName, verr = plugin.createVethPair(
			netConfig.BranchVlanID, args.ContainerID, bridgeName, targetNetNS)
		return verr
	})
	if err != nil {
		log.Errorf("Failed to create veth pair: %v.", err)
		return err
	}

	// Create the tap link in target network namespace.
	log.Infof("Creating tap link %s.", tapLinkName)
	err = targetNetNS.Run(func() error {
		return plugin.createTapLink(tapBridgeName, vethPeerName, tapLinkName, netConfig.Uid, netConfig.Gid)
	})
	if err != nil {
		log.Errorf("Failed to create tap link: %v.", err)
		return err
	}

	// Generate CNI result.
	// IP addresses, routes and DNS are configured by VPC DHCP servers.
	result := &cniTypesCurrent.Result{
		Interfaces: []*cniTypesCurrent.Interface{
			{
				Name:    tapLinkName,
				Mac:     netConfig.BranchMACAddress.String(),
				Sandbox: targetNetNSName,
			},
		},
	}

	log.Infof("Writing CNI result to stdout: %+v.", result)

	return cniTypes.PrintResult(result, netConfig.CNIVersion)
}