Skip to content

Commit 7db6c99

Browse files
committed
Reapply "Add the IP rule for a UDN only when it is advertised to the default VRF"
This reverts commit 1ea2739. Signed-off-by: Jaime Caamaño Ruiz <[email protected]>
1 parent bcfce1b commit 7db6c99

File tree

2 files changed

+318
-92
lines changed

2 files changed

+318
-92
lines changed

go-controller/pkg/node/gateway_udn.go

Lines changed: 116 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

9498
func 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
622625
func (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

872885
func (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

Comments
 (0)