From 52c80de3cf9df37909cb68d873e7c4af408dcba4 Mon Sep 17 00:00:00 2001 From: Tim Rozet Date: Wed, 27 Aug 2025 15:16:40 -0400 Subject: [PATCH 1/3] Openflow: lookup conntrack & table=1 only when breth0 is next hop Fixes regression from 1448d5ab14337b647f3e3034ea4ffc077431979a The previous commit dropped matching on in_port so that localnet ports would also use table 1. This allows reply packets from a localnet pod towards the shared OVN/LOCAL IP to be sent to the correct port. However, a regression was introduced where traffic coming from these localnet ports to any destination would be sent to table 1. Egress traffic from the localnet ports is not committed to conntrack, so by sending to table=1 via CT we were getting a miss. This is especially bad for hardware offload where a localnet port is being used as the Geneve encap port. In this case all geneve traffic misses in CT lookup and is not offloaded. Table 1 is intended to be for handling IP traffic destined to the shared Gateway IP/MAC that both the Host and OVN use. It is also used to handle reply traffic for Egress IP. To fix this problem, we can add dl_dst match criteria to this flow, ensuring that only traffic destined to the Host/OVN goes to table 1. Furthermore, after fixing this problem there still exists the issue that localnet -> host/OVN egress traffic will still enter table 1 and CT miss. Potentially this can be fixed with always committing egress traffic, but it might have performance penalty, so deferring that fix to a later date. Signed-off-by: Tim Rozet --- go-controller/pkg/node/bridgeconfig/bridgeflows.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go-controller/pkg/node/bridgeconfig/bridgeflows.go b/go-controller/pkg/node/bridgeconfig/bridgeflows.go index 8a858c30e9..94d13acd9a 100644 --- a/go-controller/pkg/node/bridgeconfig/bridgeflows.go +++ b/go-controller/pkg/node/bridgeconfig/bridgeflows.go @@ -632,12 +632,12 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e } if ofPortPhys != "" { - // table 0, packets coming from external or other localnet ports. Send it through conntrack and - // resubmit to table 1 to know the state and mark of the connection. + // table 0, packets coming from external or other localnet ports and destined to OVN or LOCAL. + // Send it through conntrack and resubmit to table 1 to know the state and mark of the connection. // Note, there are higher priority rules that take care of traffic coming from LOCAL and OVN ports. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=50, ip, actions=ct(zone=%d, nat, table=1)", - nodetypes.DefaultOpenFlowCookie, config.Default.ConntrackZone)) + fmt.Sprintf("cookie=%s, priority=50, ip, dl_dst=%s, actions=ct(zone=%d, nat, table=1)", + nodetypes.DefaultOpenFlowCookie, bridgeMacAddress, config.Default.ConntrackZone)) } } From d0d15bd4fc0fdd7f045ac9d7ded5cf58040323c3 Mon Sep 17 00:00:00 2001 From: Riccardo Ravaioli Date: Thu, 28 Aug 2025 19:37:51 +0200 Subject: [PATCH 2/3] Openflow: drop in_port from IPv6 dispatch OF rule at prio=50 We did this for IPv4 in 1448d5ab14337b647f3e3034ea4ffc077431979a, but forgot about IPv6. Signed-off-by: Riccardo Ravaioli --- go-controller/pkg/node/bridgeconfig/bridgeflows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go-controller/pkg/node/bridgeconfig/bridgeflows.go b/go-controller/pkg/node/bridgeconfig/bridgeflows.go index 94d13acd9a..147dc98e07 100644 --- a/go-controller/pkg/node/bridgeconfig/bridgeflows.go +++ b/go-controller/pkg/node/bridgeconfig/bridgeflows.go @@ -733,8 +733,8 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, packets coming from external. Send it through conntrack and // resubmit to table 1 to know the state and mark of the connection. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=50, in_port=%s, ipv6, "+ - "actions=ct(zone=%d, nat, table=1)", nodetypes.DefaultOpenFlowCookie, ofPortPhys, config.Default.ConntrackZone)) + fmt.Sprintf("cookie=%s, priority=50, ipv6, "+ + "actions=ct(zone=%d, nat, table=1)", nodetypes.DefaultOpenFlowCookie, config.Default.ConntrackZone)) } } if ofPortPhys != "" { From 493bd877ea322430a27a6f5460978dd38ee1a8a0 Mon Sep 17 00:00:00 2001 From: Riccardo Ravaioli Date: Thu, 28 Aug 2025 19:40:26 +0200 Subject: [PATCH 3/3] Openflow: lookup conntrack & table=1 when breth0 is next hop (IPv6) Add dl_dst=$breth0 to table=0, prio=50 for IPv6 We want to match in table=1 only conntrack'ed reply traffic whose next hop is either OVN or the host. As a consequence, localnet traffic whose next hop is an external router (and that might or might not be destined to OVN/host) should bypass table=1 and just hit the NORMAL flow in table=0. Signed-off-by: Riccardo Ravaioli --- go-controller/pkg/node/bridgeconfig/bridgeflows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go-controller/pkg/node/bridgeconfig/bridgeflows.go b/go-controller/pkg/node/bridgeconfig/bridgeflows.go index 147dc98e07..2fd111cfac 100644 --- a/go-controller/pkg/node/bridgeconfig/bridgeflows.go +++ b/go-controller/pkg/node/bridgeconfig/bridgeflows.go @@ -733,8 +733,8 @@ func (b *BridgeConfiguration) commonFlows(hostSubnets []*net.IPNet) ([]string, e // table 0, packets coming from external. Send it through conntrack and // resubmit to table 1 to know the state and mark of the connection. dftFlows = append(dftFlows, - fmt.Sprintf("cookie=%s, priority=50, ipv6, "+ - "actions=ct(zone=%d, nat, table=1)", nodetypes.DefaultOpenFlowCookie, config.Default.ConntrackZone)) + fmt.Sprintf("cookie=%s, priority=50, ipv6, dl_dst=%s, actions=ct(zone=%d, nat, table=1)", + nodetypes.DefaultOpenFlowCookie, bridgeMacAddress, config.Default.ConntrackZone)) } } if ofPortPhys != "" {