Skip to content

Commit

Permalink
separate getIpConfig based on OS for HNS prefix changes, add subnet i…
Browse files Browse the repository at this point in the history
…n UTs
  • Loading branch information
kmurudi committed Jul 4, 2024
1 parent 70e9f8c commit a164ec8
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 98 deletions.
96 changes: 0 additions & 96 deletions cns/middlewares/k8sSwiftV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
85 changes: 83 additions & 2 deletions cns/middlewares/k8sSwiftV2_linux.go
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
100 changes: 100 additions & 0 deletions cns/middlewares/k8sSwiftV2_windows.go
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions cns/middlewares/mock/mockClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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{
Expand Down Expand Up @@ -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{}
Expand Down

0 comments on commit a164ec8

Please sign in to comment.