Skip to content

Commit b5cb8cc

Browse files
committed
Merge remote-tracking branch 'ovnorg/master' into downstream-merge-28th-april-2025
2 parents 7ca0c99 + aa2557a commit b5cb8cc

File tree

5 files changed

+400
-26
lines changed

5 files changed

+400
-26
lines changed

go-controller/pkg/node/gateway.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ func (g *gateway) AddEgressIP(eip *egressipv1.EgressIP) error {
241241
if err = g.Reconcile(); err != nil {
242242
return fmt.Errorf("failed to sync gateway: %v", err)
243243
}
244-
g.openflowManager.requestFlowSync()
245244
}
246245
return nil
247246
}
@@ -258,7 +257,6 @@ func (g *gateway) UpdateEgressIP(oldEIP, newEIP *egressipv1.EgressIP) error {
258257
if err = g.Reconcile(); err != nil {
259258
return fmt.Errorf("failed to sync gateway: %v", err)
260259
}
261-
g.openflowManager.requestFlowSync()
262260
}
263261
return nil
264262
}
@@ -275,7 +273,6 @@ func (g *gateway) DeleteEgressIP(eip *egressipv1.EgressIP) error {
275273
if err = g.Reconcile(); err != nil {
276274
return fmt.Errorf("failed to sync gateway: %v", err)
277275
}
278-
g.openflowManager.requestFlowSync()
279276
}
280277
return nil
281278
}
@@ -290,7 +287,6 @@ func (g *gateway) SyncEgressIP(eips []interface{}) error {
290287
if err := g.Reconcile(); err != nil {
291288
return fmt.Errorf("failed to sync gateway: %v", err)
292289
}
293-
g.openflowManager.requestFlowSync()
294290
return nil
295291
}
296292

@@ -492,6 +488,8 @@ func (g *gateway) Reconcile() error {
492488
if err := g.openflowManager.updateBridgeFlowCache(g.nodeIPManager.ListAddresses()); err != nil {
493489
return err
494490
}
491+
// let's sync these flows immediately
492+
g.openflowManager.requestFlowSync()
495493
err := g.updateSNATRules()
496494
if err != nil {
497495
return err

go-controller/pkg/node/gateway_shared_intf.go

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -411,18 +411,33 @@ func (npw *nodePortWatcher) updateServiceFlowCache(service *corev1.Service, netI
411411
}
412412

413413
ipPrefix := "ip"
414-
masqueradeSubnet := config.Gateway.V4MasqueradeSubnet
415414
if !utilnet.IsIPv4String(service.Spec.ClusterIP) {
416415
ipPrefix = "ipv6"
417-
masqueradeSubnet = config.Gateway.V6MasqueradeSubnet
418416
}
419417
// table 2, user-defined network host -> OVN towards default cluster network services
420418
defaultNetConfig := npw.ofm.defaultBridge.getActiveNetworkBridgeConfig(types.DefaultNetworkName)
421-
422-
npw.ofm.updateFlowCacheEntry(key, []string{fmt.Sprintf("cookie=%s, priority=300, table=2, %s, %s_src=%s, %s_dst=%s, "+
419+
// sample flow: cookie=0xdeff105, duration=2319.685s, table=2, n_packets=496, n_bytes=67111, priority=300,
420+
// ip,nw_dst=10.96.0.1 actions=mod_dl_dst:02:42:ac:12:00:03,output:"patch-breth0_ov"
421+
// This flow is used for UDNs and advertised UDNs to be able to reach kapi and dns services alone on default network
422+
flows := []string{fmt.Sprintf("cookie=%s, priority=300, table=2, %s, %s_dst=%s, "+
423423
"actions=set_field:%s->eth_dst,output:%s",
424-
defaultOpenFlowCookie, ipPrefix, ipPrefix, masqueradeSubnet, ipPrefix, service.Spec.ClusterIP,
425-
npw.ofm.getDefaultBridgeMAC().String(), defaultNetConfig.ofPortPatch)})
424+
defaultOpenFlowCookie, ipPrefix, ipPrefix, service.Spec.ClusterIP,
425+
npw.ofm.getDefaultBridgeMAC().String(), defaultNetConfig.ofPortPatch)}
426+
if util.IsRouteAdvertisementsEnabled() {
427+
// if the network is advertised, then for the reply from kapi and dns services to go back
428+
// into the UDN's VRF we need flows that statically send this to the local port
429+
// sample flow: cookie=0xdeff105, duration=264.196s, table=0, n_packets=0, n_bytes=0, priority=490,ip,
430+
// in_port="patch-breth0_ov",nw_src=10.96.0.10,actions=ct(table=3,zone=64001,nat)
431+
// this flow is meant to match all advertised UDNs and then the ip rules on the host will take
432+
// this packet into the corresponding UDNs
433+
// NOTE: We chose priority 490 to differentiate this flow from the flow at priority 500 added for the
434+
// non-advertised UDNs reponse for debugging purposes:
435+
// sample flow for non-advertised UDNs: cookie=0xdeff105, duration=684.087s, table=0, n_packets=0, n_bytes=0,
436+
// idle_age=684, priority=500,ip,in_port=2,nw_src=10.96.0.0/16,nw_dst=169.254.0.0/17 actions=ct(table=3,zone=64001,nat)
437+
flows = append(flows, fmt.Sprintf("cookie=%s, priority=490, in_port=%s, ip, ip_src=%s,actions=ct(zone=%d,nat,table=3)",
438+
defaultOpenFlowCookie, defaultNetConfig.ofPortPatch, service.Spec.ClusterIP, config.Default.HostMasqConntrackZone))
439+
}
440+
npw.ofm.updateFlowCacheEntry(key, flows)
426441
}
427442
}
428443
return utilerrors.Join(errors...)
@@ -1593,6 +1608,37 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
15931608
"actions=ct(commit,zone=%d,table=2)",
15941609
defaultOpenFlowCookie, ofPortHost, protoPrefix, protoPrefix,
15951610
masqSubnet, protoPrefix, svcCIDR, config.Default.HostMasqConntrackZone))
1611+
if util.IsRouteAdvertisementsEnabled() {
1612+
// If the UDN is advertised then instead of matching on the masqSubnet
1613+
// we match on the UDNPodSubnet itself and we also don't SNAT to 169.254.0.2
1614+
// sample flow: cookie=0xdeff105, duration=1472.742s, table=0, n_packets=9, n_bytes=666, priority=550
1615+
// ip,in_port=LOCAL,nw_src=103.103.0.0/16,nw_dst=10.96.0.0/16 actions=ct(commit,table=2,zone=64001)
1616+
for _, netConfig := range bridge.patchedNetConfigs() {
1617+
if netConfig.isDefaultNetwork() {
1618+
continue
1619+
}
1620+
if netConfig.advertised.Load() {
1621+
var udnAdvertisedSubnets []*net.IPNet
1622+
for _, clusterEntry := range netConfig.subnets {
1623+
udnAdvertisedSubnets = append(udnAdvertisedSubnets, clusterEntry.CIDR)
1624+
}
1625+
// Filter subnets based on the clusterIP service family
1626+
// NOTE: We don't support more than 1 subnet CIDR of same family type; we only pick the first one
1627+
matchingIPFamilySubnet, err := util.MatchFirstIPNetFamily(utilnet.IsIPv6CIDR(svcCIDR), udnAdvertisedSubnets)
1628+
if err != nil {
1629+
klog.Infof("Unable to determine UDN subnet for the provided family isIPV6: %t, %v", utilnet.IsIPv6CIDR(svcCIDR), err)
1630+
continue
1631+
}
1632+
1633+
// Use the filtered subnet for the flow compute instead of the masqueradeIP
1634+
dftFlows = append(dftFlows,
1635+
fmt.Sprintf("cookie=%s, priority=550, in_port=%s, %s, %s_src=%s, %s_dst=%s, "+
1636+
"actions=ct(commit,zone=%d,table=2)",
1637+
defaultOpenFlowCookie, ofPortHost, protoPrefix, protoPrefix,
1638+
matchingIPFamilySubnet.String(), protoPrefix, svcCIDR, config.Default.HostMasqConntrackZone))
1639+
}
1640+
}
1641+
}
15961642
}
15971643

15981644
masqDst := masqIP
@@ -1706,10 +1752,27 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
17061752
if netConfig.isDefaultNetwork() {
17071753
continue
17081754
}
1755+
srcIPOrSubnet := netConfig.v4MasqIPs.ManagementPort.IP.String()
1756+
if util.IsRouteAdvertisementsEnabled() && netConfig.advertised.Load() {
1757+
var udnAdvertisedSubnets []*net.IPNet
1758+
for _, clusterEntry := range netConfig.subnets {
1759+
udnAdvertisedSubnets = append(udnAdvertisedSubnets, clusterEntry.CIDR)
1760+
}
1761+
// Filter subnets based on the clusterIP service family
1762+
// NOTE: We don't support more than 1 subnet CIDR of same family type; we only pick the first one
1763+
matchingIPFamilySubnet, err := util.MatchFirstIPNetFamily(false, udnAdvertisedSubnets)
1764+
if err != nil {
1765+
klog.Infof("Unable to determine IPV4 UDN subnet for the provided family isIPV6: %v", err)
1766+
continue
1767+
}
1768+
1769+
// Use the filtered subnets for the flow compute instead of the masqueradeIP
1770+
srcIPOrSubnet = matchingIPFamilySubnet.String()
1771+
}
17091772
dftFlows = append(dftFlows,
17101773
fmt.Sprintf("cookie=%s, priority=200, table=2, ip, ip_src=%s, "+
17111774
"actions=set_field:%s->eth_dst,output:%s",
1712-
defaultOpenFlowCookie, netConfig.v4MasqIPs.ManagementPort.IP,
1775+
defaultOpenFlowCookie, srcIPOrSubnet,
17131776
bridgeMacAddress, netConfig.ofPortPatch))
17141777
dftFlows = append(dftFlows,
17151778
fmt.Sprintf("cookie=%s, priority=200, table=2, ip, pkt_mark=%s, "+
@@ -1724,11 +1787,27 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
17241787
if netConfig.isDefaultNetwork() {
17251788
continue
17261789
}
1790+
srcIPOrSubnet := netConfig.v6MasqIPs.ManagementPort.IP.String()
1791+
if util.IsRouteAdvertisementsEnabled() && netConfig.advertised.Load() {
1792+
var udnAdvertisedSubnets []*net.IPNet
1793+
for _, clusterEntry := range netConfig.subnets {
1794+
udnAdvertisedSubnets = append(udnAdvertisedSubnets, clusterEntry.CIDR)
1795+
}
1796+
// Filter subnets based on the clusterIP service family
1797+
// NOTE: We don't support more than 1 subnet CIDR of same family type; we only pick the first one
1798+
matchingIPFamilySubnet, err := util.MatchFirstIPNetFamily(true, udnAdvertisedSubnets)
1799+
if err != nil {
1800+
klog.Infof("Unable to determine IPV6 UDN subnet for the provided family isIPV6: %v", err)
1801+
continue
1802+
}
17271803

1804+
// Use the filtered subnets for the flow compute instead of the masqueradeIP
1805+
srcIPOrSubnet = matchingIPFamilySubnet.String()
1806+
}
17281807
dftFlows = append(dftFlows,
17291808
fmt.Sprintf("cookie=%s, priority=200, table=2, ip6, ipv6_src=%s, "+
17301809
"actions=set_field:%s->eth_dst,output:%s",
1731-
defaultOpenFlowCookie, netConfig.v6MasqIPs.ManagementPort.IP,
1810+
defaultOpenFlowCookie, srcIPOrSubnet,
17321811
bridgeMacAddress, netConfig.ofPortPatch))
17331812
dftFlows = append(dftFlows,
17341813
fmt.Sprintf("cookie=%s, priority=200, table=2, ip6, pkt_mark=%s, "+

go-controller/pkg/node/gateway_udn.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,22 @@ func (udng *UserDefinedNetworkGateway) AddNetwork() error {
359359
if err = udng.vrfManager.AddVRFRoutes(vrfDeviceName, routes); err != nil {
360360
return fmt.Errorf("could not add VRF %s routes for network %s, err: %v", vrfDeviceName, udng.GetNetworkName(), err)
361361
}
362+
363+
isNetworkAdvertised := util.IsPodNetworkAdvertisedAtNode(udng.NetInfo, udng.node.Name)
364+
362365
// create the iprules for this network
363-
err = udng.updateUDNVRFIPRule()
364-
if err != nil {
366+
if err = udng.updateUDNVRFIPRules(isNetworkAdvertised); err != nil {
365367
return fmt.Errorf("failed to update IP rules for network %s: %w", udng.GetNetworkName(), err)
366368
}
369+
370+
if err = udng.updateAdvertisedUDNIsolationRules(isNetworkAdvertised); err != nil {
371+
return fmt.Errorf("failed to update isolation rules for network %s: %w", udng.GetNetworkName(), err)
372+
}
373+
374+
if err := udng.updateUDNVRFIPRoute(isNetworkAdvertised); err != nil {
375+
return fmt.Errorf("failed to update ip routes for network %s: %w", udng.GetNetworkName(), err)
376+
}
377+
367378
// add loose mode for rp filter on management port
368379
mgmtPortName := util.GetNetworkScopedK8sMgmtHostIntfName(uint(udng.GetNetworkID()))
369380
if err := addRPFilterLooseModeForManagementPort(mgmtPortName); err != nil {
@@ -777,12 +788,11 @@ func (udng *UserDefinedNetworkGateway) getV6MasqueradeIP() (*net.IPNet, error) {
777788
// 2000: from all to 10.132.0.0/14 lookup 1007
778789
// 2000: from all fwmark 0x1001 lookup 1009
779790
// 2000: from all to 10.134.0.0/14 lookup 1009
780-
func (udng *UserDefinedNetworkGateway) constructUDNVRFIPRules() ([]netlink.Rule, []netlink.Rule, error) {
791+
func (udng *UserDefinedNetworkGateway) constructUDNVRFIPRules(isNetworkAdvertised bool) ([]netlink.Rule, []netlink.Rule, error) {
781792
var addIPRules []netlink.Rule
782793
var delIPRules []netlink.Rule
783794
var masqIPRules []netlink.Rule
784795
var subnetIPRules []netlink.Rule
785-
isNetworkAdvertised := util.IsPodNetworkAdvertisedAtNode(udng.NetInfo, udng.node.Name)
786796
masqIPv4, err := udng.getV4MasqueradeIP()
787797
if err != nil {
788798
return nil, nil, err
@@ -911,7 +921,7 @@ func (udng *UserDefinedNetworkGateway) doReconcile() error {
911921
isNetworkAdvertised := util.IsPodNetworkAdvertisedAtNode(udng.NetInfo, udng.node.Name)
912922
udng.openflowManager.defaultBridge.netConfig[udng.GetNetworkName()].advertised.Store(isNetworkAdvertised)
913923

914-
if err := udng.updateUDNVRFIPRule(); err != nil {
924+
if err := udng.updateUDNVRFIPRules(isNetworkAdvertised); err != nil {
915925
return fmt.Errorf("error while updating ip rule for UDN %s: %s", udng.GetNetworkName(), err)
916926
}
917927

@@ -922,20 +932,23 @@ func (udng *UserDefinedNetworkGateway) doReconcile() error {
922932
// add below OpenFlows based on the gateway mode and whether the network is advertised or not:
923933
// table=1, n_packets=0, n_bytes=0, priority=16,ip,nw_dst=128.192.0.2 actions=LOCAL (Both gateway modes)
924934
// table=1, n_packets=0, n_bytes=0, priority=15,ip,nw_dst=128.192.0.0/14 actions=output:3 (shared gateway mode)
935+
// necessary service isolation flows based on whether network is advertised or not
925936
if err := udng.openflowManager.updateBridgeFlowCache(udng.nodeIPManager.ListAddresses()); err != nil {
926937
return fmt.Errorf("error while updating logical flow for UDN %s: %s", udng.GetNetworkName(), err)
927938
}
939+
// let's sync these flows immediately
940+
udng.openflowManager.requestFlowSync()
928941

929942
if err := udng.updateAdvertisedUDNIsolationRules(isNetworkAdvertised); err != nil {
930943
return fmt.Errorf("error while updating advertised UDN isolation rules for network %s: %w", udng.GetNetworkName(), err)
931944
}
932945
return nil
933946
}
934947

935-
// updateUDNVRFIPRule updates IP rules for a network depending on whether the
948+
// updateUDNVRFIPRules updates IP rules for a network depending on whether the
936949
// network is advertised or not
937-
func (udng *UserDefinedNetworkGateway) updateUDNVRFIPRule() error {
938-
addIPRules, deleteIPRules, err := udng.constructUDNVRFIPRules()
950+
func (udng *UserDefinedNetworkGateway) updateUDNVRFIPRules(isNetworkAdvertised bool) error {
951+
addIPRules, deleteIPRules, err := udng.constructUDNVRFIPRules(isNetworkAdvertised)
939952
if err != nil {
940953
return fmt.Errorf("unable to get iprules for network %s, err: %v", udng.GetNetworkName(), err)
941954
}

0 commit comments

Comments
 (0)