in common/core/network.go [95:238]
func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
logrus.Debugf("[cni-net] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}.",
args.ContainerID, args.Netns, args.IfName, args.Args, args.Path)
var err error
var nwConfig *network.NetworkInfo
podConfig, err := cni.ParseCniArgs(args.Args)
k8sNamespace := ""
if err == nil {
k8sNamespace = string(podConfig.K8S_POD_NAMESPACE)
}
// Parse network configuration from stdin.
cniConfig, err := cni.ParseNetworkConfig(args.StdinData)
if err != nil {
logrus.Errorf("[cni-net] Failed to parse network configuration, err:%v.", err)
return err
}
logrus.Debugf("[cni-net] Read network configuration %+v.", cniConfig)
if cniConfig.OptionalFlags.EnableDualStack == false {
logrus.Infof("[cni-net] Dual stack is disabled")
} else {
logrus.Infof("[cni-net] Dual stack is enabled")
}
// Convert cniConfig to NetworkInfo
// We don't set namespace, setting namespace is not valid for EP creation
networkInfo, err := cniConfig.GetNetworkInfo(k8sNamespace)
if err != nil {
logrus.Errorf("[cni-net] Failed to get network information from network configuration, err:%v.", err)
return err
}
epInfo, err := cniConfig.GetEndpointInfo(networkInfo, args.ContainerID, "")
if err != nil {
return err
}
epInfo.DualStack = cniConfig.OptionalFlags.EnableDualStack
// Check for missing namespace
if args.Netns == "" {
logrus.Errorf("[cni-net] Missing Namespace, cannot add, endpoint : [%v].", epInfo)
return errors.New("cannot create endpoint without a namespace")
}
if cniConfig.OptionalFlags.EnableDualStack == false {
nwConfig, err = getOrCreateNetwork(plugin, networkInfo, cniConfig)
} else {
// The network must be created beforehand
nwConfig, err = plugin.nm.GetNetworkByName(cniConfig.Name)
if nwConfig.Type != network.L2Bridge {
logrus.Errorf("[cni-net] Dual stack can only be specified with l2bridge network: [%v].", nwConfig.Type)
return errors.New("Dual stack specified with non l2bridge network")
}
}
if err != nil {
return err
}
hnsEndpoint, err := plugin.nm.GetEndpointByName(epInfo.Name, cniConfig.OptionalFlags.EnableDualStack)
if hnsEndpoint != nil {
logrus.Infof("[cni-net] Endpoint %+v already exists for network %v.", hnsEndpoint, nwConfig.ID)
// Endpoint exists
// Validate for duplication
if hnsEndpoint.NetworkID == nwConfig.ID {
// An endpoint already exists in the same network.
// Do not allow creation of more endpoints on same network
logrus.Debugf("[cni-net] Endpoint exists on same network, ignoring add : [%v].", epInfo)
// Convert result to the requested CNI version.
res := cni.GetCurrResult(nwConfig, hnsEndpoint, args.IfName, cniConfig)
result, err := res.GetAsVersion(cniConfig.CniVersion)
if err != nil {
return err
}
result.Print()
return nil
}
} else {
logrus.Debugf("[cni-net] Creating a new Endpoint")
}
// If Ipam was provided, allocate a pool and obtain address
if cniConfig.Ipam.Type != "" {
err = allocateIpam(
networkInfo,
epInfo,
cniConfig,
cniConfig.OptionalFlags.ForceBridgeGateway,
args.StdinData)
if err != nil {
// Error was logged by allocateIpam.
return err
}
defer func() {
if resultError != nil {
logrus.Debugf("[cni-net] failure during ADD cleaning-up ipam, %v", err)
os.Setenv("CNI_COMMAND", "DEL")
err := deallocateIpam(cniConfig, args.StdinData)
os.Setenv("CNI_COMMAND", "ADD")
if err != nil {
logrus.Debugf("[cni-net] failed during ADD command for clean-up delegate delete call, %v", err)
}
}
}()
}
if cniConfig.OptionalFlags.GatewayFromAdditionalRoutes {
logrus.Debugf("[cni-net] GatewayFromAdditionalRoutes set")
addEndpointGatewaysFromConfig(epInfo, cniConfig)
}
// Apply the Network Policy for Endpoint
epInfo.Policies = append(epInfo.Policies, networkInfo.Policies...)
// If LoopbackDSR is set, add to policies
if cniConfig.OptionalFlags.LoopbackDSR {
hcnLoopbackRoute, _ := network.GetLoopbackDSRPolicy(&epInfo.IPAddress)
epInfo.Policies = append(epInfo.Policies, hcnLoopbackRoute)
}
epInfo, err = plugin.nm.CreateEndpoint(nwConfig.ID, epInfo, args.Netns)
if err != nil {
logrus.Errorf("[cni-net] Failed to create endpoint, error : %v.", err)
return err
}
// Convert result to the requested CNI version.
res := cni.GetCurrResult(nwConfig, epInfo, args.IfName, cniConfig)
result, err := res.GetAsVersion(cniConfig.CniVersion)
if err != nil {
return err
}
result.Print()
logrus.Debugf("[cni-net] result: %+v", result)
return nil
}