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

Add UTs to configure secondary interfaces add Result for windows swiftv2 #2923

Merged
merged 12 commits into from
Aug 23, 2024
340 changes: 340 additions & 0 deletions cni/network/invoker_cns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2151,3 +2151,343 @@ func TestShallowCopyIpamAddConfigOptions(t *testing.T) {
nullRes := nullOpts.shallowCopyIpamAddConfigOptions()
require.Equal(t, map[string]interface{}{}, nullRes)
}

// Test addBackendNICToResult() and configureSecondaryAddResult() to update secondary interfaces to cni Result
func TestAddNICsToCNIResult(t *testing.T) {
require := require.New(t) //nolint further usage of require without passing t

macAddress := "bc:9a:78:56:34:12"
newMacAddress := "bc:9a:78:56:34:45"
newParsedMacAddress, _ := net.ParseMAC(newMacAddress)
newNCGatewayIPAddress := "40.0.0.1"

pnpID := "PCI\\VEN_15B3&DEV_101C&SUBSYS_000715B3&REV_00\\5&8c5acce&0&0"
newPnpID := "PCI\\VEN_15B3&DEV_101C&SUBSYS_000715B3&REV_00\\5&8c5acce&0&1"

newPodIPConfig := &cns.IPSubnet{
IPAddress: "30.1.1.10",
PrefixLength: 24,
}

newIP, newIPNet, _ := newPodIPConfig.GetIPNet()

type fields struct {
podName string
podNamespace string
cnsClient cnsclient
}

type args struct {
nwCfg *cni.NetworkConfig
args *cniSkel.CmdArgs
hostSubnetPrefix *net.IPNet
options map[string]interface{}
info IPResultInfo
podIPConfig *cns.IPSubnet
}

tests := []struct {
name string
fields fields
args args
wantSecondaryInterfacesInfo map[string]network.InterfaceInfo
}{
{
name: "add new backendNIC to cni Result",
fields: fields{
podName: testPodInfo.PodName,
podNamespace: testPodInfo.PodNamespace,
cnsClient: &MockCNSClient{
require: require,
requestIPs: requestIPsHandler{
ipconfigArgument: cns.IPConfigsRequest{
PodInterfaceID: "testcont-testifname1",
InfraContainerID: "testcontainerid1",
OrchestratorContext: marshallPodInfo(testPodInfo),
},
result: &cns.IPConfigsResponse{
PodIPInfo: []cns.PodIpInfo{
{
PodIPConfig: cns.IPSubnet{
IPAddress: "10.0.1.10",
PrefixLength: 24,
},
NetworkContainerPrimaryIPConfig: cns.IPConfiguration{
IPSubnet: cns.IPSubnet{
IPAddress: "10.0.1.0",
PrefixLength: 24,
},
DNSServers: nil,
GatewayIPAddress: "10.0.0.1",
},
HostPrimaryIPInfo: cns.HostIPInfo{
Gateway: "10.0.0.1",
PrimaryIP: "10.0.0.1",
Subnet: "10.0.0.0/24",
},
NICType: cns.InfraNIC,
},
{
MacAddress: macAddress,
NICType: cns.BackendNIC,
PnPID: pnpID,
},
},
Response: cns.Response{
ReturnCode: 0,
Message: "",
},
},
err: nil,
},
},
},
args: args{
nwCfg: &cni.NetworkConfig{},
args: &cniSkel.CmdArgs{
ContainerID: "testcontainerid1",
Netns: "testnetns1",
IfName: "testifname1",
},
hostSubnetPrefix: getCIDRNotationForAddress("10.0.0.1/24"),
options: map[string]interface{}{},
// update new pnpID, macAddress
info: IPResultInfo{
pnpID: newPnpID,
macAddress: newMacAddress,
nicType: cns.BackendNIC,
},
},
wantSecondaryInterfacesInfo: map[string]network.InterfaceInfo{
macAddress: {
MacAddress: newParsedMacAddress,
PnPID: newPnpID,
NICType: cns.BackendNIC,
},
},
},
{
name: "add new delegatedVMNIC to cni Result",
fields: fields{
podName: testPodInfo.PodName,
podNamespace: testPodInfo.PodNamespace,
cnsClient: &MockCNSClient{
require: require,
requestIPs: requestIPsHandler{
ipconfigArgument: cns.IPConfigsRequest{
PodInterfaceID: "testcont-testifname1",
InfraContainerID: "testcontainerid1",
OrchestratorContext: marshallPodInfo(testPodInfo),
},
result: &cns.IPConfigsResponse{
PodIPInfo: []cns.PodIpInfo{
{
PodIPConfig: cns.IPSubnet{
IPAddress: "10.0.1.10",
PrefixLength: 24,
},
NetworkContainerPrimaryIPConfig: cns.IPConfiguration{
IPSubnet: cns.IPSubnet{
IPAddress: "10.0.1.0",
PrefixLength: 24,
},
DNSServers: nil,
GatewayIPAddress: "10.0.0.1",
},
HostPrimaryIPInfo: cns.HostIPInfo{
Gateway: "10.0.0.1",
PrimaryIP: "10.0.0.1",
Subnet: "10.0.0.0/24",
},
NICType: cns.InfraNIC,
SkipDefaultRoutes: true,
},
{
PodIPConfig: cns.IPSubnet{
IPAddress: "20.1.1.10",
PrefixLength: 24,
},
HostPrimaryIPInfo: cns.HostIPInfo{
Gateway: "20.0.0.1",
PrimaryIP: "20.0.0.2",
Subnet: "20.0.0.1/24",
},
NICType: cns.NodeNetworkInterfaceFrontendNIC,
MacAddress: macAddress,
},
},
Response: cns.Response{
ReturnCode: 0,
Message: "",
},
},
err: nil,
},
},
},
args: args{
nwCfg: &cni.NetworkConfig{},
args: &cniSkel.CmdArgs{
ContainerID: "testcontainerid1",
Netns: "testnetns1",
IfName: "testifname1",
},
hostSubnetPrefix: getCIDRNotationForAddress("10.0.0.1/24"),
options: map[string]interface{}{},
// update podIPConfig
podIPConfig: newPodIPConfig,
// update new mac address and ncGatewayIPAddress
info: IPResultInfo{
macAddress: newMacAddress,
nicType: cns.NodeNetworkInterfaceFrontendNIC,
ncGatewayIPAddress: newNCGatewayIPAddress,
},
},
wantSecondaryInterfacesInfo: map[string]network.InterfaceInfo{
macAddress: {
MacAddress: newParsedMacAddress,
NICType: cns.NodeNetworkInterfaceFrontendNIC,
IPConfigs: []*network.IPConfig{
{
Address: net.IPNet{
IP: newIP,
Mask: newIPNet.Mask,
},
Gateway: net.ParseIP(newNCGatewayIPAddress),
},
},
Routes: []network.RouteInfo{},
},
},
},
{
name: "add new accelnetNIC to cni Result",
fields: fields{
podName: testPodInfo.PodName,
podNamespace: testPodInfo.PodNamespace,
cnsClient: &MockCNSClient{
require: require,
requestIPs: requestIPsHandler{
ipconfigArgument: cns.IPConfigsRequest{
PodInterfaceID: "testcont-testifname1",
InfraContainerID: "testcontainerid1",
OrchestratorContext: marshallPodInfo(testPodInfo),
},
result: &cns.IPConfigsResponse{
PodIPInfo: []cns.PodIpInfo{
{
PodIPConfig: cns.IPSubnet{
IPAddress: "10.0.1.10",
PrefixLength: 24,
},
NetworkContainerPrimaryIPConfig: cns.IPConfiguration{
IPSubnet: cns.IPSubnet{
IPAddress: "10.0.1.0",
PrefixLength: 24,
},
DNSServers: nil,
GatewayIPAddress: "10.0.0.1",
},
HostPrimaryIPInfo: cns.HostIPInfo{
Gateway: "10.0.0.1",
PrimaryIP: "10.0.0.1",
Subnet: "10.0.0.0/24",
},
NICType: cns.InfraNIC,
SkipDefaultRoutes: true,
},
{
PodIPConfig: cns.IPSubnet{
IPAddress: "20.1.1.10",
PrefixLength: 24,
},
HostPrimaryIPInfo: cns.HostIPInfo{
Gateway: "20.0.0.1",
PrimaryIP: "20.0.0.2",
Subnet: "20.0.0.1/24",
},
NICType: cns.NodeNetworkInterfaceAccelnetFrontendNIC,
MacAddress: macAddress,
},
},
Response: cns.Response{
ReturnCode: 0,
Message: "",
},
},
err: nil,
},
},
},
args: args{
nwCfg: &cni.NetworkConfig{},
args: &cniSkel.CmdArgs{
ContainerID: "testcontainerid1",
Netns: "testnetns1",
IfName: "testifname1",
},
hostSubnetPrefix: getCIDRNotationForAddress("10.0.0.1/24"),
options: map[string]interface{}{},
// update podIPConfig
podIPConfig: newPodIPConfig,
// update new mac address and ncGatewayIPAddress
info: IPResultInfo{
macAddress: newMacAddress,
nicType: cns.NodeNetworkInterfaceFrontendNIC,
ncGatewayIPAddress: newNCGatewayIPAddress,
},
},
wantSecondaryInterfacesInfo: map[string]network.InterfaceInfo{
macAddress: {
MacAddress: newParsedMacAddress,
NICType: cns.NodeNetworkInterfaceFrontendNIC,
IPConfigs: []*network.IPConfig{
{
Address: net.IPNet{
IP: newIP,
Mask: newIPNet.Mask,
},
Gateway: net.ParseIP(newNCGatewayIPAddress),
},
},
Routes: []network.RouteInfo{},
},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
invoker := &CNSIPAMInvoker{
podName: tt.fields.podName,
podNamespace: tt.fields.podNamespace,
cnsClient: tt.fields.cnsClient,
}
ipamAddResult, err := invoker.Add(IPAMAddConfig{nwCfg: tt.args.nwCfg, args: tt.args.args, options: tt.args.options})
if err != nil {
t.Fatalf("Failed to create ipamAddResult due to error: %v", err)
}

for _, ifInfo := range ipamAddResult.interfaceInfo {
if ifInfo.NICType == cns.BackendNIC {
// add new backendNIC info to cni Result
err := addBackendNICToResult(&tt.args.info, &ipamAddResult, macAddress)
if err != nil {
t.Fatalf("Failed to add backend NIC to cni Result due to error %v", err)
}
fmt.Printf("want:%+v\nrest:%+v\n", tt.wantSecondaryInterfacesInfo, ipamAddResult.interfaceInfo[macAddress])
require.EqualValues(tt.wantSecondaryInterfacesInfo[macAddress], ipamAddResult.interfaceInfo[macAddress], "incorrect response for IB")
}
if ifInfo.NICType == cns.NodeNetworkInterfaceFrontendNIC || ifInfo.NICType == cns.NodeNetworkInterfaceAccelnetFrontendNIC {
// add new secondaryInterfaceNIC to cni Result
err := configureSecondaryAddResult(&tt.args.info, &ipamAddResult, tt.args.podIPConfig, macAddress)
if err != nil {
t.Fatalf("Failed to add secondary interface NIC %s to cni Result due to error %v", ifInfo.NICType, err)
}
fmt.Printf("want:%+v\nrest:%+v\n", tt.wantSecondaryInterfacesInfo, ipamAddResult.interfaceInfo[macAddress])
require.EqualValues(tt.wantSecondaryInterfacesInfo[macAddress], ipamAddResult.interfaceInfo[macAddress], "incorrect response for delegatedVMNIC/accelnetNIC")
}
}
})
}
}
8 changes: 5 additions & 3 deletions cni/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,9 +686,11 @@ func (plugin *NetPlugin) findMasterInterface(opt *createEpInfoOpt) string {
return plugin.findMasterInterfaceBySubnet(opt.ipamAddConfig.nwCfg, &opt.ifInfo.HostSubnetPrefix)
case cns.NodeNetworkInterfaceFrontendNIC, cns.NodeNetworkInterfaceAccelnetFrontendNIC:
return plugin.findInterfaceByMAC(opt.ifInfo.MacAddress.String())
case cns.BackendNIC: // TODO: how to find interface with IB NIC by mac address
opt.ifInfo.Name = ibInterfacePrefix + strconv.Itoa(opt.endpointIndex)
return opt.ifInfo.Name
case cns.BackendNIC:
// if windows swiftv2 has right network drivers, there will be an NDIS interface while the VFs are mounted
// when the VF is dismounted, this interface will go away
// return an unique interface name to containerd
return ibInterfacePrefix + strconv.Itoa(opt.endpointIndex)
tamilmani1989 marked this conversation as resolved.
Show resolved Hide resolved
default:
return ""
}
Expand Down
Loading
Loading