@@ -89,6 +89,10 @@ type UserDefinedNetworkGateway struct {
8989
9090 // gwInterfaceIndex holds the link index of gateway interface
9191 gwInterfaceIndex int
92+
93+ // save BGP state at the start of reconciliation loop run to handle it consistently throughout the run
94+ isNetworkAdvertisedToDefaultVRF bool
95+ isNetworkAdvertised bool
9296}
9397
9498func NewUserDefinedNetworkGateway (netInfo util.NetInfo , node * corev1.Node , nodeLister listers.NodeLister ,
@@ -225,18 +229,18 @@ func (udng *UserDefinedNetworkGateway) AddNetwork() error {
225229 return fmt .Errorf ("could not add VRF %s routes for network %s, err: %v" , vrfDeviceName , udng .GetNetworkName (), err )
226230 }
227231
228- isNetworkAdvertised := util . IsPodNetworkAdvertisedAtNode ( udng .NetInfo , udng . node . Name )
232+ udng .updateAdvertisementStatus ( )
229233
230234 // create the iprules for this network
231- if err = udng .updateUDNVRFIPRules (isNetworkAdvertised ); err != nil {
235+ if err = udng .updateUDNVRFIPRules (); err != nil {
232236 return fmt .Errorf ("failed to update IP rules for network %s: %w" , udng .GetNetworkName (), err )
233237 }
234238
235- if err = udng .updateAdvertisedUDNIsolationRules (isNetworkAdvertised ); err != nil {
239+ if err = udng .updateAdvertisedUDNIsolationRules (); err != nil {
236240 return fmt .Errorf ("failed to update isolation rules for network %s: %w" , udng .GetNetworkName (), err )
237241 }
238242
239- if err := udng .updateUDNVRFIPRoute (isNetworkAdvertised ); err != nil {
243+ if err := udng .updateUDNVRFIPRoute (); err != nil {
240244 return fmt .Errorf ("failed to update ip routes for network %s: %w" , udng .GetNetworkName (), err )
241245 }
242246
@@ -314,18 +318,16 @@ func (udng *UserDefinedNetworkGateway) DelNetwork() error {
314318 }
315319 }
316320
317- if util .IsPodNetworkAdvertisedAtNode (udng .NetInfo , udng .node .Name ) {
318- err := udng .updateAdvertisedUDNIsolationRules (false )
319- if err != nil {
320- return fmt .Errorf ("failed to remove advertised UDN isolation rules for network %s: %w" , udng .GetNetworkName (), err )
321- }
321+ err := udng .deleteAdvertisedUDNIsolationRules ()
322+ if err != nil {
323+ return fmt .Errorf ("failed to remove advertised UDN isolation rules for network %s: %w" , udng .GetNetworkName (), err )
322324 }
323325
324326 if err := udng .delMarkChain (); err != nil {
325327 return err
326328 }
327329 // delete the management port interface for this network
328- err : = udng .deleteUDNManagementPort ()
330+ err = udng .deleteUDNManagementPort ()
329331 if err != nil {
330332 return err
331333 }
@@ -483,8 +485,7 @@ func (udng *UserDefinedNetworkGateway) computeRoutesForUDN(mpLink netlink.Link)
483485
484486 // Route2: Add default route: default via 172.18.0.1 dev breth0 mtu 1400
485487 // necessary for UDN CNI and host-networked pods default traffic to go to node's gatewayIP
486- isNetworkAdvertised := util .IsPodNetworkAdvertisedAtNode (udng .NetInfo , udng .node .Name )
487- defaultRoute , err := udng .getDefaultRoute (isNetworkAdvertised )
488+ defaultRoute , err := udng .getDefaultRouteExceptIfVRFLite ()
488489 if err != nil {
489490 return nil , fmt .Errorf ("unable to add default route for network %s, err: %v" , udng .GetNetworkName (), err )
490491 }
@@ -585,15 +586,7 @@ func (udng *UserDefinedNetworkGateway) computeRoutesForUDN(mpLink netlink.Link)
585586 return retVal , nil
586587}
587588
588- func (udng * UserDefinedNetworkGateway ) getDefaultRoute (isNetworkAdvertised bool ) ([]netlink.Route , error ) {
589- vrfs := udng .GetPodNetworkAdvertisedOnNodeVRFs (udng .node .Name )
590- // If the network is advertised on a non default VRF then we should only consider routes received from external BGP
591- // device and not send any traffic based on default route similar to one present in default VRF. This is more important
592- // for VRF-Lite usecase where we need traffic to leave from vlan device instead of default gateway interface.
593- if isNetworkAdvertised && ! slices .Contains (vrfs , types .DefaultNetworkName ) {
594- return nil , nil
595- }
596-
589+ func (udng * UserDefinedNetworkGateway ) getDefaultRoute () ([]netlink.Route , error ) {
597590 networkMTU := udng .NetInfo .MTU ()
598591 if networkMTU == 0 {
599592 networkMTU = config .Default .MTU
@@ -618,6 +611,16 @@ func (udng *UserDefinedNetworkGateway) getDefaultRoute(isNetworkAdvertised bool)
618611 return retVal , nil
619612}
620613
614+ func (udng * UserDefinedNetworkGateway ) getDefaultRouteExceptIfVRFLite () ([]netlink.Route , error ) {
615+ // If the network is advertised on a non default VRF then we should only consider routes received from external BGP
616+ // device and not send any traffic based on default route similar to one present in default VRF. This is more important
617+ // for VRF-Lite usecase where we need traffic to leave from vlan device instead of default gateway interface.
618+ if udng .isNetworkAdvertised && ! udng .isNetworkAdvertisedToDefaultVRF {
619+ return nil , nil
620+ }
621+ return udng .getDefaultRoute ()
622+ }
623+
621624// getV4MasqueradeIP returns the V4 management port masqueradeIP for this network
622625func (udng * UserDefinedNetworkGateway ) getV4MasqueradeIP () (* net.IPNet , error ) {
623626 if ! config .IPv4Mode {
@@ -644,21 +647,18 @@ func (udng *UserDefinedNetworkGateway) getV6MasqueradeIP() (*net.IPNet, error) {
644647
645648// constructUDNVRFIPRules constructs rules that redirect matching packets
646649// into the corresponding UDN VRF routing table.
647- // If the network is not advertised, an example of the rules we set for two
648- // networks is:
650+ //
651+ // When a network is not advertised on the default VRF, an example of the rules
652+ // we set for it is:
649653// 2000: from all fwmark 0x1001 lookup 1007
650654// 2000: from all to 169.254.0.12 lookup 1007
651- // 2000: from all fwmark 0x1002 lookup 1009
652- // 2000: from all to 169.254.0.14 lookup 1009
653- // If the network is advertised, an example of the rules we set for two
654- // networks is:
655+ //
656+ // When a network is advertised on the default VRF, an example of the rules
657+ // we set for it is:
655658// 2000: from all fwmark 0x1001 lookup 1007
656659// 2000: from all to 10.132.0.0/14 lookup 1007
657660// 2000: from all to 169.254.0.12 lookup 1007
658- // 2000: from all fwmark 0x1001 lookup 1009
659- // 2000: from all to 10.134.0.0/14 lookup 1009
660- // 2000: from all to 169.254.0.14 lookup 1009
661- func (udng * UserDefinedNetworkGateway ) constructUDNVRFIPRules (isNetworkAdvertised bool ) ([]netlink.Rule , []netlink.Rule , error ) {
661+ func (udng * UserDefinedNetworkGateway ) constructUDNVRFIPRules () ([]netlink.Rule , []netlink.Rule , error ) {
662662 var addIPRules []netlink.Rule
663663 var delIPRules []netlink.Rule
664664 var masqIPRules []netlink.Rule
@@ -691,12 +691,14 @@ func (udng *UserDefinedNetworkGateway) constructUDNVRFIPRules(isNetworkAdvertise
691691 }
692692 }
693693 switch {
694- case ! isNetworkAdvertised :
694+ case udng .isNetworkAdvertisedToDefaultVRF :
695+ // the network is advertised to the default VRF
695696 addIPRules = append (addIPRules , masqIPRules ... )
696- delIPRules = append (delIPRules , subnetIPRules ... )
697- default :
698697 addIPRules = append (addIPRules , subnetIPRules ... )
698+ default :
699+ // network is not advertised on the default VRF
699700 addIPRules = append (addIPRules , masqIPRules ... )
701+ delIPRules = append (delIPRules , subnetIPRules ... )
700702 }
701703 return addIPRules , delIPRules , nil
702704}
@@ -794,19 +796,20 @@ func (udng *UserDefinedNetworkGateway) doReconcile() error {
794796 return fmt .Errorf ("openflow manager with default bridge configuration has not been provided for network %s" , udng .GetNetworkName ())
795797 }
796798
799+ udng .updateAdvertisementStatus ()
800+
797801 // update bridge configuration
798- isNetworkAdvertised := util .IsPodNetworkAdvertisedAtNode (udng .NetInfo , udng .node .Name )
799802 netConfig := udng .openflowManager .defaultBridge .GetNetworkConfig (udng .GetNetworkName ())
800803 if netConfig == nil {
801804 return fmt .Errorf ("missing bridge configuration for network %s" , udng .GetNetworkName ())
802805 }
803- netConfig .Advertised .Store (isNetworkAdvertised )
806+ netConfig .Advertised .Store (udng . isNetworkAdvertised )
804807
805- if err := udng .updateUDNVRFIPRules (isNetworkAdvertised ); err != nil {
808+ if err := udng .updateUDNVRFIPRules (); err != nil {
806809 return fmt .Errorf ("error while updating ip rule for UDN %s: %s" , udng .GetNetworkName (), err )
807810 }
808811
809- if err := udng .updateUDNVRFIPRoute (isNetworkAdvertised ); err != nil {
812+ if err := udng .updateUDNVRFIPRoute (); err != nil {
810813 return fmt .Errorf ("error while updating ip route for UDN %s: %s" , udng .GetNetworkName (), err )
811814 }
812815
@@ -820,16 +823,16 @@ func (udng *UserDefinedNetworkGateway) doReconcile() error {
820823 // let's sync these flows immediately
821824 udng .openflowManager .requestFlowSync ()
822825
823- if err := udng .updateAdvertisedUDNIsolationRules (isNetworkAdvertised ); err != nil {
826+ if err := udng .updateAdvertisedUDNIsolationRules (); err != nil {
824827 return fmt .Errorf ("error while updating advertised UDN isolation rules for network %s: %w" , udng .GetNetworkName (), err )
825828 }
826829 return nil
827830}
828831
829832// updateUDNVRFIPRules updates IP rules for a network depending on whether the
830- // network is advertised or not
831- func (udng * UserDefinedNetworkGateway ) updateUDNVRFIPRules (isNetworkAdvertised bool ) error {
832- addIPRules , deleteIPRules , err := udng .constructUDNVRFIPRules (isNetworkAdvertised )
833+ // network is advertised to the default VRF or not
834+ func (udng * UserDefinedNetworkGateway ) updateUDNVRFIPRules () error {
835+ addIPRules , deleteIPRules , err := udng .constructUDNVRFIPRules ()
833836 if err != nil {
834837 return fmt .Errorf ("unable to get iprules for network %s, err: %v" , udng .GetNetworkName (), err )
835838 }
@@ -848,30 +851,40 @@ func (udng *UserDefinedNetworkGateway) updateUDNVRFIPRules(isNetworkAdvertised b
848851}
849852
850853// Add or remove default route from a vrf device based on the network is
851- // advertised on its own network or default network
852- func (udng * UserDefinedNetworkGateway ) updateUDNVRFIPRoute (isNetworkAdvertised bool ) error {
853- vrfs := udng .GetPodNetworkAdvertisedOnNodeVRFs (udng .node .Name )
854- if isNetworkAdvertised && ! slices .Contains (vrfs , types .DefaultNetworkName ) {
854+ // advertised on its own network or the default network
855+ func (udng * UserDefinedNetworkGateway ) updateUDNVRFIPRoute () error {
856+ vrfName := util .GetNetworkVRFName (udng .NetInfo )
857+
858+ switch {
859+ case udng .isNetworkAdvertised && ! udng .isNetworkAdvertisedToDefaultVRF :
860+ // Remove default route for networks advertised to non-default VRF
855861 if err := udng .removeDefaultRouteFromVRF (); err != nil {
856- return fmt .Errorf ("error while removing default route from VRF %s corresponding to network %s: %s " ,
857- util . GetNetworkVRFName ( udng . NetInfo ) , udng .GetNetworkName (), err )
862+ return fmt .Errorf ("failed to remove default route from VRF %s for network %s: %v " ,
863+ vrfName , udng .GetNetworkName (), err )
858864 }
859- } else if ! isNetworkAdvertised || slices .Contains (vrfs , types .DefaultNetworkName ) {
860- defaultRoute , err := udng .getDefaultRoute (isNetworkAdvertised )
865+
866+ default :
867+ // Add default route for networks that are either:
868+ // - not advertised
869+ // - advertised to default VRF
870+ defaultRoute , err := udng .getDefaultRouteExceptIfVRFLite ()
861871 if err != nil {
862- return fmt .Errorf ("unable to get default route for network %s, err: %v" , udng .GetNetworkName (), err )
872+ return fmt .Errorf ("failed to get default route for network %s: %v" ,
873+ udng .GetNetworkName (), err )
863874 }
864- if err = udng .vrfManager .AddVRFRoutes (util .GetNetworkVRFName (udng .NetInfo ), defaultRoute ); err != nil {
865- return fmt .Errorf ("error while adding default route to VRF %s corresponding to network %s, err: %v" ,
866- util .GetNetworkVRFName (udng .NetInfo ), udng .GetNetworkName (), err )
875+
876+ if err = udng .vrfManager .AddVRFRoutes (vrfName , defaultRoute ); err != nil {
877+ return fmt .Errorf ("failed to add default route to VRF %s for network %s: %v" ,
878+ vrfName , udng .GetNetworkName (), err )
867879 }
868880 }
881+
869882 return nil
870883}
871884
872885func (udng * UserDefinedNetworkGateway ) removeDefaultRouteFromVRF () error {
873886 vrfDeviceName := util .GetNetworkVRFName (udng .NetInfo )
874- defaultRoute , err := udng .getDefaultRoute (false )
887+ defaultRoute , err := udng .getDefaultRoute ()
875888 if err != nil {
876889 return fmt .Errorf ("unable to get default route for network %s, err: %v" , udng .GetNetworkName (), err )
877890 }
@@ -900,39 +913,22 @@ func (udng *UserDefinedNetworkGateway) removeDefaultRouteFromVRF() error {
900913// comment "advertised UDNs V4 subnets"
901914// elements = { 10.10.0.0/16 comment "cluster_udn_l3network" }
902915// }
903- func (udng * UserDefinedNetworkGateway ) updateAdvertisedUDNIsolationRules (isNetworkAdvertised bool ) error {
916+ func (udng * UserDefinedNetworkGateway ) updateAdvertisedUDNIsolationRules () error {
917+ switch {
918+ case udng .isNetworkAdvertised :
919+ return udng .addAdvertisedUDNIsolationRules ()
920+ default :
921+ return udng .deleteAdvertisedUDNIsolationRules ()
922+ }
923+ }
924+
925+ func (udng * UserDefinedNetworkGateway ) addAdvertisedUDNIsolationRules () error {
904926 nft , err := nodenft .GetNFTablesHelper ()
905927 if err != nil {
906928 return fmt .Errorf ("failed to get nftables helper: %v" , err )
907929 }
908930 tx := nft .NewTransaction ()
909931
910- if ! isNetworkAdvertised {
911- existingV4 , err := nft .ListElements (context .TODO (), "set" , nftablesAdvertisedUDNsSetV4 )
912- if err != nil {
913- if ! knftables .IsNotFound (err ) {
914- return fmt .Errorf ("could not list existing items in %s set: %w" , nftablesAdvertisedUDNsSetV4 , err )
915- }
916- }
917- existingV6 , err := nft .ListElements (context .TODO (), "set" , nftablesAdvertisedUDNsSetV6 )
918- if err != nil {
919- if ! knftables .IsNotFound (err ) {
920- return fmt .Errorf ("could not list existing items in %s set: %w" , nftablesAdvertisedUDNsSetV6 , err )
921- }
922- }
923-
924- for _ , elem := range append (existingV4 , existingV6 ... ) {
925- if elem .Comment != nil && * elem .Comment == udng .GetNetworkName () {
926- tx .Delete (elem )
927- }
928- }
929-
930- if tx .NumOperations () == 0 {
931- return nil
932- }
933- return nft .Run (context .TODO (), tx )
934- }
935-
936932 for _ , udnNet := range udng .Subnets () {
937933 set := nftablesAdvertisedUDNsSetV4
938934 if utilnet .IsIPv6CIDR (udnNet .CIDR ) {
@@ -951,3 +947,41 @@ func (udng *UserDefinedNetworkGateway) updateAdvertisedUDNIsolationRules(isNetwo
951947 }
952948 return nft .Run (context .TODO (), tx )
953949}
950+
951+ func (udng * UserDefinedNetworkGateway ) deleteAdvertisedUDNIsolationRules () error {
952+ nft , err := nodenft .GetNFTablesHelper ()
953+ if err != nil {
954+ return fmt .Errorf ("failed to get nftables helper: %v" , err )
955+ }
956+ tx := nft .NewTransaction ()
957+
958+ existingV4 , err := nft .ListElements (context .TODO (), "set" , nftablesAdvertisedUDNsSetV4 )
959+ if err != nil {
960+ if ! knftables .IsNotFound (err ) {
961+ return fmt .Errorf ("could not list existing items in %s set: %w" , nftablesAdvertisedUDNsSetV4 , err )
962+ }
963+ }
964+ existingV6 , err := nft .ListElements (context .TODO (), "set" , nftablesAdvertisedUDNsSetV6 )
965+ if err != nil {
966+ if ! knftables .IsNotFound (err ) {
967+ return fmt .Errorf ("could not list existing items in %s set: %w" , nftablesAdvertisedUDNsSetV6 , err )
968+ }
969+ }
970+
971+ for _ , elem := range append (existingV4 , existingV6 ... ) {
972+ if elem .Comment != nil && * elem .Comment == udng .GetNetworkName () {
973+ tx .Delete (elem )
974+ }
975+ }
976+
977+ if tx .NumOperations () == 0 {
978+ return nil
979+ }
980+ return nft .Run (context .TODO (), tx )
981+ }
982+
983+ func (udng * UserDefinedNetworkGateway ) updateAdvertisementStatus () {
984+ vrfs := udng .GetPodNetworkAdvertisedOnNodeVRFs (udng .node .Name )
985+ udng .isNetworkAdvertised = len (vrfs ) > 0
986+ udng .isNetworkAdvertisedToDefaultVRF = slices .Contains (vrfs , types .DefaultNetworkName )
987+ }
0 commit comments