Skip to content

Commit 13f7037

Browse files
authored
feat: Added NIC type and modified setRoutes function to support Windows (#2679)
* Added NIC type and modified setRoutes function to support Windows * Removed deprecated nic types
1 parent 7e8b45f commit 13f7037

File tree

10 files changed

+406
-164
lines changed

10 files changed

+406
-164
lines changed

cni/network/invoker_cns.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
167167
key := invoker.getInterfaceInfoKey(info.nicType, info.macAddress)
168168
switch info.nicType {
169169
case cns.DelegatedVMNIC:
170-
// only handling single v4 PodIPInfo for DelegatedVMNICs at the moment, will have to update once v6 gets added
170+
// only handling single v4 PodIPInfo for Frontend NICs at the moment, will have to update once v6 gets added
171171
if !info.skipDefaultRoutes {
172172
numInterfacesWithDefaultRoutes++
173173
}

cni/network/invoker_cns_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,7 @@ func Test_getInterfaceInfoKey(t *testing.T) {
14441444
require.Equal(string(cns.InfraNIC), inv.getInterfaceInfoKey(cns.InfraNIC, dummyMAC))
14451445
require.Equal(dummyMAC, inv.getInterfaceInfoKey(cns.DelegatedVMNIC, dummyMAC))
14461446
require.Equal("", inv.getInterfaceInfoKey(cns.DelegatedVMNIC, ""))
1447-
require.Equal(string(cns.BackendNIC), inv.getInterfaceInfoKey(cns.BackendNIC, dummyMAC))
1447+
require.Equal(string(cns.NodeNetworkInterfaceBackendNIC), inv.getInterfaceInfoKey(cns.NodeNetworkInterfaceBackendNIC, dummyMAC))
14481448
}
14491449

14501450
func TestCNSIPAMInvoker_Add_SwiftV2(t *testing.T) {

cns/NetworkContainerContract.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,18 @@ type NICType string
7878
// NIC Types
7979
const (
8080
InfraNIC NICType = "InfraNIC"
81-
// Delegated VM NICs are projected from VM to container network namespace
82-
DelegatedVMNIC NICType = "DelegatedVMNIC"
83-
// BackendNIC NICs are used for infiniband nics on a VM
81+
// DelegatedVMNIC are projected from VM to container network namespace
82+
DelegatedVMNIC NICType = "FrontendNIC"
83+
// BackendNIC are used for infiniband NICs on a VM
8484
BackendNIC NICType = "BackendNIC"
85+
// NodeNetworkInterfaceAccelnetFrontendNIC is a type of front-end nic that offers accelerated networking performance
86+
NodeNetworkInterfaceAccelnetFrontendNIC NICType = "FrontendNIC_Accelnet"
87+
88+
// 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
89+
// NodeNetworkInterfaceFrontendNIC is the new name for DelegatedVMNIC
90+
NodeNetworkInterfaceFrontendNIC NICType = "FrontendNIC"
91+
// NodeNetworkInterfaceBackendNIC is the new name for BackendNIC
92+
NodeNetworkInterfaceBackendNIC NICType = "BackendNIC"
8593
)
8694

8795
// ChannelMode :- CNS channel modes
@@ -465,9 +473,8 @@ type PodIpInfo struct {
465473
PodIPConfig IPSubnet
466474
NetworkContainerPrimaryIPConfig IPConfiguration
467475
HostPrimaryIPInfo HostIPInfo
468-
// NICType defines whether NIC is InfraNIC or DelegatedVMNIC or BackendNIC
469-
NICType NICType
470-
InterfaceName string
476+
NICType NICType
477+
InterfaceName string
471478
// MacAddress of interface
472479
MacAddress string
473480
// SkipDefaultRoutes is true if default routes should not be added on interface

cns/middlewares/k8sSwiftV2.go

Lines changed: 67 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package middlewares
33
import (
44
"context"
55
"fmt"
6-
"net/netip"
7-
86
"github.com/Azure/azure-container-networking/cns"
97
"github.com/Azure/azure-container-networking/cns/configuration"
108
"github.com/Azure/azure-container-networking/cns/logger"
@@ -39,17 +37,17 @@ var _ cns.IPConfigsHandlerMiddleware = (*K8sSWIFTv2Middleware)(nil)
3937

4038
// IPConfigsRequestHandlerWrapper is the middleware function for handling SWIFT v2 IP configs requests for AKS-SWIFT. This function wrapped the default SWIFT request
4139
// and release IP configs handlers.
42-
func (m *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
40+
func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
4341
return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) {
44-
podInfo, respCode, message := m.validateIPConfigsRequest(ctx, &req)
42+
podInfo, respCode, message := k.validateIPConfigsRequest(ctx, &req)
4543

4644
if respCode != types.Success {
4745
return &cns.IPConfigsResponse{
4846
Response: cns.Response{
4947
ReturnCode: respCode,
5048
Message: message,
5149
},
52-
}, errors.New("failed to validate ip configs request")
50+
}, errors.New("failed to validate IP configs request")
5351
}
5452
ipConfigsResp, err := defaultHandler(ctx, req)
5553
// If the pod is not v2, return the response from the handler
@@ -69,7 +67,7 @@ func (m *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
6967
if err != nil {
7068
return ipConfigsResp, err
7169
}
72-
SWIFTv2PodIPInfo, err := m.getIPConfig(ctx, podInfo)
70+
SWIFTv2PodIPInfos, err := k.getIPConfig(ctx, podInfo)
7371
if err != nil {
7472
return &cns.IPConfigsResponse{
7573
Response: cns.Response{
@@ -79,11 +77,11 @@ func (m *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
7977
PodIPInfo: []cns.PodIpInfo{},
8078
}, errors.Wrapf(err, "failed to get SWIFTv2 IP config : %v", req)
8179
}
82-
ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfo)
80+
ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfos...)
8381
// Set routes for the pod
8482
for i := range ipConfigsResp.PodIPInfo {
8583
ipInfo := &ipConfigsResp.PodIPInfo[i]
86-
err = m.setRoutes(ipInfo)
84+
err = k.setRoutes(ipInfo)
8785
if err != nil {
8886
return &cns.IPConfigsResponse{
8987
Response: cns.Response{
@@ -100,7 +98,7 @@ func (m *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
10098

10199
// validateIPConfigsRequest validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario.
102100
// nolint
103-
func (m *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
101+
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
104102
// Retrieve the pod from the cluster
105103
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
106104
if err != nil {
@@ -110,7 +108,7 @@ func (m *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
110108
logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name())
111109
podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
112110
pod := v1.Pod{}
113-
if err := m.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
111+
if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
114112
errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName)
115113
return nil, types.UnexpectedError, errBuf.Error()
116114
}
@@ -121,11 +119,11 @@ func (m *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
121119
// Check if the MTPNC CRD exists for the pod, if not, return error
122120
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
123121
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
124-
if err := m.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
122+
if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
125123
return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error()
126124
}
127125
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
128-
if mtpnc.Status.PrimaryIP == "" || mtpnc.Status.MacAddress == "" || mtpnc.Status.NCID == "" || mtpnc.Status.GatewayIP == "" {
126+
if !mtpnc.IsReady() {
129127
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
130128
}
131129
}
@@ -135,150 +133,78 @@ func (m *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
135133
}
136134

137135
// getIPConfig returns the pod's SWIFT V2 IP configuration.
138-
func (m *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodInfo) (cns.PodIpInfo, error) {
136+
func (k *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodInfo) ([]cns.PodIpInfo, error) {
139137
// Check if the MTPNC CRD exists for the pod, if not, return error
140138
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
141139
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
142-
if err := m.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
143-
return cns.PodIpInfo{}, errors.Wrapf(err, "failed to get pod's mtpnc from cache")
140+
if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
141+
return nil, errors.Wrapf(err, "failed to get pod's mtpnc from cache")
144142
}
145143

146144
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
147-
if mtpnc.Status.PrimaryIP == "" || mtpnc.Status.MacAddress == "" || mtpnc.Status.NCID == "" || mtpnc.Status.GatewayIP == "" {
148-
return cns.PodIpInfo{}, errMTPNCNotReady
145+
if !mtpnc.IsReady() {
146+
return nil, errMTPNCNotReady
149147
}
150148
logger.Printf("[SWIFTv2Middleware] mtpnc for pod %s is : %+v", podInfo.Name(), mtpnc)
151149

152-
// Parse MTPNC primaryIP to get the IP address and prefix length
153-
p, err := netip.ParsePrefix(mtpnc.Status.PrimaryIP)
154-
if err != nil {
155-
return cns.PodIpInfo{}, errors.Wrapf(err, "failed to parse mtpnc primaryIP %s", mtpnc.Status.PrimaryIP)
156-
}
157-
// Get the IP address and prefix length
158-
ip := p.Addr()
159-
prefixSize := p.Bits()
160-
if prefixSize != prefixLength {
161-
return cns.PodIpInfo{}, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize)
162-
}
163-
podIPInfo := cns.PodIpInfo{
164-
PodIPConfig: cns.IPSubnet{
165-
IPAddress: ip.String(),
166-
PrefixLength: uint8(prefixSize),
167-
},
168-
MacAddress: mtpnc.Status.MacAddress,
169-
NICType: cns.DelegatedVMNIC,
170-
SkipDefaultRoutes: false,
171-
// InterfaceName is empty for DelegatedVMNIC
172-
}
173-
174-
return podIPInfo, nil
175-
}
176-
177-
// setRoutes sets the routes for podIPInfo used in SWIFT V2 scenario.
178-
func (m *K8sSWIFTv2Middleware) setRoutes(podIPInfo *cns.PodIpInfo) error {
179-
logger.Printf("[SWIFTv2Middleware] set routes for pod with nic type : %s", podIPInfo.NICType)
180-
podIPInfo.Routes = []cns.Route{}
181-
switch podIPInfo.NICType {
182-
case cns.DelegatedVMNIC:
183-
virtualGWRoute := cns.Route{
184-
IPAddress: fmt.Sprintf("%s/%d", virtualGW, prefixLength),
185-
}
186-
// default route via SWIFT v2 interface
187-
route := cns.Route{
188-
IPAddress: "0.0.0.0/0",
189-
GatewayIPAddress: virtualGW,
190-
}
191-
podIPInfo.Routes = []cns.Route{virtualGWRoute, route}
192-
case cns.InfraNIC:
193-
// Get and parse infraVNETCIDRs from env
194-
infraVNETCIDRs, err := configuration.InfraVNETCIDRs()
195-
if err != nil {
196-
return errors.Wrapf(err, "failed to get infraVNETCIDRs from env")
197-
}
198-
infraVNETCIDRsv4, infraVNETCIDRsv6, err := utils.ParseCIDRs(infraVNETCIDRs)
199-
if err != nil {
200-
return errors.Wrapf(err, "failed to parse infraVNETCIDRs")
201-
}
202-
203-
// Get and parse podCIDRs from env
204-
podCIDRs, err := configuration.PodCIDRs()
205-
if err != nil {
206-
return errors.Wrapf(err, "failed to get podCIDRs from env")
207-
}
208-
podCIDRsV4, podCIDRv6, err := utils.ParseCIDRs(podCIDRs)
209-
if err != nil {
210-
return errors.Wrapf(err, "failed to parse podCIDRs")
211-
}
150+
var podIPInfos []cns.PodIpInfo
212151

213-
// Get and parse serviceCIDRs from env
214-
serviceCIDRs, err := configuration.ServiceCIDRs()
152+
if len(mtpnc.Status.InterfaceInfos) == 0 {
153+
// Use fields from mtpnc.Status if InterfaceInfos is empty
154+
ip, prefixSize, err := utils.ParseIPAndPrefix(mtpnc.Status.PrimaryIP)
215155
if err != nil {
216-
return errors.Wrapf(err, "failed to get serviceCIDRs from env")
217-
}
218-
serviceCIDRsV4, serviceCIDRsV6, err := utils.ParseCIDRs(serviceCIDRs)
219-
if err != nil {
220-
return errors.Wrapf(err, "failed to parse serviceCIDRs")
221-
}
222-
// Check if the podIPInfo is IPv4 or IPv6
223-
ip, err := netip.ParseAddr(podIPInfo.PodIPConfig.IPAddress)
224-
if err != nil {
225-
return errors.Wrapf(err, "failed to parse podIPConfig IP address %s", podIPInfo.PodIPConfig.IPAddress)
226-
}
227-
if ip.Is4() {
228-
// routes for IPv4 podCIDR traffic
229-
for _, podCIDRv4 := range podCIDRsV4 {
230-
podCIDRv4Route := cns.Route{
231-
IPAddress: podCIDRv4,
232-
GatewayIPAddress: overlayGatewayv4,
233-
}
234-
podIPInfo.Routes = append(podIPInfo.Routes, podCIDRv4Route)
235-
}
236-
// route for IPv4 serviceCIDR traffic
237-
for _, serviceCIDRv4 := range serviceCIDRsV4 {
238-
serviceCIDRv4Route := cns.Route{
239-
IPAddress: serviceCIDRv4,
240-
GatewayIPAddress: overlayGatewayv4,
241-
}
242-
podIPInfo.Routes = append(podIPInfo.Routes, serviceCIDRv4Route)
243-
}
244-
// route for IPv4 infraVNETCIDR traffic
245-
for _, infraVNETCIDRv4 := range infraVNETCIDRsv4 {
246-
infraVNETCIDRv4Route := cns.Route{
247-
IPAddress: infraVNETCIDRv4,
248-
GatewayIPAddress: overlayGatewayv4,
249-
}
250-
podIPInfo.Routes = append(podIPInfo.Routes, infraVNETCIDRv4Route)
156+
return nil, errors.Wrap(err, "failed to parse mtpnc primary IP and prefix")
157+
}
158+
if prefixSize != prefixLength {
159+
return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize)
160+
}
161+
162+
podIPInfos = append(podIPInfos, cns.PodIpInfo{
163+
PodIPConfig: cns.IPSubnet{
164+
IPAddress: ip,
165+
PrefixLength: uint8(prefixSize),
166+
},
167+
MacAddress: mtpnc.Status.MacAddress,
168+
NICType: cns.DelegatedVMNIC,
169+
SkipDefaultRoutes: false,
170+
// InterfaceName is empty for DelegatedVMNIC
171+
})
172+
} else {
173+
// Use InterfaceInfos if not empty
174+
podIPInfos = make([]cns.PodIpInfo, len(mtpnc.Status.InterfaceInfos))
175+
for i, interfaceInfo := range mtpnc.Status.InterfaceInfos {
176+
// Parse MTPNC primaryIP to get the IP address and prefix length
177+
ip, prefixSize, err := utils.ParseIPAndPrefix(interfaceInfo.PrimaryIP)
178+
if err != nil {
179+
return nil, errors.Wrap(err, "failed to parse mtpnc primary IP and prefix")
251180
}
252-
} else {
253-
// routes for IPv6 podCIDR traffic
254-
for _, podCIDRv6 := range podCIDRv6 {
255-
podCIDRv6Route := cns.Route{
256-
IPAddress: podCIDRv6,
257-
GatewayIPAddress: overlayGatewayV6,
258-
}
259-
podIPInfo.Routes = append(podIPInfo.Routes, podCIDRv6Route)
181+
if prefixSize != prefixLength {
182+
return nil, errors.Wrapf(errInvalidMTPNCPrefixLength, "mtpnc primaryIP prefix length is %d", prefixSize)
260183
}
261-
// route for IPv6 serviceCIDR traffic
262-
for _, serviceCIDRv6 := range serviceCIDRsV6 {
263-
serviceCIDRv6Route := cns.Route{
264-
IPAddress: serviceCIDRv6,
265-
GatewayIPAddress: overlayGatewayV6,
266-
}
267-
podIPInfo.Routes = append(podIPInfo.Routes, serviceCIDRv6Route)
184+
185+
var nicType cns.NICType
186+
switch {
187+
case interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC && !interfaceInfo.AccelnetEnabled:
188+
nicType = cns.DelegatedVMNIC
189+
case interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC && interfaceInfo.AccelnetEnabled:
190+
nicType = cns.NodeNetworkInterfaceAccelnetFrontendNIC
191+
case interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC:
192+
nicType = cns.NodeNetworkInterfaceBackendNIC
193+
default:
194+
nicType = cns.DelegatedVMNIC
268195
}
269-
// route for IPv6 infraVNETCIDR traffic
270-
for _, infraVNETCIDRv6 := range infraVNETCIDRsv6 {
271-
infraVNETCIDRv6Route := cns.Route{
272-
IPAddress: infraVNETCIDRv6,
273-
GatewayIPAddress: overlayGatewayV6,
274-
}
275-
podIPInfo.Routes = append(podIPInfo.Routes, infraVNETCIDRv6Route)
196+
197+
podIPInfos[i] = cns.PodIpInfo{
198+
PodIPConfig: cns.IPSubnet{
199+
IPAddress: ip,
200+
PrefixLength: uint8(prefixSize),
201+
},
202+
MacAddress: interfaceInfo.MacAddress,
203+
NICType: nicType,
204+
SkipDefaultRoutes: false,
276205
}
277206
}
278-
podIPInfo.SkipDefaultRoutes = true
279-
case cns.BackendNIC:
280-
default:
281-
return errInvalidSWIFTv2NICType
282207
}
283-
return nil
208+
209+
return podIPInfos, nil
284210
}

0 commit comments

Comments
 (0)