From a164ec8717804c71f1f11a44f33fb6c26d6e3724 Mon Sep 17 00:00:00 2001 From: Kshitija Murudi Date: Wed, 3 Jul 2024 19:03:44 -0700 Subject: [PATCH] separate getIpConfig based on OS for HNS prefix changes, add subnet in UTs --- cns/middlewares/k8sSwiftV2.go | 96 ------------------------- cns/middlewares/k8sSwiftV2_linux.go | 85 +++++++++++++++++++++- cns/middlewares/k8sSwiftV2_windows.go | 100 ++++++++++++++++++++++++++ cns/middlewares/mock/mockClient.go | 4 ++ 4 files changed, 187 insertions(+), 98 deletions(-) diff --git a/cns/middlewares/k8sSwiftV2.go b/cns/middlewares/k8sSwiftV2.go index e9511736f7d..1b8d634779b 100644 --- a/cns/middlewares/k8sSwiftV2.go +++ b/cns/middlewares/k8sSwiftV2.go @@ -7,8 +7,6 @@ import ( "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/Azure/azure-container-networking/cns/types" "github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" @@ -132,97 +130,3 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req // retrieve podinfo from orchestrator context return podInfo, types.Success, "" } - -// getIPConfig returns the pod's SWIFT V2 IP configuration. -func (k *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") - } - - // Check if the MTPNC CRD is ready. If one of the fields is empty, return error - if !mtpnc.IsReady() { - return nil, errMTPNCNotReady - } - logger.Printf("[SWIFTv2Middleware] mtpnc for pod %s is : %+v", podInfo.Name(), mtpnc) - - var podIPInfos []cns.PodIpInfo - - if len(mtpnc.Status.InterfaceInfos) == 0 { - // Use fields from mtpnc.Status if InterfaceInfos is empty - ip, prefixSize, err := utils.ParseIPAndPrefix(mtpnc.Status.PrimaryIP) - 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") - } - if prefixSize != prefixLength { - return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) - } - // Parse MTPNC SubnetAddressSpace to get the subnet prefix length - subnet, subnetPrefix, err := utils.ParseIPAndPrefix(interfaceInfo.PrimaryIP) - if err != nil { - return nil, errors.Wrap(err, "failed to parse mtpnc subnetAddressSpace prefix") - } - - 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 - } - - podIPInfos[i] = cns.PodIpInfo{ - PodIPConfig: cns.IPSubnet{ - IPAddress: ip, - PrefixLength: uint8(prefixSize), - }, - MacAddress: interfaceInfo.MacAddress, - NICType: nicType, - SkipDefaultRoutes: false, - HostPrimaryIPInfo: cns.HostIPInfo{ - Gateway: interfaceInfo.GatewayIP, - PrimaryIP: ip, - Subnet: interfaceInfo.SubnetAddressSpace, - }, - NetworkContainerPrimaryIPConfig: cns.IPConfiguration{ - IPSubnet: cns.IPSubnet{ - IPAddress: subnet, - PrefixLength: uint8(subnetPrefix), - }, - GatewayIPAddress: interfaceInfo.GatewayIP, - }, - } - } - } - - return podIPInfos, nil -} diff --git a/cns/middlewares/k8sSwiftV2_linux.go b/cns/middlewares/k8sSwiftV2_linux.go index 30b3db7700f..01cabd0b677 100644 --- a/cns/middlewares/k8sSwiftV2_linux.go +++ b/cns/middlewares/k8sSwiftV2_linux.go @@ -1,16 +1,97 @@ package middlewares import ( - "fmt" - "net/netip" + "context" "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/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" "github.com/pkg/errors" + k8stypes "k8s.io/apimachinery/pkg/types" ) +// getIPConfig returns the pod's SWIFT V2 IP configuration. +func (k *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") + } + + // Check if the MTPNC CRD is ready. If one of the fields is empty, return error + if !mtpnc.IsReady() { + return nil, errMTPNCNotReady + } + logger.Printf("[SWIFTv2Middleware] mtpnc for pod %s is : %+v", podInfo.Name(), mtpnc) + + var podIPInfos []cns.PodIpInfo + + if len(mtpnc.Status.InterfaceInfos) == 0 { + // Use fields from mtpnc.Status if InterfaceInfos is empty + ip, prefixSize, err := utils.ParseIPAndPrefix(mtpnc.Status.PrimaryIP) + 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") + } + if prefixSize != prefixLength { + return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) + } + + 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 + } + + podIPInfos[i] = cns.PodIpInfo{ + PodIPConfig: cns.IPSubnet{ + IPAddress: ip, + PrefixLength: uint8(prefixSize), + }, + MacAddress: interfaceInfo.MacAddress, + NICType: nicType, + SkipDefaultRoutes: false, + HostPrimaryIPInfo: cns.HostIPInfo{ + Gateway: interfaceInfo.GatewayIP, + }, + } + } + } + + return podIPInfos, nil +} + // 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) diff --git a/cns/middlewares/k8sSwiftV2_windows.go b/cns/middlewares/k8sSwiftV2_windows.go index d20d28bec9a..79f68ac1502 100644 --- a/cns/middlewares/k8sSwiftV2_windows.go +++ b/cns/middlewares/k8sSwiftV2_windows.go @@ -1,10 +1,110 @@ package middlewares import ( + "context" + "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/cns/logger" + "github.com/Azure/azure-container-networking/cns/middlewares/utils" + "github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" + "github.com/pkg/errors" + k8stypes "k8s.io/apimachinery/pkg/types" ) +// getIPConfig returns the pod's SWIFT V2 IP configuration. +func (k *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") + } + + // Check if the MTPNC CRD is ready. If one of the fields is empty, return error + if !mtpnc.IsReady() { + return nil, errMTPNCNotReady + } + logger.Printf("[SWIFTv2Middleware] mtpnc for pod %s is : %+v", podInfo.Name(), mtpnc) + + var podIPInfos []cns.PodIpInfo + + if len(mtpnc.Status.InterfaceInfos) == 0 { + // Use fields from mtpnc.Status if InterfaceInfos is empty + ip, prefixSize, err := utils.ParseIPAndPrefix(mtpnc.Status.PrimaryIP) + 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") + } + if prefixSize != prefixLength { + return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) + } + // Parse MTPNC SubnetAddressSpace to get the subnet prefix length + subnet, subnetPrefix, err := utils.ParseIPAndPrefix(interfaceInfo.PrimaryIP) + if err != nil { + return nil, errors.Wrap(err, "failed to parse mtpnc subnetAddressSpace prefix") + } + + 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 + } + + podIPInfos[i] = cns.PodIpInfo{ + PodIPConfig: cns.IPSubnet{ + IPAddress: ip, + PrefixLength: uint8(subnetPrefix), + }, + MacAddress: interfaceInfo.MacAddress, + NICType: nicType, + SkipDefaultRoutes: false, + HostPrimaryIPInfo: cns.HostIPInfo{ + Gateway: interfaceInfo.GatewayIP, + PrimaryIP: ip, + Subnet: interfaceInfo.SubnetAddressSpace, + }, + NetworkContainerPrimaryIPConfig: cns.IPConfiguration{ + IPSubnet: cns.IPSubnet{ + IPAddress: subnet, + PrefixLength: uint8(subnetPrefix), + }, + GatewayIPAddress: interfaceInfo.GatewayIP, + }, + } + } + } + + return podIPInfos, nil +} + // for AKS L1VH, do not set default route on infraNIC to avoid customer pod reaching all infra vnet services // default route is set for secondary interface NIC(i.e,delegatedNIC) func (k *K8sSWIFTv2Middleware) setRoutes(podIPInfo *cns.PodIpInfo) error { diff --git a/cns/middlewares/mock/mockClient.go b/cns/middlewares/mock/mockClient.go index 4c2b1adfa93..56dbdbadb48 100644 --- a/cns/middlewares/mock/mockClient.go +++ b/cns/middlewares/mock/mockClient.go @@ -61,6 +61,7 @@ func NewClient() *Client { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeVnetNIC, AccelnetEnabled: false, + SubnetAddressSpace: "192.168.0.0/24", } testInterfaceInfos3 := v1alpha1.InterfaceInfo{ NCID: "testncid", @@ -69,6 +70,7 @@ func NewClient() *Client { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeVnetNIC, AccelnetEnabled: false, + SubnetAddressSpace: "192.168.0.0/24", } testInterfaceInfos5 := v1alpha1.InterfaceInfo{ NCID: "testncid", @@ -77,6 +79,7 @@ func NewClient() *Client { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeInfiniBandNIC, AccelnetEnabled: true, + SubnetAddressSpace: "192.168.0.0/24", } testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{ @@ -154,6 +157,7 @@ func (c *Client) SetMTPNCReady() { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeVnetNIC, AccelnetEnabled: false, + SubnetAddressSpace: "192.168.0.0/24", } testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{}