Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L1VH CNI first version #2465

Closed
wants to merge 56 commits into from
Closed

L1VH CNI first version #2465

wants to merge 56 commits into from

Conversation

paulyufan2
Copy link
Contributor

@paulyufan2 paulyufan2 commented Jan 3, 2024

Reason for Change:

This implementation is to support swiftv2 L1VH CNI feature:
CNI receives goal state from CNS and create linux/windows pod on Windows VM/Node in swiftv2 L1VH path;
The container pod is using secondary interface with its mac address and NIC type(Delegated NIC or Accelnet) to be created;
We support up to 8 pods to be created by using different interfaces along with different hnsNetwork; CNI supports hnsNetwork creation(when pod is added to the VM) and deletion(when pod is removed from VM) to prevent leakage;

Issue Fixed:

Requirements:

Notes:

@paulyufan2 paulyufan2 marked this pull request as ready for review January 19, 2024 22:02
@paulyufan2 paulyufan2 requested review from a team as code owners January 19, 2024 22:02
@paulyufan2 paulyufan2 added the cni Related to CNI. label Jan 19, 2024
@@ -8,7 +8,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0
github.com/Masterminds/semver v1.5.0
github.com/Microsoft/go-winio v0.6.1
github.com/Microsoft/hcsshim v0.11.4
github.com/Microsoft/hcsshim v0.12.0-rc.2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What caused this update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to fetch this hcsshim version for:
hcnNetwork.Flags = hcn.DisableHostPort

Copy link
Contributor

@jpayne3506 jpayne3506 Jan 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering it is a release candidate update. Can you also run CNI Release Test on this PR? Just want to ensure there are not additional changes that are breaking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we cannot merge with release candidate version.. have to get official version released

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in rc status as they are making 0.12.X dependent on containerd 2.0, which has not been released yet.

Comment on lines +174 to +178
// Add secondary interface info from podIPInfo to ipamAddResult
info.hostSubnet = response.PodIPInfo[i].HostSecondaryIPInfo.Subnet
info.hostPrimaryIP = response.PodIPInfo[i].HostSecondaryIPInfo.PrimaryIP
info.hostGateway = response.PodIPInfo[i].HostSecondaryIPInfo.Gateway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wont this affect AKS swift 2.0? it was using this before:


			hostSubnet:         response.PodIPInfo[i].HostPrimaryIPInfo.Subnet,
			hostPrimaryIP:      response.PodIPInfo[i].HostPrimaryIPInfo.PrimaryIP,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it gets secondary interface info from HostSecondaryIPInfo

@@ -45,6 +45,9 @@ const (
ipv6FullMask = 128
)

// Secondary interface NIC types
var secondaryInterfaceNICType = []string{cns.BackendNICNC, string(cns.DelegatedVMNIC)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why typecasting for delegatedvmnic but not for backendnicnc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's because they are defined in different types on CNS codes, I can update CNS code

cniResult := cniTypesCurr.Result{}
// Add secondaryInterface info to result if it exists; otherwise add default primary interface info to result
if hasSecondaryInterface(ipamAddResult) {
cniResult = *convertInterfaceInfoToCniResult(ipamAddResult.secondaryInterfacesInfo[0], args.IfName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can it be cniResult = convertInterfaceInfoToCniResult(ipamAddResult.secondaryInterfacesInfo[0], args.IfName)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if required , define a new variable.. but lets not make code convoluted

@@ -450,6 +455,13 @@ func configureSecondaryAddResult(info *IPResultInfo, addResult *IPAMAddResult, p
return errors.Wrap(err, "Invalid mac address")
}

_, hostIPNet, err := net.ParseCIDR(info.hostSubnet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this is required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because we do need "hostSubnetPrefix" to find master interface if you check findMasterInterface()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check based on macAddress instead?

@@ -45,6 +45,9 @@ const (
ipv6FullMask = 128
)

// Secondary interface NIC types
var secondaryInterfaceNICType = []string{cns.BackendNICNC, string(cns.DelegatedVMNIC)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should have enum for nic types.. we should resuse from cns package

@@ -362,12 +386,18 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
telemetry.SendCNIMetric(&cniMetric, plugin.tb)

// Add Interfaces to result.
defaultCniResult := convertInterfaceInfoToCniResult(ipamAddResult.defaultInterfaceInfo, args.IfName)
cniResult := cniTypesCurr.Result{}
// Add secondaryInterface info to result if it exists; otherwise add default primary interface info to result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can it be other way.. add secondary interface to result if default interface does not exist

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in design, we have both default and secondary interface info in ipamAddResult;

@@ -460,6 +494,14 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
zap.Any("results", ipamAddResult))
return plugin.Errorf(errMsg)
}
} else if !nwCfg.MultiTenancy && nwCfg.IPAM.Type == network.AzureCNS {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wanted to understand why we need this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because for swiftv2 path, the nwconfig multitenancy must not be set to true which was confused before; and the nwcfg ipam type should be azureCNS

@@ -450,6 +455,13 @@ func configureSecondaryAddResult(info *IPResultInfo, addResult *IPAMAddResult, p
return errors.Wrap(err, "Invalid mac address")
}

_, hostIPNet, err := net.ParseCIDR(info.hostSubnet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check based on macAddress instead?

@@ -78,6 +81,14 @@ type NetPlugin struct {
multitenancyClient MultitenancyClient
}

// save secondary interface usage with ipNet and macAddress properties
var SecondaryInterfaces map[string]SecondaryInterfaceProperty
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's key here? Add a comment on it

Comment on lines 329 to 338
func hasSecondaryInterface(ipamAddResult IPAMAddResult) bool {
if ipamAddResult.secondaryInterfacesInfo != nil {
for _, interfaceNICType := range secondaryInterfaceNICType {
if string(ipamAddResult.secondaryInterfacesInfo[0].NICType) == interfaceNICType {
return true
}
}
}
return false
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should just check `len(secondaryInterfacesInfo)>0``

interfaceInfo := network.InterfaceInfo{}
// find ipnet from secondaryInterfaceInfo if it exists;
if hasSecondaryInterface(ipamAddResult) {
interfaceInfo = ipamAddResult.secondaryInterfacesInfo[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets iterate instead of assuming index 0 will be expected nic info

macAddress = ipamAddResult.secondaryInterfacesInfo[0].MacAddress.String()
}

masterIfName := plugin.findMasterInterface(ipamAddConfig.nwCfg, &ipnet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find master interface by macAddress if hostSubnetPrefix is not provided or interface couldn't find

// Get secondary interface info from CNI state file and save them to ipamAddResult in CNI Delete call
secondaryInterfaceInfo, err := plugin.nm.GetNetworkSecondaryInterfaceInfo(endpointID)
if err != nil {
logger.Error("Failed to get secondaryInterfaceInfo", zap.Error(err))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change level to info
log endpointID

logger.Error("Failed to get secondaryInterfaceInfo", zap.Error(err))
}

ipamAddResult.secondaryInterfacesInfo = []network.InterfaceInfo{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err == nil {
then set this
}

endpointID := plugin.nm.GetEndpointID(args.ContainerID, args.IfName)

// Get secondary interface info from CNI state file and save them to ipamAddResult in CNI Delete call
secondaryInterfaceInfo, err := plugin.nm.GetNetworkSecondaryInterfaceInfo(endpointID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not be specfic call for each interface, instead it should fetch all interface associated with that containerID

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will address in stateless cni

@@ -1032,6 +1120,16 @@ func (plugin *NetPlugin) Delete(args *cniSkel.CmdArgs) error {
err = plugin.Errorf("Failed to extract network name from network config. error: %v", err)
return err
}

// cleanup interfaces usage map for swiftv2 L1VH and delete hnsNetwork associated with this networkID
if &ipamAddResult != nil && ipamAddResult.secondaryInterfacesInfo != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change ipamAddResult to pointer otherwise

@@ -1049,7 +1147,6 @@ func (plugin *NetPlugin) Delete(args *cniSkel.CmdArgs) error {
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line is on line 1082, just moved to the above

cni/api/api.go Show resolved Hide resolved
@@ -1049,7 +1147,6 @@ func (plugin *NetPlugin) Delete(args *cniSkel.CmdArgs) error {
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line is on line 1082, just moved to the above

Comment on lines 81 to 87
// save secondary interface property
// key is secondary interface name and value is its macAddress
var SecondaryInterfaces map[string]SecondaryInterfaceProperty

type SecondaryInterfaceProperty struct {
macAddress string
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if its not required, lets remove

@@ -217,6 +226,14 @@ func (plugin *NetPlugin) findMasterInterface(nwCfg *cni.NetworkConfig, subnetPre
subnetPrefixString := subnetPrefix.String()
interfaces, _ := net.Interfaces()
for _, iface := range interfaces {
if subnetPrefixString == "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a new function findMasterInterfaceByMac

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would be branch to this vs the default function used by other paths?

@@ -362,12 +387,17 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
telemetry.SendCNIMetric(&cniMetric, plugin.tb)

// Add Interfaces to result.
defaultCniResult := convertInterfaceInfoToCniResult(ipamAddResult.defaultInterfaceInfo, args.IfName)
cniResult := &cniTypesCurr.Result{}
cniResult = convertInterfaceInfoToCniResult(ipamAddResult.defaultInterfaceInfo, args.IfName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add UT for this?

cniResult := &cniTypesCurr.Result{}
cniResult = convertInterfaceInfoToCniResult(ipamAddResult.defaultInterfaceInfo, args.IfName)
// if defaultInterfaceInfo does not exist, then try to use secondaryInterfaceInfo
if cniResult == nil && hasSecondaryInterface(ipamAddResult) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should append to result.Interface since its an array and not overwrite it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked with Kshitija and we only add one NC at a time and the secondary interface is always the first element of the secondaryInterfacesInfo

Comment on lines 467 to 469

options := make(map[string]any)
ipamAddConfig := IPAMAddConfig{nwCfg: nwCfg, args: args, options: options}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not required, lets remove it

Copy link

This pull request is stale because it has been open for 2 weeks with no activity. Remove stale label or comment or this will be closed in 7 days

@github-actions github-actions bot added the stale Stale due to inactivity. label Mar 13, 2024
Copy link

Pull request closed due to inactivity.

@github-actions github-actions bot closed this Mar 21, 2024
@github-actions github-actions bot deleted the CNIL1VHBranch branch March 21, 2024 00:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cni Related to CNI. stale Stale due to inactivity.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants