in plugins/vpc-branch-eni/plugin/commands.go [42:182]
func (plugin *Plugin) Add(args *cniSkel.CmdArgs) error {
// Parse network configuration.
netConfig, err := config.New(args)
if err != nil {
log.Errorf("Failed to parse netconfig from args: %v.", err)
return err
}
log.Infof("Executing ADD with netconfig: %+v.", netConfig)
// Find the network namespace.
log.Infof("Searching for netns %s.", args.Netns)
ns, err := netns.GetNetNS(args.Netns)
if err != nil {
log.Errorf("Failed to find netns %s: %v.", args.Netns, err)
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
}
// Bring up the trunk ENI.
err = trunk.SetOpState(true)
if err != nil {
log.Errorf("Failed to bring up trunk interface %s: %v", netConfig.TrunkName, err)
return err
}
// Create the branch ENI.
branchName := fmt.Sprintf(branchLinkNameFormat, trunk.GetLinkName(), netConfig.BranchVlanID)
branch, err := eni.NewBranch(trunk, branchName, netConfig.BranchMACAddress, netConfig.BranchVlanID)
if err != nil {
log.Errorf("Failed to create branch interface %s: %v.", branchName, err)
return err
}
// Create a link for the branch ENI.
log.Infof("Creating branch link %s.", branchName)
overrideMAC := netConfig.InterfaceType == config.IfTypeVLAN
err = branch.AttachToLink(overrideMAC)
if err != nil {
if os.IsExist(err) {
// If the branch link already exists, it may have been created in a previous invocation
// of this plugin. Look for it in the target network namespace and reset it.
err = ns.Run(func() error {
err := branch.ENI.AttachToLink()
if err != nil {
return err
}
for _, ipAddr := range netConfig.IPAddresses {
err = branch.DeleteIPAddress(&ipAddr)
if os.IsNotExist(err) {
err = nil
} else if err != nil {
log.Errorf("Failed to reset branch link: %v", err)
}
}
return err
})
}
if err != nil {
log.Errorf("Failed to attach branch interface %s: %v.", branchName, err)
return err
}
} else {
// Move branch ENI to the network namespace.
log.Infof("Moving branch link %s to netns %s.", branch, args.Netns)
err = branch.SetNetNS(ns)
if err != nil {
log.Errorf("Failed to move branch link: %v.", err)
return err
}
}
// Complete the remaining setup in target network namespace.
err = ns.Run(func() error {
var err error
// Create the container-facing link based on the requested interface type.
switch netConfig.InterfaceType {
case config.IfTypeVLAN:
// Container is running in a network namespace on this host.
err = plugin.createVLANLink(branch, args.IfName, netConfig.IPAddresses, netConfig.GatewayIPAddresses)
case config.IfTypeTAP:
// Container is running in a VM.
// Connect the branch ENI to a TAP link in the target network namespace.
bridgeName := fmt.Sprintf(bridgeNameFormat, netConfig.BranchVlanID)
err = plugin.createTAPLink(branch, bridgeName, args.IfName, netConfig.Tap)
case config.IfTypeMACVTAP:
// Container is running in a VM.
// Connect the branch ENI to a MACVTAP link in the target network namespace.
err = plugin.createMACVTAPLink(args.IfName, branch.GetLinkIndex())
}
// Add a blackhole route for IMDS endpoint if required.
if netConfig.BlockIMDS {
err = imds.BlockInstanceMetadataEndpoint()
if err != nil {
return err
}
}
// Set branch link operational state up. VLAN interfaces were already brought up above.
if netConfig.InterfaceType != config.IfTypeVLAN && err == nil {
log.Infof("Setting branch link state up.")
err = branch.SetOpState(true)
if err != nil {
log.Errorf("Failed to set branch link %v state: %v.", branch, err)
return err
}
}
return err
})
if err != nil {
log.Errorf("Failed to setup the 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: args.IfName,
Mac: netConfig.BranchMACAddress.String(),
Sandbox: args.Netns,
},
},
}
log.Infof("Writing CNI result to stdout: %+v", result)
return cniTypes.PrintResult(result, netConfig.CNIVersion)
}