99
1010 "github.com/vishvananda/netlink"
1111
12+ corev1 "k8s.io/api/core/v1"
13+ "k8s.io/apimachinery/pkg/util/sets"
1214 "k8s.io/klog/v2"
1315 utilnet "k8s.io/utils/net"
1416
@@ -195,7 +197,6 @@ func (nc *DefaultNodeNetworkController) initGatewayPreStart(
195197 subnets []* net.IPNet ,
196198 nodeAnnotator kube.Annotator ,
197199 mgmtPort managementport.Interface ,
198- kubeNodeIP net.IP ,
199200) (* gateway , error ) {
200201
201202 klog .Info ("Initializing Gateway Functionality for Gateway PreStart" )
@@ -219,13 +220,39 @@ func (nc *DefaultNodeNetworkController) initGatewayPreStart(
219220 return nil , err
220221 }
221222
222- // For DPU need to use the host IP addr which currently is assumed to be K8s Node cluster
223- // internal IP address .
223+ // For DPU mode, we need to use the host IP address which is stored as a Kubernetes
224+ // node annotation rather than using the gateway interface IP addresses .
224225 if config .OvnKubeNode .Mode == types .NodeModeDPU {
225- ifAddrs , err = nodeutil .GetDPUHostPrimaryIPAddresses (kubeNodeIP , ifAddrs )
226+ // Retrieve the current node object from the Kubernetes API
227+ var node * corev1.Node
228+ if node , err = nc .watchFactory .GetNode (nc .name ); err != nil {
229+ return nil , fmt .Errorf ("error retrieving node %s: %v" , nc .name , err )
230+ }
231+
232+ // Extract the primary DPU address annotation from the node
233+ nodeIfAddr , err := util .GetNodePrimaryDPUHostAddrAnnotation (node )
226234 if err != nil {
227235 return nil , err
228236 }
237+ // For DPU mode, we only support IPv4 for now.
238+ nodeAddrStr := nodeIfAddr .IPv4
239+ if nodeAddrStr == "" {
240+ return nil , fmt .Errorf ("node primary DPU address annotation is empty for node %s" , nc .name )
241+ }
242+
243+ // Parse the IPv4 address string into IP and network components
244+ nodeIP , nodeAddrs , err := net .ParseCIDR (nodeAddrStr )
245+ if err != nil {
246+ return nil , fmt .Errorf ("failed to parse node IP address %s: %v" , nodeAddrStr , err )
247+ }
248+
249+ // Set the parsed IP as the network address
250+ nodeAddrs .IP = nodeIP
251+
252+ // Create a new slice and replace ifAddrs with the DPU host address
253+ // This overrides the gateway interface addresses for DPU mode
254+ var gwIps []* net.IPNet
255+ ifAddrs = append (gwIps , nodeAddrs )
229256 }
230257
231258 if err := util .SetNodePrimaryIfAddrs (nodeAnnotator , ifAddrs ); err != nil {
@@ -359,43 +386,79 @@ func interfaceForEXGW(intfName string) string {
359386 return intfName
360387}
361388
362- func (nc * DefaultNodeNetworkController ) initGatewayDPUHost (kubeNodeIP net.IP ) error {
389+ func (nc * DefaultNodeNetworkController ) initGatewayDPUHost (kubeNodeIP net.IP , nodeAnnotator kube. Annotator ) error {
363390 // A DPU host gateway is complementary to the shared gateway running
364391 // on the DPU embedded CPU. it performs some initializations and
365392 // watch on services for iptable rule updates and run a loadBalancerHealth checker
366393 // Note: all K8s Node related annotations are handled from DPU.
367394 klog .Info ("Initializing Shared Gateway Functionality on DPU host" )
368395 var err error
369396
370- // Force gateway interface to be the interface associated with kubeNodeIP
371- gwIntf , err := getInterfaceByIP (kubeNodeIP )
397+ // Find the network interface that has the Kubernetes node IP assigned to it
398+ // This interface will be used for DPU host gateway operations
399+ kubeIntf , err := getInterfaceByIP (kubeNodeIP )
372400 if err != nil {
373401 return err
374402 }
375- config .Gateway .Interface = gwIntf
376403
377- _ , gatewayIntf , err := getGatewayNextHops ()
404+ // Get all IP addresses (IPv4 and IPv6) configured on the detected interface
405+ ifAddrs , err := nodeutil .GetNetworkInterfaceIPAddresses (kubeIntf )
378406 if err != nil {
379407 return err
380408 }
381409
382- ifAddrs , err := nodeutil .GetNetworkInterfaceIPAddresses (gatewayIntf )
383- if err != nil {
410+ // Extract the IPv4 address from the interface addresses for node annotation
411+ nodeIPNet , _ := util .MatchFirstIPNetFamily (false , ifAddrs )
412+ nodeAddrSet := sets.New [string ](nodeIPNet .String ())
413+
414+ // If no gateway interface is explicitly configured, use the detected interface
415+ if config .Gateway .Interface == "" {
416+ config .Gateway .Interface = kubeIntf
417+ }
418+
419+ // If a different gateway interface is configured than the one with used for the kubernetes node IP,
420+ // get its addresses and add them to the node address set for routing purposes
421+ if config .Gateway .Interface != kubeIntf {
422+ ifAddrs , err = nodeutil .GetNetworkInterfaceIPAddresses (config .Gateway .Interface )
423+ if err != nil {
424+ return err
425+ }
426+ detectedIPNetv4 , _ := util .MatchFirstIPNetFamily (false , ifAddrs )
427+ nodeAddrSet .Insert (detectedIPNetv4 .String ())
428+ // Use the configured interface for the masquerade route instead of the auto-detected one
429+ kubeIntf = config .Gateway .Interface
430+ }
431+
432+ // Set the primary DPU address annotation on the node with the interface addresses
433+ if err := util .SetNodePrimaryDPUHostAddr (nodeAnnotator , ifAddrs ); err != nil {
434+ klog .Errorf ("Unable to set primary IP net label on node, err: %v" , err )
435+ return err
436+ }
437+
438+ // Set the host CIDRs annotation to include all detected network addresses
439+ // This helps with routing decisions for traffic coming from the host
440+ if err := util .SetNodeHostCIDRs (nodeAnnotator , nodeAddrSet ); err != nil {
441+ klog .Errorf ("Unable to set host-cidrs on node, err: %v" , err )
384442 return err
385443 }
386444
445+ // Apply all node annotations to the Kubernetes node object
446+ if err := nodeAnnotator .Run (); err != nil {
447+ return fmt .Errorf ("failed to set node %s annotations: %w" , nc .name , err )
448+ }
449+
387450 // Delete stale masquerade resources if there are any. This is to make sure that there
388451 // are no Linux resources with IP from old masquerade subnet when masquerade subnet
389452 // gets changed as part of day2 operation.
390- if err := deleteStaleMasqueradeResources (gwIntf , nc .name , nc .watchFactory ); err != nil {
453+ if err := deleteStaleMasqueradeResources (kubeIntf , nc .name , nc .watchFactory ); err != nil {
391454 return fmt .Errorf ("failed to remove stale masquerade resources: %w" , err )
392455 }
393456
394- if err := setNodeMasqueradeIPOnExtBridge (gwIntf ); err != nil {
395- return fmt .Errorf ("failed to set the node masquerade IP on the ext bridge %s: %v" , gwIntf , err )
457+ if err := setNodeMasqueradeIPOnExtBridge (kubeIntf ); err != nil {
458+ return fmt .Errorf ("failed to set the node masquerade IP on the ext bridge %s: %v" , kubeIntf , err )
396459 }
397460
398- if err := addMasqueradeRoute (nc .routeManager , gwIntf , nc .name , ifAddrs , nc .watchFactory ); err != nil {
461+ if err := addMasqueradeRoute (nc .routeManager , kubeIntf , nc .name , ifAddrs , nc .watchFactory ); err != nil {
399462 return fmt .Errorf ("failed to set the node masquerade route to OVN: %v" , err )
400463 }
401464
@@ -404,7 +467,7 @@ func (nc *DefaultNodeNetworkController) initGatewayDPUHost(kubeNodeIP net.IP) er
404467 return fmt .Errorf ("failed to update masquerade subnet annotation on node: %s, error: %v" , nc .name , err )
405468 }
406469
407- err = configureSvcRouteViaInterface (nc .routeManager , gatewayIntf , DummyNextHopIPs ())
470+ err = configureSvcRouteViaInterface (nc .routeManager , config . Gateway . Interface , DummyNextHopIPs ())
408471 if err != nil {
409472 return err
410473 }
@@ -430,7 +493,7 @@ func (nc *DefaultNodeNetworkController) initGatewayDPUHost(kubeNodeIP net.IP) er
430493 gw .portClaimWatcher = portClaimWatcher
431494 }
432495
433- if err := addHostMACBindings (gwIntf ); err != nil {
496+ if err := addHostMACBindings (kubeIntf ); err != nil {
434497 return fmt .Errorf ("failed to add MAC bindings for service routing" )
435498 }
436499
0 commit comments