Hi Jacob Thanks for the review.
On Fri, Aug 21, 2026 at 7:54 PM Jacob Tanenbaum <[email protected]> wrote: > > > On Fri, Aug 21, 2026 at 3:30 AM Xavier Simonart via dev < > [email protected]> wrote: > >> Since [1] we do not learn routes with auto-generated link-local next-hops. >> However, routes with auto-generated lla next hops were still created and >> deleted from ovn-ic-sb, causing high cpu usage on ovn-ic and ovn-ic-sb, >> as well as high traffic between AZs and ovn-ic-sb. >> >> Fix this by skipping route advertisement when the derived next-hop is >> an EUI-64 LLA (i.e. fe80::/64). >> Non-EUI-64 link-local addresses (e.g. fe80:10::1/64), are intentionally >> left unfiltered and continue to be advertised and learned normally. >> >> [1] cb0e2b3f44da ("ovn-ic: do not learn routes with link-local next-hops") >> >> Reported-at: https://issues.redhat.com/browse/FDP-2000 >> Assisted-by: Claude Sonnet 4.6, OpenCode >> Signed-off-by: Xavier Simonart <[email protected]> >> >> --- >> v2: - Update test based on comment from Roberto in v1, adding non-EUI-64 >> addresses. >> - Check for NULL lrp in VLOG. >> - Change IPv6 addresses used (per Claude's review). >> --- >> ic/ovn-ic.c | 14 +++++++++ >> tests/ovn-ic.at | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 98 insertions(+) >> >> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c >> index f7cc41748..7eac87259 100644 >> --- a/ic/ovn-ic.c >> +++ b/ic/ovn-ic.c >> @@ -2142,6 +2142,20 @@ add_network_to_routes_ad(struct hmap *routes_ad, >> const char *network, >> return; >> } >> >> + if (in6_is_lla(&nexthop)) { >> > > The filter is only added here but add_static_to_routes_ad() and > add_lb_vip_to_routes_ad() also call get_nexthop_from_lport_addresses() > should the same filter be applied to them as well? > You are right; great catch! I'll fix it v3. > > If so it might be it cleaner to add the check once, in either > get_nexthop_from_lport_addresses(), returning false when the result is an > LLA, or in add_to_routes_ad()? > > >> + if (VLOG_IS_DBG_ENABLED()) { >> + struct ds msg = DS_EMPTY_INITIALIZER; >> + ds_put_format(&msg, "Route ad: skip lla nexthop"); >> + if (nb_lrp) { >> + ds_put_format(&msg, " of lrp %s", nb_lrp->name); >> + } >> + ds_put_format(&msg, "."); >> + VLOG_DBG("%s", ds_cstr(&msg)); >> + ds_destroy(&msg); >> + } >> + return; >> + } >> + >> if (VLOG_IS_DBG_ENABLED()) { >> struct ds msg = DS_EMPTY_INITIALIZER; >> >> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at >> index 1435a19a3..d7d9ad676 100644 >> --- a/tests/ovn-ic.at >> +++ b/tests/ovn-ic.at >> @@ -5628,7 +5628,91 @@ OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl >> lr-route-list lr11 | grep 192.168 | >> ]) >> >> OVN_CLEANUP_IC([az1], [az2]) >> +AT_CLEANUP >> +]) >> + >> +OVN_FOR_EACH_NORTHD([ >> +AT_SETUP([interconnection - LLA]) >> +AT_KEYWORDS([LLA]) >> +# Logical network: >> >> +#┌──────────────────────────────────────────────────┬────────────────────────────────────────────────────┐ >> +#│ AZ1 │ >> AZ2 │ >> >> +#├──────────────────────────────────────────────────┼────────────────────────────────────────────────────┤ >> +#│ LS11-LR11 (fd11::254) - LR11 - (2001:db8::1) ── TS1 ── (2001:db8::2) >> - LR12 - (fd12::254) - LR12-LS12 │ >> +#│ LS21-LR21 (fd21::254) - LR21 - (fe80:10::1) ─────┼──── (fe80:10::2) >> - LR22 - (fd22::254) - LR22-LS22 │ >> >> +#└──────────────────────────────────────────────────┴────────────────────────────────────────────────────┘ >> +# LR11/LR12: trigger EUI-64 LLA filtering: they have a global IPv6 >> address on the TS port that gets removed, >> +# causing their stub subnet (fd1x::/64) to fall back to an >> EUI-64 LLA nexthop that should be suppressed. >> +# LR21/LR22: verify non-EUI-64 LLA nexthops (fe80:10::x) work correctly; >> their subnets (fd2x::/64) are advertised and learned. >> >> +ovn_init_ic_db >> +net_add n1 >> + >> +for i in 1 2; do >> + ovn_start az$i >> + sim_add hv$i >> + as hv$i >> + check ovs-vsctl add-br br-phys >> + ovn_az_attach az$i n1 br-phys 192.168.$i.1 16 >> + ovn_as az$i >> + check ovs-vsctl set open . external-ids:ovn-is-interconn=true >> + check ovn-nbctl set nb_global . options:ic-route-learn=true >> + check ovn-nbctl set nb_global . options:ic-route-adv=true >> +done >> + >> +check ovn-ic-nbctl ts-add ts1 >> +check ovn_as az1 ovn-nbctl wait-until logical_switch ts1 >> +check ovn_as az2 ovn-nbctl wait-until logical_switch ts1 >> + >> +for i in 1 2; do >> + ovn_as az$i >> + check ovn-nbctl lr-add lr1$i \ >> + -- lrp-add lr1$i lr1$i-ts1 00:aa:aa:aa:aa:1$i >> 2001:db8::$i/64 \ >> + -- lrp-add lr1$i lr1$i-ls1$i 00:00:00:00:0$i:fe >> fd1$i::254/64 \ >> + -- lsp-add-router-port ts1 ts1-lr1$i lr1$i-ts1 >> + check ovn-nbctl lr-add lr2$i \ >> + -- lrp-add lr2$i lr2$i-ts1 aa:aa:aa:aa:aa:2$i >> fe80:10::$i/64 \ >> + -- lsp-add-router-port ts1 ts1-lr2$i lr2$i-ts1 >> + >> + check ovn-nbctl --wait=sb lrp-add lr2$i lr2$i-ls2$i >> 00:00:00:00:0$i:0$i fd2$i::254/64 >> + >> +done >> + >> +wait_for_ports_up >> +check ovn-ic-nbctl --wait=sb sync >> +check ovn_as az1 ovn-nbctl --wait=hv sync >> +check ovn_as az2 ovn-nbctl --wait=hv sync >> + >> +# Non-EUI-64 LLA nexthops must be advertised to IC-SB and learned >> normally. >> +OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep learned | >> \ >> + grep fd22::]) >> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr21 | awk '/learned/{print >> $1, $2}'], [0], [dnl >> +fd22::/64 fe80:10::2 >> +]) >> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr22 | grep learned | >> \ >> + grep fd21::]) >> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr22 | awk '/learned/{print >> $1, $2}'], [0], [dnl >> +fd21::/64 fe80:10::1 >> +]) >> > > > I am pretty sure the following code with static routes will expose the > issue. Unless I am misunderstanding. > > +# Add a static route on lr11. After removing the global IPv6 address, > +# add_static_to_routes_ad() will use the EUI-64 LLA as nexthop because > +# it lacks the in6_is_lla() filter that add_network_to_routes_ad() has. > +ovn_as az1 check ovn-nbctl lr-route-add lr11 fd99::/64 2001:db8::2 > +check ovn-ic-nbctl --wait=sb sync > +OVS_WAIT_UNTIL([ovn-ic-sbctl list route | grep fd99]) > You're right, and this (as well as a similar lb test) fails. > > > > > >> + >> +ovn_as az1 check ovn-nbctl remove logical_router_port lr11-ts1 networks >> "2001\:db8\:\:1/64" >> +check ovn-ic-nbctl --wait=sb sync >> + >> +# ic-sb route should not contain lla next hops. >> +# Such routes used to be created and deleted in ic-sb. >> +# Do not use OVS_WAIT_WHILE or WAIT_UNTIL as the wrong (lla) route >> appears and disappears. >> +for i in $(seq 1 50); do >> + AT_CHECK([ovn-ic-sbctl list route | grep "fe80:" | sort], [0], [dnl >> +nexthop : "fe80:10::1" >> +nexthop : "fe80:10::2" >> +]) >> +done >> + >> +OVN_CLEANUP_SBOX([hv1]) >> + >> +OVN_CLEANUP_SBOX([hv2]) >> + >> +OVN_CLEANUP_IC([az1], [az2]) >> > > Nit: The blank lines are not necessary. > Will fix in v3. > > >> AT_CLEANUP >> ]) >> >> -- >> 2.47.1 >> >> _______________________________________________ >> dev mailing list >> [email protected] >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> >> Thanks Xavier _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
