@@ -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, " +
0 commit comments