The conntrack flush of a removed ECMP next-hop is queued in front of the flow bundle that takes the next-hop out of the flows. A packet that the switch handles in between finds no conntrack entry and goes through the old flows, which can still pick the removed next-hop and commit a new entry with its MAC in ct_label. Nothing flushes that entry later.
Queue the flush after the bundle instead, next to the LB 5-tuple flushes. The test now checks that the flush follows the bundle commit. CC: Lorenzo Bianconi <[email protected]> CC: Dumitru Ceara <[email protected]> Fixes: b4cacd5c2142 ("ofctrl: Introduce ecmp_nexthop_monitor.") Assisted-by: Claude Opus 5.5, Claude Code Signed-off-by: Bekei Park <[email protected]> --- v2: No change. controller/ofctrl.c | 15 +++++++++------ tests/ovn.at | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 12da7f7..194a0c0 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -2821,12 +2821,6 @@ ofctrl_put(struct ovn_desired_flow_table *lflow_table, /* OpenFlow messages to send to the switch to bring it up-to-date. */ struct ovs_list msgs = OVS_LIST_INITIALIZER(&msgs); - /* Removed ECMP next-hops stay pending while the connection is down, - * because rconn drops the messages queued then. */ - if (rconn_is_connected(swconn)) { - ecmp_nexthop_monitor_flush(swconn, &msgs); - } - /* Iterate through ct zones that need to be flushed. */ struct shash_node *iter; SHASH_FOR_EACH(iter, pending_ct_zones) { @@ -3024,6 +3018,15 @@ ofctrl_put(struct ovn_desired_flow_table *lflow_table, } } + /* Flush the conntrack entries of removed ECMP next-hops after the flow + * bundle, so that a packet in between cannot commit a new entry towards + * a removed next-hop through the old flows. Removed next-hops stay + * pending while the connection is down, because rconn drops the + * messages queued then. */ + if (rconn_is_connected(swconn)) { + ecmp_nexthop_monitor_flush(swconn, &msgs); + } + acl_ids_flush_expired(tracked_acl_ids, rconn_get_version(swconn), &msgs); if (!ovs_list_is_empty(&msgs)) { diff --git a/tests/ovn.at b/tests/ovn.at index 2ba8514..8f544a9 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -48718,7 +48718,7 @@ check test -n "$zone" flush_10="NXT_CT_FLUSH .* zone=$zone labels=0xf0000000101000000000/" flush_20="NXT_CT_FLUSH .* zone=$zone labels=0xf0000000202000000000/" -AS_BOX([Removed next-hop is flushed]) +AS_BOX([Removed next-hop is flushed after the flow bundle]) n=$(wc -l < hv1/ovs-vswitchd.log) check ovn-nbctl --wait=hv lr-route-del lr0 1.0.0.0/24 192.168.10.20 tail -n +$((n + 1)) hv1/ovs-vswitchd.log > vswitchd-del.log @@ -48726,6 +48726,10 @@ AT_CHECK([grep -c "$flush_20" vswitchd-del.log], [0], [1 ]) AT_CHECK([grep -c "$flush_10" vswitchd-del.log], [1], [0 ]) +commit=$(grep -n "type=COMMIT_REQUEST" vswitchd-del.log | head -1 | cut -d: -f1) +flush=$(grep -n "$flush_20" vswitchd-del.log | cut -d: -f1) +check test -n "$commit" +check test "$commit" -lt "$flush" AS_BOX([Removed next-hop is flushed when ofctrl could not send at removal]) check ovn-nbctl --ecmp-symmetric-reply lr-route-add lr0 1.0.0.0/24 192.168.10.20 -- 2.43.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
