On 2/11/26 11:12 AM, Ales Musil wrote:
> On Tue, Feb 10, 2026 at 12:24 PM Dumitru Ceara via dev <
> [email protected]> wrote:
>
>> Commit 9c3ae6f27475 ("northd: Add ECMP symmetric replies for egress.")
>> tried to add ECMP-symmetric-reply semantics to traffic forwarded on
>> sessions initiating from "behind" the static route, i.e., traffic
>> hitting the route in the original direction.
>>
>> However, it decided to commit the session to conntrack only when we
>> finally received reply traffic on the session.
>>
>> As shown in https://issues.redhat.com/browse/FDP-1983, if the hash
>> function of the ECMP route changes in between the original SYN and the
>> last ACK of the 3-way-handshake of a TCP session (e.g., if ECMP paths
>> are added to the route) then traffic in the original direction might
>> incorrectly migrate and be forwarded via a different next-hop than the
>> original SYN.
>>
>> In order to fix this, we now commit the traffic on the first SYN instead
>> of waiting for replies. That happens in a new logical router pipeline
>> stage 'lr_in_ecmp_stateful_egr', just after 'lr_in_arp_request' where
>> which we store the (resolved) next-hop MAC and packet out-port in
>> conntrack for traffic forwarded by ECMP-symmetric-reply static routes
>> (in the original direction).
>>
>> The system-ovn.at tests also had to be updated because, due to the fact
>> that traffic was committed to conntrack only on the first
>> non-session-setup reply, the tuples were "wrong". I.e., the conntrack
>> session looked as if it had been created from "outside" the static
>> route.
>>
>> Fixes: 9c3ae6f27475 ("northd: Add ECMP symmetric replies for egress.")
>> Reported-at: https://issues.redhat.com/browse/FDP-1983
>> Signed-off-by: Dumitru Ceara <[email protected]>
>> ---
>>
>
> Hi Dumitru,
>
> thank you for the patch, just one tiny nit below.
>
Hi Ales,
Thanks for the review!
>
>> lib/ovn-util.c | 4 +--
>> northd/northd.c | 54 ++++++++++++++++++++++++++++++++++++-----
>> northd/northd.h | 2 ++
>> northd/ovn-northd.8.xml | 18 +++++++++++---
>> tests/ovn-northd.at | 45 ++++++++++++++++++++++++++--------
>> tests/system-ovn.at | 12 ++++++---
>> 6 files changed, 110 insertions(+), 25 deletions(-)
>>
>> diff --git a/lib/ovn-util.c b/lib/ovn-util.c
>> index 8a065e3c29..2df51dc7ef 100644
>> --- a/lib/ovn-util.c
>> +++ b/lib/ovn-util.c
>> @@ -968,8 +968,8 @@ ip_address_and_port_from_lb_key(const char *key, char
>> **ip_address,
>> *
>> * NOTE: If OVN_NORTHD_PIPELINE_CSUM is updated make sure to double check
>> * whether an update of OVN_INTERNAL_MINOR_VER is required. */
>> -#define OVN_NORTHD_PIPELINE_CSUM "4239189964 11014"
>> -#define OVN_INTERNAL_MINOR_VER 11
>> +#define OVN_NORTHD_PIPELINE_CSUM "45472499 11094"
>> +#define OVN_INTERNAL_MINOR_VER 12
>>
>> /* Returns the OVN version. The caller must free the returned value. */
>> char *
>> diff --git a/northd/northd.c b/northd/northd.c
>> index 2df205ec23..9b74fd4667 100644
>> --- a/northd/northd.c
>> +++ b/northd/northd.c
>> @@ -201,6 +201,9 @@ BUILD_ASSERT_DECL(ACL_OBS_STAGE_MAX < (1 << 2));
>> #define REGBIT_DHCP_RELAY_REQ_CHK "reg9[7]"
>> #define REGBIT_DHCP_RELAY_RESP_CHK "reg9[8]"
>> #define REGBIT_NEXTHOP_IS_IPV4 "reg9[9]"
>> +/* Register bit to store whether we need to commit this ECMP symmetric
>> + * reply processed packet after resolving its next-hop MAC address. */
>> +#define REGBIT_NEEDS_ECMP_STATEFUL_COMMIT "reg9[10]"
>>
>> /* Register to store the eth address associated to a router port for
>> packets
>> * received in S_ROUTER_IN_ADMISSION.
>> @@ -12345,6 +12348,7 @@ add_ecmp_symmetric_reply_flows(struct lflow_table
>> *lflows,
>> * ds_put_cstr() call. The previous contents are needed.
>> */
>> ds_put_cstr(&match, " && (ct.new || ct.est)");
>> +
>>
>
> nit: Unrelated change.
>
>
Ah, my bad.
>> ds_put_format(&actions,
>> "ct_commit { ct_label.ecmp_reply_eth = eth.src; "
>> "ct_mark.ecmp_reply_port = %" PRId64 ";}; "
>> @@ -12499,13 +12503,16 @@ build_ecmp_route_flow(struct lflow_table *lflows,
>> "%s = %s; "
>> "eth.src = %s; "
>> "outport = %s; "
>> - REGBIT_NEXTHOP_IS_IPV4" = %d; "
>> - "next;",
>> + REGBIT_NEXTHOP_IS_IPV4" = %d; ",
>> is_ipv4_nexthop ? REG_SRC_IPV4 : REG_SRC_IPV6,
>> route->lrp_addr_s,
>> route->out_port->lrp_networks.ea_s,
>> route->out_port->json_key,
>> is_ipv4_nexthop);
>> + if (route->ecmp_symmetric_reply) {
>> + ds_put_cstr(&actions, REGBIT_NEEDS_ECMP_STATEFUL_COMMIT " =
>> 1; ");
>> + }
>> + ds_put_cstr(&actions, "next;");
>> ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 100,
>> ds_cstr(&match), ds_cstr(&actions), lflow_ref,
>> WITH_HINT(route->source_hint));
>> @@ -15954,7 +15961,7 @@ build_arp_request_flows_for_lrouter(
>> "ip6.dst = %s; "
>> "nd.target = %s; "
>> "output; "
>> - "}; output;", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
>> + "}; next;", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
>> route->nexthop);
>>
>> ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
>> @@ -15974,7 +15981,7 @@ build_arp_request_flows_for_lrouter(
>> "arp.tpa = " REG_NEXT_HOP_IPV4 "; "
>> "arp.op = 1; " /* ARP request */
>> "output; "
>> - "}; output;",
>> + "}; next;",
>> lflow_ref,
>> WITH_CTRL_METER(copp_meter_get(COPP_ARP_RESOLVE,
>> od->nbr->copp,
>>
>> meter_groups)));
>> @@ -15984,11 +15991,40 @@ build_arp_request_flows_for_lrouter(
>> "nd_ns { "
>> "nd.target = " REG_NEXT_HOP_IPV6 "; "
>> "output; "
>> - "}; output;",
>> + "}; next;",
>> lflow_ref,
>> WITH_CTRL_METER(copp_meter_get(COPP_ND_NS_RESOLVE,
>> od->nbr->copp,
>>
>> meter_groups)));
>> - ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1", "output;",
>> + ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1", "next;",
>> + lflow_ref);
>> +}
>> +
>> +static void
>> +build_ecmp_stateful_egr_flows_for_lrouter_port(
>> + struct ovn_port *op, struct lflow_table *lflows,
>> + struct ds *match, struct ds *actions,
>> + struct lflow_ref *lflow_ref)
>> +{
>> + ds_clear(match);
>> + ds_put_format(match, REGBIT_NEEDS_ECMP_STATEFUL_COMMIT " == 1 && ip
>> && "
>> + "outport == %s", op->json_key);
>> +
>> + ds_clear(actions);
>> + ds_put_format(actions,
>> + "ct_commit { ct_label.ecmp_reply_eth = eth.dst; "
>> + "ct_mark.ecmp_reply_port = %" PRId64 ";}; "
>> + "output;",
>> + op->sb->tunnel_key);
>> + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ECMP_STATEFUL_EGR, 100,
>> + ds_cstr(match), ds_cstr(actions), lflow_ref);
>> +}
>> +
>> +static void
>> +build_ecmp_stateful_egr_flows_for_lrouter(
>> + struct ovn_datapath *od, struct lflow_table *lflows,
>> + struct lflow_ref *lflow_ref)
>> +{
>> + ovn_lflow_add(lflows, od, S_ROUTER_IN_ECMP_STATEFUL_EGR, 0, "1",
>> "output;",
>> lflow_ref);
>> }
>>
>> @@ -19039,6 +19075,8 @@ build_lswitch_and_lrouter_iterate_by_lr(struct
>> ovn_datapath *od,
>> &lsi->actions,
>> lsi->meter_groups,
>> od->datapath_lflows);
>> + build_ecmp_stateful_egr_flows_for_lrouter(od, lsi->lflows,
>> + od->datapath_lflows);
>> build_lrouter_network_id_flows(od, lsi->lflows, &lsi->match,
>> &lsi->actions, od->datapath_lflows);
>> build_misc_local_traffic_drop_flows_for_lrouter(od, lsi->lflows,
>> @@ -19129,6 +19167,10 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct
>> ovn_port *op,
>> build_lrouter_routing_protocol_redirect(op, lsi->lflows, &lsi->match,
>> &lsi->actions, op->lflow_ref,
>> lsi->ls_ports,
>> lsi->bfd_ports);
>> + build_ecmp_stateful_egr_flows_for_lrouter_port(op, lsi->lflows,
>> + &lsi->match,
>> + &lsi->actions,
>> + op->lflow_ref);
>> }
>>
>> static void *
>> diff --git a/northd/northd.h b/northd/northd.h
>> index f812656af2..9158f3d532 100644
>> --- a/northd/northd.h
>> +++ b/northd/northd.h
>> @@ -602,6 +602,8 @@ ovn_datapath_is_stale(const struct ovn_datapath *od)
>> PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 25,
>> "lr_in_gw_redirect") \
>> PIPELINE_STAGE(ROUTER, IN, NETWORK_ID, 26, "lr_in_network_id")
>> \
>> PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 27,
>> "lr_in_arp_request") \
>> + PIPELINE_STAGE(ROUTER, IN, ECMP_STATEFUL_EGR, 28,
>> \
>> + "lr_in_ecmp_stateful_egr")
>> \
>> \
>> /* Logical router egress stages. */ \
>> PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0,
>> \
>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
>> index 279d81f35d..ca37d4e398 100644
>> --- a/northd/ovn-northd.8.xml
>> +++ b/northd/ovn-northd.8.xml
>> @@ -5507,8 +5507,9 @@ icmp6 {
>>
>> <p>
>> In the common case where the Ethernet destination has been
>> resolved, this
>> - table outputs the packet. Otherwise, it composes and sends an ARP
>> or
>> - IPv6 Neighbor Solicitation request. It holds the following flows:
>> + table advances the packet to the next table. Otherwise, it
>> composes and
>> + sends an ARP or IPv6 Neighbor Solicitation request. It holds the
>> + following flows:
>> </p>
>>
>> <ul>
>> @@ -5577,10 +5578,21 @@ nd_ns {
>>
>> <li>
>> Known MAC address. A priority-0 flow with match <code>1</code>
>> has
>> - actions <code>output;</code>.
>> + actions <code>next;</code>.
>> </li>
>> </ul>
>>
>> + <h3>Ingress Table 27: ECMP symmetric reply processing for egress</h3>
This was a copy/paste error. It should've been "Table 28".
>> + <p>
>> + This table contains logical flows that commit IP traffic forwarded
>> by
>> + ECMP symmetric reply static routes in the "route direction", that
>> is,
>> + for sessions initiated from behind such routes. These flows can be
>> hit
>> + only on gateway routers, the only type of routers that supports ECMP
>> + symmetric reply routes. As the egress port of the traffic needs to
>> be
>> + stored in conntrack for these sessions, one logical flow is added
>> for
>> + each logical router port.
>> + </p>
>> +
>> <h3>Egress Table 0: Check DNAT local </h3>
>>
>> <p>
>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>> index f3454a3631..aeb07f1dde 100644
>> --- a/tests/ovn-northd.at
>> +++ b/tests/ovn-northd.at
>> @@ -7139,10 +7139,15 @@ AT_CHECK([grep -w "lr_in_ip_routing" lr0flows |
>> ovn_strip_lflows], [0], [dnl
>>
>> AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | ovn_strip_lflows],
>> [0], [dnl
>> table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1),
>> action=(drop;)
>> - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.10; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; next;)
>> + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.10; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; reg9[[10]] = 1; next;)
>> table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]]
>> == 0), action=(next;)
>> ])
>>
>> +AT_CHECK([grep -e "lr_in_ecmp_stateful_egr" lr0flows | ovn_strip_lflows],
>> [0], [dnl
>> + table=??(lr_in_ecmp_stateful_egr), priority=0 , match=(1),
>> action=(output;)
>> + table=??(lr_in_ecmp_stateful_egr), priority=100 , match=(reg9[[10]] ==
>> 1 && ip && outport == "lr0-public"), action=(ct_commit {
>> ct_label.ecmp_reply_eth = eth.dst; ct_mark.ecmp_reply_port = 1;}; output;)
>> +])
>> +
>> check ovn-nbctl --wait=sb --ecmp-symmetric-reply lr-route-add lr0 1.0.0.1
>> 192.168.0.20
>> check_row_count ECMP_Nexthop 2
>> check_column 192.168.0.10 ECMP_Nexthop nexthop nexthop=192.168.0.10
>> @@ -7159,8 +7164,8 @@ AT_CHECK([grep -w "lr_in_ip_routing" lr0flows |
>> ovn_strip_lflows], [0], [dnl
>> ])
>> AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed
>> 's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl
>> table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1),
>> action=(drop;)
>> - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; next;)
>> - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; next;)
>> + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; reg9[[10]] = 1; next;)
>> + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; reg9[[10]] = 1; next;)
>> table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]]
>> == 0), action=(next;)
>> ])
>>
>> @@ -7174,6 +7179,16 @@ AT_CHECK([grep -e "lr_in_arp_resolve.*ecmp"
>> lr0flows | ovn_strip_lflows], [0], [
>> table=??(lr_in_arp_resolve ), priority=200 ,
>> match=(ct_mark.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 =
>> ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;)
>> ])
>>
>> +AT_CHECK([grep -e "lr_in_ecmp_stateful_egr" lr0flows | ovn_strip_lflows],
>> [0], [dnl
>> + table=??(lr_in_ecmp_stateful_egr), priority=0 , match=(1),
>> action=(output;)
>> + table=??(lr_in_ecmp_stateful_egr), priority=100 , match=(reg9[[10]] ==
>> 1 && ip && outport == "lr0-public"), action=(ct_commit {
>> ct_label.ecmp_reply_eth = eth.dst; ct_mark.ecmp_reply_port = 1;}; output;)
>> +])
>> +
>> +# Check that reroute policies reset ecmp-symmetric-reply behavior when
>> hit.
>> +check ovn-nbctl --wait=sb \
>> + -- lr-policy-add lr0 20 "ip4.src == 10.0.0.4" reroute 192.168.0.10 \
>> + -- lr-policy-add lr0 10 "ip4.src == 10.0.0.3" reroute
>> 192.168.0.10,192.168.0.20
>> +
>> # add ecmp route with wrong nexthop
>> check ovn-nbctl --wait=sb --ecmp-symmetric-reply lr-route-add lr0 1.0.0.1
>> 192.168.1.20
>> check_row_count ECMP_Nexthop 2
>> @@ -7191,11 +7206,16 @@ AT_CHECK([grep -w "lr_in_ip_routing" lr0flows |
>> ovn_strip_lflows], [0], [dnl
>> ])
>> AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed
>> 's/192\.168\.0\..0/192.168.0.??/' | ovn_strip_lflows], [0], [dnl
>> table=??(lr_in_ip_routing_ecmp), priority=0 , match=(1),
>> action=(drop;)
>> - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; next;)
>> - table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; next;)
>> + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 1), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; reg9[[10]] = 1; next;)
>> + table=??(lr_in_ip_routing_ecmp), priority=100 , match=(reg8[[0..15]]
>> == 1 && reg8[[16..31]] == 2), action=(reg0 = 192.168.0.??; reg5 =
>> 192.168.0.1; eth.src = 00:00:20:20:12:13; outport = "lr0-public"; reg9[[9]]
>> = 1; reg9[[10]] = 1; next;)
>> table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]]
>> == 0), action=(next;)
>> ])
>>
>> +AT_CHECK([grep -e "lr_in_ecmp_stateful_egr" lr0flows | ovn_strip_lflows],
>> [0], [dnl
>> + table=??(lr_in_ecmp_stateful_egr), priority=0 , match=(1),
>> action=(output;)
>> + table=??(lr_in_ecmp_stateful_egr), priority=100 , match=(reg9[[10]] ==
>> 1 && ip && outport == "lr0-public"), action=(ct_commit {
>> ct_label.ecmp_reply_eth = eth.dst; ct_mark.ecmp_reply_port = 1;}; output;)
>> +])
>> +
>> check ovn-nbctl lr-route-del lr0
>> wait_row_count nb:Logical_Router_Static_Route 0
>> check_row_count ECMP_Nexthop 0
>> @@ -7241,6 +7261,11 @@ AT_CHECK([grep -e "(lr_in_ip_routing ).*3.3.0.0"
>> lr0flows | sed 's/table=../ta
>> table=??(lr_in_ip_routing ), priority=133 , match=(reg7 == 0 &&
>> ip4.dst == 3.3.0.0/16 && udp), action=(ip.ttl--; flags.loopback = 1;
>> reg8[[0..15]] = 1; reg8[[16..31]] = select(values=(1, 2);
>> hash_fields="ip_dst,ip_proto,ip_src,udp_dst,udp_src");)
>> ])
>>
>> +AT_CHECK([grep -e "lr_in_ecmp_stateful_egr" lr0flows | ovn_strip_lflows],
>> [0], [dnl
>> + table=??(lr_in_ecmp_stateful_egr), priority=0 , match=(1),
>> action=(output;)
>> + table=??(lr_in_ecmp_stateful_egr), priority=100 , match=(reg9[[10]] ==
>> 1 && ip && outport == "lr0-public"), action=(ct_commit {
>> ct_label.ecmp_reply_eth = eth.dst; ct_mark.ecmp_reply_port = 1;}; output;)
>> +])
>> +
>> OVN_CLEANUP_NORTHD
>> AT_CLEANUP
>> ])
>> @@ -7289,11 +7314,11 @@ AT_CHECK([grep -e "lr_in_arp_resolve" lr0flows |
>> ovn_strip_lflows], [0], [dnl
>> ])
>>
>> AT_CHECK([grep -e "lr_in_arp_request" lr0flows | ovn_strip_lflows], [0],
>> [dnl
>> - table=??(lr_in_arp_request ), priority=0 , match=(1),
>> action=(output;)
>> - table=??(lr_in_arp_request ), priority=100 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0), action=(nd_ns { nd.target = xxreg0;
>> output; }; output;)
>> - table=??(lr_in_arp_request ), priority=100 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 1), action=(arp { eth.dst =
>> ff:ff:ff:ff:ff:ff; arp.spa = reg5; arp.tpa = reg0; arp.op = 1; output; };
>> output;)
>> - table=??(lr_in_arp_request ), priority=200 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::10),
>> action=(nd_ns { eth.dst = 33:33:ff:00:00:10; ip6.dst = ff02::1:ff00:10;
>> nd.target = 2001:db8::10; output; }; output;)
>> - table=??(lr_in_arp_request ), priority=200 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::20),
>> action=(nd_ns { eth.dst = 33:33:ff:00:00:20; ip6.dst = ff02::1:ff00:20;
>> nd.target = 2001:db8::20; output; }; output;)
>> + table=??(lr_in_arp_request ), priority=0 , match=(1), action=(next;)
>> + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0), action=(nd_ns { nd.target = xxreg0;
>> output; }; next;)
>> + table=??(lr_in_arp_request ), priority=100 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 1), action=(arp { eth.dst =
>> ff:ff:ff:ff:ff:ff; arp.spa = reg5; arp.tpa = reg0; arp.op = 1; output; };
>> next;)
>> + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::10),
>> action=(nd_ns { eth.dst = 33:33:ff:00:00:10; ip6.dst = ff02::1:ff00:10;
>> nd.target = 2001:db8::10; output; }; next;)
>> + table=??(lr_in_arp_request ), priority=200 , match=(eth.dst ==
>> 00:00:00:00:00:00 && reg9[[9]] == 0 && xxreg0 == 2001:db8::20),
>> action=(nd_ns { eth.dst = 33:33:ff:00:00:20; ip6.dst = ff02::1:ff00:20;
>> nd.target = 2001:db8::20; output; }; next;)
>> ])
>>
>> OVN_CLEANUP_NORTHD
>> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
>> index 82b7e7db5b..c732af9b91 100644
>> --- a/tests/system-ovn.at
>> +++ b/tests/system-ovn.at
>> @@ -6679,7 +6679,8 @@ NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2
>> 172.16.0.1 | FORMAT_PING], \
>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x401020500000000 |
>> FORMAT_CT(172.16.0.1) | \
>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/' |
>> sed -e 's/mark=[[0-9]]*/mark=<cleared>/' | sort], [0], [dnl
>>
>> -tcp,orig=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020500000000,protoinfo=(state=<cleared>)
>>
>> +icmp,orig=(src=10.0.0.2,dst=172.16.0.1,id=<cleared>,type=8,code=0),reply=(src=172.16.0.1,dst=10.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared>,mark=<cleared>,labels=0x401020500000000
>>
>> +tcp,orig=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020500000000,protoinfo=(state=<cleared>)
>> ])
>>
>> # Now remove one ECMP route and check that traffic is still being
>> conntracked.
>> @@ -6695,7 +6696,8 @@ NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2
>> 172.16.0.1 | FORMAT_PING], \
>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x401020500000000 |
>> FORMAT_CT(172.16.0.1) | \
>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/' |
>> sed -e 's/mark=[[0-9]]*/mark=<cleared>/' | sort], [0], [dnl
>>
>> -tcp,orig=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020500000000,protoinfo=(state=<cleared>)
>>
>> +icmp,orig=(src=10.0.0.2,dst=172.16.0.1,id=<cleared>,type=8,code=0),reply=(src=172.16.0.1,dst=10.0.0.2,id=<cleared>,type=0,code=0),zone=<cleared>,mark=<cleared>,labels=0x401020500000000
>>
>> +tcp,orig=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),reply=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020500000000,protoinfo=(state=<cleared>)
>> ])
>>
>> OVN_CLEANUP_CONTROLLER([hv1])
>> @@ -6904,7 +6906,8 @@ NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2
>> fd07::1 | FORMAT_PING], \
>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x1001020400000000 |
>> FORMAT_CT(fd07::1) | \
>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/' |
>> sed -e 's/mark=[[0-9]]*/mark=<cleared>/' | sort], [0], [dnl
>>
>> -tcp,orig=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>)
>>
>> +icmpv6,orig=(src=fd01::2,dst=fd07::1,id=<cleared>,type=128,code=0),reply=(src=fd07::1,dst=fd01::2,id=<cleared>,type=129,code=0),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000
>>
>> +tcp,orig=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),reply=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>)
>> ])
>>
>> # Now remove one ECMP route and check that traffic is still being
>> conntracked.
>> @@ -6920,7 +6923,8 @@ NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2
>> fd07::1 | FORMAT_PING], \
>> AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x1001020400000000 |
>> FORMAT_CT(fd07::1) | \
>> sed -e 's/zone=[[0-9]]*/zone=<cleared>/' |
>> sed -e 's/mark=[[0-9]]*/mark=<cleared>/' | sort], [0], [dnl
>>
>> -tcp,orig=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>)
>>
>> +icmpv6,orig=(src=fd01::2,dst=fd07::1,id=<cleared>,type=128,code=0),reply=(src=fd07::1,dst=fd01::2,id=<cleared>,type=129,code=0),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000
>>
>> +tcp,orig=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),reply=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>)
>> ])
>>
>> OVN_CLEANUP_CONTROLLER([hv1])
>> --
>> 2.52.0
>>
>> _______________________________________________
>> dev mailing list
>> [email protected]
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>>
> With that addressed:
> Acked-by: Ales Musil <[email protected]>
>
I fixed up the two minor things above and applied the patch to main,
25.09 and 25.03.
Thanks,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev