Skip to content

Commit aa2557a

Browse files
authored
Merge pull request #5192 from tssurya/bgp-isolation-udnpod-to-default-net-svc-take2
Isolate default network services from UDN pods
2 parents 14237a8 + c24ff47 commit aa2557a

File tree

5 files changed

+380
-16
lines changed

5 files changed

+380
-16
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,9 +932,12 @@ func (udng *UserDefinedNetworkGateway) doReconcile() error {
932932
// add below OpenFlows based on the gateway mode and whether the network is advertised or not:
933933
// table=1, n_packets=0, n_bytes=0, priority=16,ip,nw_dst=128.192.0.2 actions=LOCAL (Both gateway modes)
934934
// 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
935936
if err := udng.openflowManager.updateBridgeFlowCache(udng.nodeIPManager.ListAddresses()); err != nil {
936937
return fmt.Errorf("error while updating logical flow for UDN %s: %s", udng.GetNetworkName(), err)
937938
}
939+
// let's sync these flows immediately
940+
udng.openflowManager.requestFlowSync()
938941

939942
if err := udng.updateAdvertisedUDNIsolationRules(isNetworkAdvertised); err != nil {
940943
return fmt.Errorf("error while updating advertised UDN isolation rules for network %s: %w", udng.GetNetworkName(), err)

0 commit comments

Comments
 (0)