@@ -411,18 +411,33 @@ func (npw *nodePortWatcher) updateServiceFlowCache(service *corev1.Service, netI
411
411
}
412
412
413
413
ipPrefix := "ip"
414
- masqueradeSubnet := config .Gateway .V4MasqueradeSubnet
415
414
if ! utilnet .IsIPv4String (service .Spec .ClusterIP ) {
416
415
ipPrefix = "ipv6"
417
- masqueradeSubnet = config .Gateway .V6MasqueradeSubnet
418
416
}
419
417
// table 2, user-defined network host -> OVN towards default cluster network services
420
418
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, " +
423
423
"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 )
426
441
}
427
442
}
428
443
return utilerrors .Join (errors ... )
@@ -1593,6 +1608,37 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
1593
1608
"actions=ct(commit,zone=%d,table=2)" ,
1594
1609
defaultOpenFlowCookie , ofPortHost , protoPrefix , protoPrefix ,
1595
1610
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
+ }
1596
1642
}
1597
1643
1598
1644
masqDst := masqIP
@@ -1706,10 +1752,27 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
1706
1752
if netConfig .isDefaultNetwork () {
1707
1753
continue
1708
1754
}
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
+ }
1709
1772
dftFlows = append (dftFlows ,
1710
1773
fmt .Sprintf ("cookie=%s, priority=200, table=2, ip, ip_src=%s, " +
1711
1774
"actions=set_field:%s->eth_dst,output:%s" ,
1712
- defaultOpenFlowCookie , netConfig . v4MasqIPs . ManagementPort . IP ,
1775
+ defaultOpenFlowCookie , srcIPOrSubnet ,
1713
1776
bridgeMacAddress , netConfig .ofPortPatch ))
1714
1777
dftFlows = append (dftFlows ,
1715
1778
fmt .Sprintf ("cookie=%s, priority=200, table=2, ip, pkt_mark=%s, " +
@@ -1724,11 +1787,27 @@ func flowsForDefaultBridge(bridge *bridgeConfiguration, extraIPs []net.IP) ([]st
1724
1787
if netConfig .isDefaultNetwork () {
1725
1788
continue
1726
1789
}
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
+ }
1727
1803
1804
+ // Use the filtered subnets for the flow compute instead of the masqueradeIP
1805
+ srcIPOrSubnet = matchingIPFamilySubnet .String ()
1806
+ }
1728
1807
dftFlows = append (dftFlows ,
1729
1808
fmt .Sprintf ("cookie=%s, priority=200, table=2, ip6, ipv6_src=%s, " +
1730
1809
"actions=set_field:%s->eth_dst,output:%s" ,
1731
- defaultOpenFlowCookie , netConfig . v6MasqIPs . ManagementPort . IP ,
1810
+ defaultOpenFlowCookie , srcIPOrSubnet ,
1732
1811
bridgeMacAddress , netConfig .ofPortPatch ))
1733
1812
dftFlows = append (dftFlows ,
1734
1813
fmt .Sprintf ("cookie=%s, priority=200, table=2, ip6, pkt_mark=%s, " +
0 commit comments