diff --git a/cni/network/invoker_cns.go b/cni/network/invoker_cns.go index 36d95209d2e..1a832ac09a8 100644 --- a/cni/network/invoker_cns.go +++ b/cni/network/invoker_cns.go @@ -166,7 +166,7 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro //nolint:exhaustive // ignore exhaustive types check switch info.nicType { case cns.DelegatedVMNIC: - // only handling single v4 PodIPInfo for Frontend NICs at the moment, will have to update once v6 gets added + // only handling single v4 PodIPInfo for DelegatedVMNICs at the moment, will have to update once v6 gets added if !info.skipDefaultRoutes { numInterfacesWithDefaultRoutes++ } diff --git a/cns/NetworkContainerContract.go b/cns/NetworkContainerContract.go index 51dcce2bd26..86b9446cc6f 100644 --- a/cns/NetworkContainerContract.go +++ b/cns/NetworkContainerContract.go @@ -78,18 +78,10 @@ type NICType string // NIC Types const ( InfraNIC NICType = "InfraNIC" - // DelegatedVMNIC are projected from VM to container network namespace + // Delegated VM NICs are projected from VM to container network namespace DelegatedVMNIC NICType = "DelegatedVMNIC" - // BackendNIC are used for infiniband NICs on a VM + // BackendNIC NICs are used for infiniband nics on a VM BackendNIC NICType = "BackendNIC" - // NodeNetworkInterfaceAccelnetFrontendNIC is a type of front-end nic that offers accelerated networking performance - NodeNetworkInterfaceAccelnetFrontendNIC NICType = "FrontendNIC_Accelnet" - - // TODO: These two const are currently unused due to version compatibility with DNC. DelegatedVMNIC and NodeNetworkInterfaceBackendNIC should be renamed to align with the naming convention with DNC - // NodeNetworkInterfaceFrontendNIC is the new name for DelegatedVMNIC - NodeNetworkInterfaceFrontendNIC NICType = "FrontendNIC" - // NodeNetworkInterfaceBackendNIC is the new name for BackendNIC - NodeNetworkInterfaceBackendNIC NICType = "BackendNIC" ) // ChannelMode :- CNS channel modes @@ -489,8 +481,9 @@ type PodIpInfo struct { PodIPConfig IPSubnet NetworkContainerPrimaryIPConfig IPConfiguration HostPrimaryIPInfo HostIPInfo - NICType NICType - InterfaceName string + // NICType defines whether NIC is InfraNIC or DelegatedVMNIC or BackendNIC + NICType NICType + InterfaceName string // MacAddress of interface MacAddress string // SkipDefaultRoutes is true if default routes should not be added on interface diff --git a/cns/middlewares/k8sSwiftV2.go b/cns/middlewares/k8sSwiftV2.go index bf8919cf97b..a9721c39950 100644 --- a/cns/middlewares/k8sSwiftV2.go +++ b/cns/middlewares/k8sSwiftV2.go @@ -3,6 +3,8 @@ package middlewares import ( "context" "fmt" + "net/netip" + "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/cns/configuration" "github.com/Azure/azure-container-networking/cns/logger" @@ -37,9 +39,9 @@ var _ cns.IPConfigsHandlerMiddleware = (*K8sSWIFTv2Middleware)(nil) // IPConfigsRequestHandlerWrapper is the middleware function for handling SWIFT v2 IP configs requests for AKS-SWIFT. This function wrapped the default SWIFT request // and release IP configs handlers. -func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc { +func (m *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc { return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) { - podInfo, respCode, message := k.validateIPConfigsRequest(ctx, &req) + podInfo, respCode, message := m.validateIPConfigsRequest(ctx, &req) if respCode != types.Success { return &cns.IPConfigsResponse{ @@ -47,7 +49,7 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa ReturnCode: respCode, Message: message, }, - }, errors.New("failed to validate IP configs request") + }, errors.New("failed to validate ip configs request") } ipConfigsResp, err := defaultHandler(ctx, req) // If the pod is not v2, return the response from the handler @@ -67,7 +69,7 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa if err != nil { return ipConfigsResp, err } - SWIFTv2PodIPInfos, err := k.getIPConfig(ctx, podInfo) + SWIFTv2PodIPInfo, err := m.getIPConfig(ctx, podInfo) if err != nil { return &cns.IPConfigsResponse{ Response: cns.Response{ @@ -77,11 +79,11 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa PodIPInfo: []cns.PodIpInfo{}, }, errors.Wrapf(err, "failed to get SWIFTv2 IP config : %v", req) } - ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfos...) + ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfo) // Set routes for the pod for i := range ipConfigsResp.PodIPInfo { ipInfo := &ipConfigsResp.PodIPInfo[i] - err = k.setRoutes(ipInfo) + err = m.setRoutes(ipInfo) if err != nil { return &cns.IPConfigsResponse{ Response: cns.Response{ @@ -98,7 +100,7 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa // validateIPConfigsRequest validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario. // nolint -func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) { +func (m *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) { // Retrieve the pod from the cluster podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext) if err != nil { @@ -108,7 +110,7 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name()) podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()} pod := v1.Pod{} - if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil { + if err := m.Cli.Get(ctx, podNamespacedName, &pod); err != nil { errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName) return nil, types.UnexpectedError, errBuf.Error() } @@ -119,11 +121,11 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req // Check if the MTPNC CRD exists for the pod, if not, return error mtpnc := v1alpha1.MultitenantPodNetworkConfig{} mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()} - if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil { + if err := m.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil { return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error() } // Check if the MTPNC CRD is ready. If one of the fields is empty, return error - if !mtpnc.IsReady() { + if mtpnc.Status.PrimaryIP == "" || mtpnc.Status.MacAddress == "" || mtpnc.Status.NCID == "" || mtpnc.Status.GatewayIP == "" { return nil, types.UnexpectedError, errMTPNCNotReady.Error() } } @@ -133,78 +135,150 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req } // getIPConfig returns the pod's SWIFT V2 IP configuration. -func (k *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodInfo) ([]cns.PodIpInfo, error) { +func (m *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodInfo) (cns.PodIpInfo, error) { // Check if the MTPNC CRD exists for the pod, if not, return error mtpnc := v1alpha1.MultitenantPodNetworkConfig{} mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()} - if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil { - return nil, errors.Wrapf(err, "failed to get pod's mtpnc from cache") + if err := m.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil { + return cns.PodIpInfo{}, errors.Wrapf(err, "failed to get pod's mtpnc from cache") } // Check if the MTPNC CRD is ready. If one of the fields is empty, return error - if !mtpnc.IsReady() { - return nil, errMTPNCNotReady + if mtpnc.Status.PrimaryIP == "" || mtpnc.Status.MacAddress == "" || mtpnc.Status.NCID == "" || mtpnc.Status.GatewayIP == "" { + return cns.PodIpInfo{}, errMTPNCNotReady } logger.Printf("[SWIFTv2Middleware] mtpnc for pod %s is : %+v", podInfo.Name(), mtpnc) - var podIPInfos []cns.PodIpInfo + // Parse MTPNC primaryIP to get the IP address and prefix length + p, err := netip.ParsePrefix(mtpnc.Status.PrimaryIP) + if err != nil { + return cns.PodIpInfo{}, errors.Wrapf(err, "failed to parse mtpnc primaryIP %s", mtpnc.Status.PrimaryIP) + } + // Get the IP address and prefix length + ip := p.Addr() + prefixSize := p.Bits() + if prefixSize != prefixLength { + return cns.PodIpInfo{}, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) + } + podIPInfo := cns.PodIpInfo{ + PodIPConfig: cns.IPSubnet{ + IPAddress: ip.String(), + PrefixLength: uint8(prefixSize), + }, + MacAddress: mtpnc.Status.MacAddress, + NICType: cns.DelegatedVMNIC, + SkipDefaultRoutes: false, + // InterfaceName is empty for DelegatedVMNIC + } + + return podIPInfo, nil +} - if len(mtpnc.Status.InterfaceInfos) == 0 { - // Use fields from mtpnc.Status if InterfaceInfos is empty - ip, prefixSize, err := utils.ParseIPAndPrefix(mtpnc.Status.PrimaryIP) +// setRoutes sets the routes for podIPInfo used in SWIFT V2 scenario. +func (m *K8sSWIFTv2Middleware) setRoutes(podIPInfo *cns.PodIpInfo) error { + logger.Printf("[SWIFTv2Middleware] set routes for pod with nic type : %s", podIPInfo.NICType) + podIPInfo.Routes = []cns.Route{} + switch podIPInfo.NICType { + case cns.DelegatedVMNIC: + virtualGWRoute := cns.Route{ + IPAddress: fmt.Sprintf("%s/%d", virtualGW, prefixLength), + } + // default route via SWIFT v2 interface + route := cns.Route{ + IPAddress: "0.0.0.0/0", + GatewayIPAddress: virtualGW, + } + podIPInfo.Routes = []cns.Route{virtualGWRoute, route} + case cns.InfraNIC: + // Get and parse infraVNETCIDRs from env + infraVNETCIDRs, err := configuration.InfraVNETCIDRs() if err != nil { - return nil, errors.Wrap(err, "failed to parse mtpnc primary IP and prefix") - } - if prefixSize != prefixLength { - return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) - } - - podIPInfos = append(podIPInfos, cns.PodIpInfo{ - PodIPConfig: cns.IPSubnet{ - IPAddress: ip, - PrefixLength: uint8(prefixSize), - }, - MacAddress: mtpnc.Status.MacAddress, - NICType: cns.DelegatedVMNIC, - SkipDefaultRoutes: false, - // InterfaceName is empty for DelegatedVMNIC - }) - } else { - // Use InterfaceInfos if not empty - podIPInfos = make([]cns.PodIpInfo, len(mtpnc.Status.InterfaceInfos)) - for i, interfaceInfo := range mtpnc.Status.InterfaceInfos { - // Parse MTPNC primaryIP to get the IP address and prefix length - ip, prefixSize, err := utils.ParseIPAndPrefix(interfaceInfo.PrimaryIP) - if err != nil { - return nil, errors.Wrap(err, "failed to parse mtpnc primary IP and prefix") + return errors.Wrapf(err, "failed to get infraVNETCIDRs from env") + } + infraVNETCIDRsv4, infraVNETCIDRsv6, err := utils.ParseCIDRs(infraVNETCIDRs) + if err != nil { + return errors.Wrapf(err, "failed to parse infraVNETCIDRs") + } + + // Get and parse podCIDRs from env + podCIDRs, err := configuration.PodCIDRs() + if err != nil { + return errors.Wrapf(err, "failed to get podCIDRs from env") + } + podCIDRsV4, podCIDRv6, err := utils.ParseCIDRs(podCIDRs) + if err != nil { + return errors.Wrapf(err, "failed to parse podCIDRs") + } + + // Get and parse serviceCIDRs from env + serviceCIDRs, err := configuration.ServiceCIDRs() + if err != nil { + return errors.Wrapf(err, "failed to get serviceCIDRs from env") + } + serviceCIDRsV4, serviceCIDRsV6, err := utils.ParseCIDRs(serviceCIDRs) + if err != nil { + return errors.Wrapf(err, "failed to parse serviceCIDRs") + } + // Check if the podIPInfo is IPv4 or IPv6 + ip, err := netip.ParseAddr(podIPInfo.PodIPConfig.IPAddress) + if err != nil { + return errors.Wrapf(err, "failed to parse podIPConfig IP address %s", podIPInfo.PodIPConfig.IPAddress) + } + if ip.Is4() { + // routes for IPv4 podCIDR traffic + for _, podCIDRv4 := range podCIDRsV4 { + podCIDRv4Route := cns.Route{ + IPAddress: podCIDRv4, + GatewayIPAddress: overlayGatewayv4, + } + podIPInfo.Routes = append(podIPInfo.Routes, podCIDRv4Route) } - if prefixSize != prefixLength { - return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) + // route for IPv4 serviceCIDR traffic + for _, serviceCIDRv4 := range serviceCIDRsV4 { + serviceCIDRv4Route := cns.Route{ + IPAddress: serviceCIDRv4, + GatewayIPAddress: overlayGatewayv4, + } + podIPInfo.Routes = append(podIPInfo.Routes, serviceCIDRv4Route) } - - var nicType cns.NICType - switch { - case interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC && !interfaceInfo.AccelnetEnabled: - nicType = cns.DelegatedVMNIC - case interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC && interfaceInfo.AccelnetEnabled: - nicType = cns.NodeNetworkInterfaceAccelnetFrontendNIC - case interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC: - nicType = cns.NodeNetworkInterfaceBackendNIC - default: - nicType = cns.DelegatedVMNIC + // route for IPv4 infraVNETCIDR traffic + for _, infraVNETCIDRv4 := range infraVNETCIDRsv4 { + infraVNETCIDRv4Route := cns.Route{ + IPAddress: infraVNETCIDRv4, + GatewayIPAddress: overlayGatewayv4, + } + podIPInfo.Routes = append(podIPInfo.Routes, infraVNETCIDRv4Route) } - - podIPInfos[i] = cns.PodIpInfo{ - PodIPConfig: cns.IPSubnet{ - IPAddress: ip, - PrefixLength: uint8(prefixSize), - }, - MacAddress: interfaceInfo.MacAddress, - NICType: nicType, - SkipDefaultRoutes: false, + } else { + // routes for IPv6 podCIDR traffic + for _, podCIDRv6 := range podCIDRv6 { + podCIDRv6Route := cns.Route{ + IPAddress: podCIDRv6, + GatewayIPAddress: overlayGatewayV6, + } + podIPInfo.Routes = append(podIPInfo.Routes, podCIDRv6Route) + } + // route for IPv6 serviceCIDR traffic + for _, serviceCIDRv6 := range serviceCIDRsV6 { + serviceCIDRv6Route := cns.Route{ + IPAddress: serviceCIDRv6, + GatewayIPAddress: overlayGatewayV6, + } + podIPInfo.Routes = append(podIPInfo.Routes, serviceCIDRv6Route) + } + // route for IPv6 infraVNETCIDR traffic + for _, infraVNETCIDRv6 := range infraVNETCIDRsv6 { + infraVNETCIDRv6Route := cns.Route{ + IPAddress: infraVNETCIDRv6, + GatewayIPAddress: overlayGatewayV6, + } + podIPInfo.Routes = append(podIPInfo.Routes, infraVNETCIDRv6Route) } } + podIPInfo.SkipDefaultRoutes = true + case cns.BackendNIC: + default: + return errInvalidSWIFTv2NICType } - - return podIPInfos, nil + return nil } diff --git a/cns/middlewares/k8sSwiftV2_linux.go b/cns/middlewares/k8sSwiftV2_linux.go deleted file mode 100644 index 30b3db7700f..00000000000 --- a/cns/middlewares/k8sSwiftV2_linux.go +++ /dev/null @@ -1,97 +0,0 @@ -package middlewares - -import ( - "fmt" - "net/netip" - - "github.com/Azure/azure-container-networking/cns" - "github.com/Azure/azure-container-networking/cns/configuration" - "github.com/Azure/azure-container-networking/cns/logger" - "github.com/Azure/azure-container-networking/cns/middlewares/utils" - "github.com/pkg/errors" -) - -// setRoutes sets the routes for podIPInfo used in SWIFT V2 scenario. -func (k *K8sSWIFTv2Middleware) setRoutes(podIPInfo *cns.PodIpInfo) error { - logger.Printf("[SWIFTv2Middleware] set routes for pod with nic type : %s", podIPInfo.NICType) - var routes []cns.Route - - switch podIPInfo.NICType { - case cns.DelegatedVMNIC: - virtualGWRoute := cns.Route{ - IPAddress: fmt.Sprintf("%s/%d", virtualGW, prefixLength), - } - // default route via SWIFT v2 interface - route := cns.Route{ - IPAddress: "0.0.0.0/0", - GatewayIPAddress: virtualGW, - } - routes = append(routes, virtualGWRoute, route) - - case cns.InfraNIC: - // Get and parse infraVNETCIDRs from env - infraVNETCIDRs, err := configuration.InfraVNETCIDRs() - if err != nil { - return errors.Wrapf(err, "failed to get infraVNETCIDRs from env") - } - infraVNETCIDRsv4, infraVNETCIDRsv6, err := utils.ParseCIDRs(infraVNETCIDRs) - if err != nil { - return errors.Wrapf(err, "failed to parse infraVNETCIDRs") - } - - // Get and parse podCIDRs from env - podCIDRs, err := configuration.PodCIDRs() - if err != nil { - return errors.Wrapf(err, "failed to get podCIDRs from env") - } - podCIDRsV4, podCIDRv6, err := utils.ParseCIDRs(podCIDRs) - if err != nil { - return errors.Wrapf(err, "failed to parse podCIDRs") - } - - // Get and parse serviceCIDRs from env - serviceCIDRs, err := configuration.ServiceCIDRs() - if err != nil { - return errors.Wrapf(err, "failed to get serviceCIDRs from env") - } - serviceCIDRsV4, serviceCIDRsV6, err := utils.ParseCIDRs(serviceCIDRs) - if err != nil { - return errors.Wrapf(err, "failed to parse serviceCIDRs") - } - - ip, err := netip.ParseAddr(podIPInfo.PodIPConfig.IPAddress) - if err != nil { - return errors.Wrapf(err, "failed to parse podIPConfig IP address %s", podIPInfo.PodIPConfig.IPAddress) - } - - if ip.Is4() { - routes = append(routes, addRoutes(podCIDRsV4, overlayGatewayv4)...) - routes = append(routes, addRoutes(serviceCIDRsV4, overlayGatewayv4)...) - routes = append(routes, addRoutes(infraVNETCIDRsv4, overlayGatewayv4)...) - } else { - routes = append(routes, addRoutes(podCIDRv6, overlayGatewayV6)...) - routes = append(routes, addRoutes(serviceCIDRsV6, overlayGatewayV6)...) - routes = append(routes, addRoutes(infraVNETCIDRsv6, overlayGatewayV6)...) - } - podIPInfo.SkipDefaultRoutes = true - - case cns.NodeNetworkInterfaceBackendNIC, cns.NodeNetworkInterfaceAccelnetFrontendNIC: //nolint:exhaustive // ignore exhaustive types check - // No-op NIC types. - default: - return errInvalidSWIFTv2NICType - } - - podIPInfo.Routes = routes - return nil -} - -func addRoutes(cidrs []string, gatewayIP string) []cns.Route { - routes := make([]cns.Route, len(cidrs)) - for i, cidr := range cidrs { - routes[i] = cns.Route{ - IPAddress: cidr, - GatewayIPAddress: gatewayIP, - } - } - return routes -} diff --git a/cns/middlewares/k8sSwiftV2_test_linux.go b/cns/middlewares/k8sSwiftV2_test.go similarity index 73% rename from cns/middlewares/k8sSwiftV2_test_linux.go rename to cns/middlewares/k8sSwiftV2_test.go index 8a5fa2b0ca7..856c4cd5211 100644 --- a/cns/middlewares/k8sSwiftV2_test_linux.go +++ b/cns/middlewares/k8sSwiftV2_test.go @@ -25,15 +25,6 @@ var ( testPod4GUID = "b21e1ee1-fb7e-4e6d-8c68-22ee5049944e" testPod4Info = cns.NewPodInfo("b21e1e-eth0", testPod4GUID, "testpod4", "testpod4namespace") - - testPod5GUID = "898fb8f1-f93e-4c96-9c31-6b89098949a3" - testPod5Info = cns.NewPodInfo("898fb8-eth0", testPod5GUID, "testpod5", "testpod5namespace") - - testPod6GUID = "898fb8f1-f93e-4c96-9c31-6b89098949a3" - testPod6Info = cns.NewPodInfo("898fb8-eth0", testPod6GUID, "testpod6", "testpod6namespace") - - testPod7GUID = "123e4567-e89b-12d3-a456-426614174000" - testPod7Info = cns.NewPodInfo("123e45-eth0", testPod7GUID, "testpod7", "testpod7namespace") ) func TestMain(m *testing.M) { @@ -188,13 +179,10 @@ func TestGetSWIFTv2IPConfigSuccess(t *testing.T) { middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} - ipInfos, err := middleware.getIPConfig(context.TODO(), testPod1Info) + ipInfo, err := middleware.getIPConfig(context.TODO(), testPod1Info) assert.Equal(t, err, nil) - // Ensure that the length of ipInfos matches the number of InterfaceInfos - // Adjust this according to the test setup - assert.Equal(t, len(ipInfos), 1) - assert.Equal(t, ipInfos[0].NICType, cns.DelegatedVMNIC) - assert.Equal(t, ipInfos[0].SkipDefaultRoutes, false) + assert.Equal(t, ipInfo.NICType, cns.DelegatedVMNIC) + assert.Equal(t, ipInfo.SkipDefaultRoutes, false) } func TestGetSWIFTv2IPConfigFailure(t *testing.T) { @@ -343,81 +331,3 @@ func TestSetRoutesFailure(t *testing.T) { } } } - -func TestAddRoutes(t *testing.T) { - cidrs := []string{"10.0.0.0/24", "20.0.0.0/24"} - gatewayIP := "192.168.1.1" - routes := addRoutes(cidrs, gatewayIP) - expectedRoutes := []cns.Route{ - { - IPAddress: "10.0.0.0/24", - GatewayIPAddress: gatewayIP, - }, - { - IPAddress: "20.0.0.0/24", - GatewayIPAddress: gatewayIP, - }, - } - assert.Equal(t, expectedRoutes, routes, "expected routes to match the expected routes") -} - -func TestNICTypeConfigSuccess(t *testing.T) { - middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} - - // Test Accelnet Frontend NIC type - ipInfos, err := middleware.getIPConfig(context.TODO(), testPod6Info) - assert.Equal(t, err, nil) - // Ensure that the length of ipInfos matches the number of InterfaceInfos - // Adjust this according to the test setup - assert.Equal(t, len(ipInfos), 1) - assert.Equal(t, ipInfos[0].NICType, cns.NodeNetworkInterfaceAccelnetFrontendNIC) - - // Test Backend NIC type - ipInfos2, err := middleware.getIPConfig(context.TODO(), testPod5Info) - assert.Equal(t, err, nil) - assert.Equal(t, len(ipInfos2), 1) - assert.Equal(t, ipInfos2[0].NICType, cns.BackendNIC) -} - -func TestGetSWIFTv2IPConfigMultiInterfaceFailure(t *testing.T) { - middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} - - // Pod's MTPNC doesn't exist in cache test - _, err := middleware.getIPConfig(context.TODO(), testPod3Info) - assert.ErrorContains(t, err, mock.ErrMTPNCNotFound.Error()) - - // Pod's MTPNC is not ready test - _, err = middleware.getIPConfig(context.TODO(), testPod4Info) - assert.Error(t, err, errMTPNCNotReady.Error()) -} - -func TestGetSWIFTv2IPConfigMultiInterfaceSuccess(t *testing.T) { - t.Setenv(configuration.EnvPodCIDRs, "10.0.1.10/24,16A0:0010:AB00:001E::2/32") - t.Setenv(configuration.EnvServiceCIDRs, "10.0.0.0/16,16A0:0010:AB00:0000::/32") - t.Setenv(configuration.EnvInfraVNETCIDRs, "10.240.0.1/16,16A0:0020:AB00:0000::/32") - - middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} - - ipInfos, err := middleware.getIPConfig(context.TODO(), testPod7Info) - assert.Equal(t, err, nil) - // Ensure that the length of ipInfos matches the number of InterfaceInfos - // Adjust this according to the test setup in mock client - expectedInterfaceCount := 3 - assert.Equal(t, len(ipInfos), expectedInterfaceCount) - - for _, ipInfo := range ipInfos { - switch ipInfo.NICType { - case cns.DelegatedVMNIC: - assert.Equal(t, ipInfo.NICType, cns.DelegatedVMNIC) - case cns.NodeNetworkInterfaceAccelnetFrontendNIC: - assert.Equal(t, ipInfo.NICType, cns.NodeNetworkInterfaceAccelnetFrontendNIC) - case cns.NodeNetworkInterfaceBackendNIC: - assert.Equal(t, ipInfo.NICType, cns.NodeNetworkInterfaceBackendNIC) - case cns.InfraNIC: - assert.Equal(t, ipInfo.NICType, cns.InfraNIC) - default: - t.Errorf("unexpected NICType: %v", ipInfo.NICType) - } - assert.Equal(t, ipInfo.SkipDefaultRoutes, false) - } -} diff --git a/cns/middlewares/k8sSwiftV2_windows.go b/cns/middlewares/k8sSwiftV2_windows.go deleted file mode 100644 index 361751584e3..00000000000 --- a/cns/middlewares/k8sSwiftV2_windows.go +++ /dev/null @@ -1,12 +0,0 @@ -package middlewares - -import ( - "github.com/Azure/azure-container-networking/cns" - "github.com/Azure/azure-container-networking/cns/logger" -) - -// setRoutes sets the routes for podIPInfo used in SWIFT V2 scenario. This is a no-op as route setting is not applicable for Windows. -func (k *K8sSWIFTv2Middleware) setRoutes(_ *cns.PodIpInfo) error { - logger.Printf("[SWIFTv2Middleware] setRoutes is a no-op on Windows") - return nil -} diff --git a/cns/middlewares/mock/mockClient.go b/cns/middlewares/mock/mockClient.go index 4c2b1adfa93..2456def9fdc 100644 --- a/cns/middlewares/mock/mockClient.go +++ b/cns/middlewares/mock/mockClient.go @@ -42,87 +42,25 @@ func NewClient() *Client { testPod4.Labels = make(map[string]string) testPod4.Labels[configuration.LabelPodSwiftV2] = podNetwork - testPod5 := v1.Pod{} - testPod5.Labels = make(map[string]string) - testPod5.Labels[configuration.LabelPodSwiftV2] = podNetwork - - testPod6 := v1.Pod{} - testPod6.Labels = make(map[string]string) - testPod6.Labels[configuration.LabelPodSwiftV2] = podNetwork - - testPod7 := v1.Pod{} - testPod7.Labels = make(map[string]string) - testPod7.Labels[configuration.LabelPodSwiftV2] = podNetwork - - testInterfaceInfos1 := v1alpha1.InterfaceInfo{ - NCID: "testncid", - PrimaryIP: "192.168.0.1/32", - MacAddress: "00:00:00:00:00:00", - GatewayIP: "10.0.0.1", - DeviceType: v1alpha1.DeviceTypeVnetNIC, - AccelnetEnabled: false, - } - testInterfaceInfos3 := v1alpha1.InterfaceInfo{ - NCID: "testncid", - PrimaryIP: "192.168.0.1/32", - MacAddress: "00:00:00:00:00:00", - GatewayIP: "10.0.0.1", - DeviceType: v1alpha1.DeviceTypeVnetNIC, - AccelnetEnabled: false, - } - testInterfaceInfos5 := v1alpha1.InterfaceInfo{ - NCID: "testncid", - PrimaryIP: "192.168.0.1/32", - MacAddress: "00:00:00:00:00:00", - GatewayIP: "10.0.0.1", - DeviceType: v1alpha1.DeviceTypeInfiniBandNIC, - AccelnetEnabled: true, - } - testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{ Status: v1alpha1.MultitenantPodNetworkConfigStatus{ - InterfaceInfos: []v1alpha1.InterfaceInfo{testInterfaceInfos1}, + PrimaryIP: "192.168.0.1/32", + MacAddress: "00:00:00:00:00:00", + GatewayIP: "10.0.0.1", + NCID: "testncid", }, } testMTPNC2 := v1alpha1.MultitenantPodNetworkConfig{} - testMTPNC3 := v1alpha1.MultitenantPodNetworkConfig{ - Status: v1alpha1.MultitenantPodNetworkConfigStatus{ - InterfaceInfos: []v1alpha1.InterfaceInfo{testInterfaceInfos3}, - }, - } - testMTPNC4 := v1alpha1.MultitenantPodNetworkConfig{} - testMTPNC5 := v1alpha1.MultitenantPodNetworkConfig{ - Status: v1alpha1.MultitenantPodNetworkConfigStatus{ - InterfaceInfos: []v1alpha1.InterfaceInfo{testInterfaceInfos5}, - }, - } - - testMTPNCMulti := v1alpha1.MultitenantPodNetworkConfig{ - Status: v1alpha1.MultitenantPodNetworkConfigStatus{ - InterfaceInfos: []v1alpha1.InterfaceInfo{testInterfaceInfos1, testInterfaceInfos3, testInterfaceInfos5}, - }, - } - return &Client{ - mtPodCache: map[string]*v1.Pod{ - "testpod1namespace/testpod1": &testPod1, - "testpod3namespace/testpod3": &testPod3, - "testpod4namespace/testpod4": &testPod4, - "testpod5namespace/testpod5": &testPod5, - "testpod6namespace/testpod6": &testPod6, - "testpod7namespace/testpod7": &testPod7, - }, + mtPodCache: map[string]*v1.Pod{"testpod1namespace/testpod1": &testPod1, "testpod3namespace/testpod3": &testPod3, "testpod4namespace/testpod4": &testPod4}, mtpncCache: map[string]*v1alpha1.MultitenantPodNetworkConfig{ "testpod1namespace/testpod1": &testMTPNC1, "testpod2namespace/testpod2": &testMTPNC2, "testpod4namespace/testpod4": &testMTPNC4, - "testpod5namespace/testpod5": &testMTPNC3, - "testpod6namespace/testpod6": &testMTPNC5, - "testpod7namespace/testpod7": &testMTPNCMulti, }, } } @@ -147,18 +85,11 @@ func (c *Client) Get(_ context.Context, key client.ObjectKey, obj client.Object, } func (c *Client) SetMTPNCReady() { - testInterfaceInfos1 := v1alpha1.InterfaceInfo{ - NCID: "testncid", - PrimaryIP: "192.168.0.1/32", - MacAddress: "00:00:00:00:00:00", - GatewayIP: "10.0.0.1", - DeviceType: v1alpha1.DeviceTypeVnetNIC, - AccelnetEnabled: false, - } - testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{} - testMTPNC1.Status.InterfaceInfos = []v1alpha1.InterfaceInfo{testInterfaceInfos1} - + testMTPNC1.Status.PrimaryIP = "192.168.0.1/32" + testMTPNC1.Status.MacAddress = "00:00:00:00:00:00" + testMTPNC1.Status.GatewayIP = "10.0.0.1" + testMTPNC1.Status.NCID = "testncid" c.mtpncCache["testpod1namespace/testpod1"] = &testMTPNC1 } diff --git a/cns/middlewares/utils/utils.go b/cns/middlewares/utils/utils.go index 687e96a86a7..2eca8551ea3 100644 --- a/cns/middlewares/utils/utils.go +++ b/cns/middlewares/utils/utils.go @@ -1,20 +1,19 @@ package utils import ( + "fmt" "net/netip" "strings" - - "github.com/pkg/errors" ) -// ParseCIDRs parses the comma-separated list of CIDRs and returns the IPv4 and IPv6 CIDRs. +// ParseCIDRs parses the comma separated list of CIDRs and returns the IPv4 and IPv6 CIDRs. func ParseCIDRs(cidrs string) (v4IPs, v6IPs []string, err error) { v4IPs = []string{} v6IPs = []string{} for _, cidr := range strings.Split(cidrs, ",") { p, err := netip.ParsePrefix(cidr) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to parse CIDR %s", cidr) + return nil, nil, fmt.Errorf("failed to parse CIDR %s : %w", cidr, err) } ip := p.Addr() if ip.Is4() { @@ -25,15 +24,3 @@ func ParseCIDRs(cidrs string) (v4IPs, v6IPs []string, err error) { } return v4IPs, v6IPs, nil } - -// ParseIPAndPrefix parses the primaryIP and returns the IP address and prefix length. -func ParseIPAndPrefix(primaryIP string) (ip string, prefixSize int, err error) { - p, err := netip.ParsePrefix(primaryIP) - if err != nil { - err = errors.Wrapf(err, "failed to parse IP %s", primaryIP) - return "", 0, err - } - ip = p.Addr().String() - prefixSize = p.Bits() - return ip, prefixSize, nil -} diff --git a/crd/multitenancy/api/v1alpha1/utils.go b/crd/multitenancy/api/v1alpha1/utils.go deleted file mode 100644 index 28e3a511631..00000000000 --- a/crd/multitenancy/api/v1alpha1/utils.go +++ /dev/null @@ -1,28 +0,0 @@ -package v1alpha1 - -// IsReady checks if all the required fields in the MTPNC status are populated -func (m *MultitenantPodNetworkConfig) IsReady() bool { - // Check if InterfaceInfos slice is not empty - if len(m.Status.InterfaceInfos) == 0 { - // Check if the higher fields in the status are populated - if m.Status.PrimaryIP == "" || - m.Status.MacAddress == "" || - m.Status.NCID == "" || - m.Status.GatewayIP == "" { - return false - } - } else { - // Check if each InterfaceInfo has all required fields populated - for _, interfaceInfo := range m.Status.InterfaceInfos { - if interfaceInfo.NCID == "" || - interfaceInfo.PrimaryIP == "" || - interfaceInfo.MacAddress == "" || - interfaceInfo.GatewayIP == "" || - interfaceInfo.DeviceType == "" { - return false - } - } - } - - return true -}