diff --git a/cns/middlewares/k8sSwiftV2.go b/cns/middlewares/k8sSwiftV2.go index 63d12fcb0c..d58bc5db3b 100644 --- a/cns/middlewares/k8sSwiftV2.go +++ b/cns/middlewares/k8sSwiftV2.go @@ -221,7 +221,8 @@ func (k *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodI if prefixSize != prefixLength { return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize) } - podIPInfos = append(podIPInfos, cns.PodIpInfo{ + + podIPInfo := cns.PodIpInfo{ PodIPConfig: cns.IPSubnet{ IPAddress: ip, PrefixLength: uint8(prefixSize), @@ -230,9 +231,15 @@ func (k *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodI NICType: cns.DelegatedVMNIC, SkipDefaultRoutes: false, // InterfaceName is empty for DelegatedVMNIC - }) + } + // for windows scenario, it is required to add additional fields with the exact subnetAddressSpace + // received from MTPNC, this function assigns them for windows while linux is a no-op + err = k.assignSubnetPrefixLengthFields(&podIPInfo, interfaceInfo, ip) + if err != nil { + return nil, errors.Wrap(err, "failed to parse mtpnc subnetAddressSpace prefix") + } + podIPInfos = append(podIPInfos, podIPInfo) } - } } diff --git a/cns/middlewares/k8sSwiftV2_linux.go b/cns/middlewares/k8sSwiftV2_linux.go index 30b3db7700..680242c4aa 100644 --- a/cns/middlewares/k8sSwiftV2_linux.go +++ b/cns/middlewares/k8sSwiftV2_linux.go @@ -8,6 +8,7 @@ import ( "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" ) @@ -95,3 +96,8 @@ func addRoutes(cidrs []string, gatewayIP string) []cns.Route { } return routes } + +// assignSubnetPrefixLengthFields is a no-op for linux swiftv2 as the default prefix-length is sufficient +func (k *K8sSWIFTv2Middleware) assignSubnetPrefixLengthFields(_ *cns.PodIpInfo, _ v1alpha1.InterfaceInfo, _ string) error { + return nil +} diff --git a/cns/middlewares/k8sSwiftV2_linux_test.go b/cns/middlewares/k8sSwiftV2_linux_test.go index d74324512d..cf55f4cce9 100644 --- a/cns/middlewares/k8sSwiftV2_linux_test.go +++ b/cns/middlewares/k8sSwiftV2_linux_test.go @@ -10,6 +10,7 @@ import ( "github.com/Azure/azure-container-networking/cns/logger" "github.com/Azure/azure-container-networking/cns/middlewares/mock" "github.com/Azure/azure-container-networking/cns/types" + "github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" "gotest.tools/v3/assert" ) @@ -455,3 +456,29 @@ func TestGetSWIFTv2IPConfigMultiInterfaceSuccess(t *testing.T) { assert.Equal(t, ipInfo.SkipDefaultRoutes, false) } } + +func TestAssignSubnetPrefixSuccess(t *testing.T) { + middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} + + podIPInfo := cns.PodIpInfo{ + PodIPConfig: cns.IPSubnet{ + IPAddress: "20.240.1.242", + PrefixLength: 32, + }, + NICType: cns.DelegatedVMNIC, + MacAddress: "12:34:56:78:9a:bc", + } + + intInfo := v1alpha1.InterfaceInfo{ + GatewayIP: "20.240.1.1", + SubnetAddressSpace: "20.240.1.0/16", + } + + ipInfo := podIPInfo + err := middleware.assignSubnetPrefixLengthFields(&ipInfo, intInfo, ipInfo.PodIPConfig.IPAddress) + assert.Equal(t, err, nil) + // assert that the function for linux does not modify any fields + assert.Equal(t, ipInfo.PodIPConfig.PrefixLength, uint8(32)) + assert.Equal(t, ipInfo.HostPrimaryIPInfo.Gateway, "") + assert.Equal(t, ipInfo.HostPrimaryIPInfo.Subnet, "") +} diff --git a/cns/middlewares/k8sSwiftV2_windows.go b/cns/middlewares/k8sSwiftV2_windows.go index d20d28bec9..a2b34cd467 100644 --- a/cns/middlewares/k8sSwiftV2_windows.go +++ b/cns/middlewares/k8sSwiftV2_windows.go @@ -3,6 +3,9 @@ package middlewares import ( "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" ) // for AKS L1VH, do not set default route on infraNIC to avoid customer pod reaching all infra vnet services @@ -14,3 +17,28 @@ func (k *K8sSWIFTv2Middleware) setRoutes(podIPInfo *cns.PodIpInfo) error { } return nil } + +// assignSubnetPrefixLengthFields will assign the subnet-prefix length to some fields of podipinfo +// this is required for the windows scenario so that HNS programming is successful for pods +func (k *K8sSWIFTv2Middleware) assignSubnetPrefixLengthFields(podIPInfo *cns.PodIpInfo, interfaceInfo v1alpha1.InterfaceInfo, ip string) error { + // Parse MTPNC SubnetAddressSpace to get the subnet prefix length + subnet, subnetPrefix, err := utils.ParseIPAndPrefix(interfaceInfo.SubnetAddressSpace) + if err != nil { + return errors.Wrap(err, "failed to parse mtpnc subnetAddressSpace prefix") + } + // assign the subnet-prefix length to all fields in podipinfo + podIPInfo.PodIPConfig.PrefixLength = uint8(subnetPrefix) + podIPInfo.HostPrimaryIPInfo = cns.HostIPInfo{ + Gateway: interfaceInfo.GatewayIP, + PrimaryIP: ip, + Subnet: interfaceInfo.SubnetAddressSpace, + } + podIPInfo.NetworkContainerPrimaryIPConfig = cns.IPConfiguration{ + IPSubnet: cns.IPSubnet{ + IPAddress: subnet, + PrefixLength: uint8(subnetPrefix), + }, + GatewayIPAddress: interfaceInfo.GatewayIP, + } + return nil +} diff --git a/cns/middlewares/k8sSwiftV2_windows_test.go b/cns/middlewares/k8sSwiftV2_windows_test.go index b0d95bebd7..945d650ae9 100644 --- a/cns/middlewares/k8sSwiftV2_windows_test.go +++ b/cns/middlewares/k8sSwiftV2_windows_test.go @@ -5,6 +5,7 @@ import ( "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/cns/middlewares/mock" + "github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" "gotest.tools/v3/assert" ) @@ -39,3 +40,29 @@ func TestSetRoutesSuccess(t *testing.T) { } } } + +func TestAssignSubnetPrefixSuccess(t *testing.T) { + middleware := K8sSWIFTv2Middleware{Cli: mock.NewClient()} + + podIPInfo := cns.PodIpInfo{ + PodIPConfig: cns.IPSubnet{ + IPAddress: "20.240.1.242", + PrefixLength: 32, + }, + NICType: cns.DelegatedVMNIC, + MacAddress: "12:34:56:78:9a:bc", + } + + intInfo := v1alpha1.InterfaceInfo{ + GatewayIP: "20.240.1.1", + SubnetAddressSpace: "20.240.1.0/16", + } + + ipInfo := podIPInfo + err := middleware.assignSubnetPrefixLengthFields(&ipInfo, intInfo, ipInfo.PodIPConfig.IPAddress) + assert.Equal(t, err, nil) + // assert that the function for windows modifies all the expected fields with prefix-length + assert.Equal(t, ipInfo.PodIPConfig.PrefixLength, uint8(16)) + assert.Equal(t, ipInfo.HostPrimaryIPInfo.Gateway, intInfo.GatewayIP) + assert.Equal(t, ipInfo.HostPrimaryIPInfo.Subnet, intInfo.SubnetAddressSpace) +} diff --git a/cns/middlewares/mock/mockClient.go b/cns/middlewares/mock/mockClient.go index 229092c3dc..843f03111a 100644 --- a/cns/middlewares/mock/mockClient.go +++ b/cns/middlewares/mock/mockClient.go @@ -73,6 +73,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", @@ -81,6 +82,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", @@ -89,6 +91,7 @@ func NewClient() *Client { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeInfiniBandNIC, AccelnetEnabled: true, + SubnetAddressSpace: "192.168.0.0/24", } testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{ @@ -216,6 +219,7 @@ func (c *Client) SetMTPNCReady() { GatewayIP: "10.0.0.1", DeviceType: v1alpha1.DeviceTypeVnetNIC, AccelnetEnabled: false, + SubnetAddressSpace: "192.168.0.0/24", } testMTPNC1 := v1alpha1.MultitenantPodNetworkConfig{}