@@ -1287,6 +1287,12 @@ lsp_is_localnet(const struct nbrec_logical_switch_port *nbsp)
return !strcmp(nbsp->type, "localnet");
}
+static bool
+lsp_is_localport(const struct nbrec_logical_switch_port *nbsp)
+{
+ return !strcmp(nbsp->type, "localport");
+}
+
static bool
lsp_is_vtep(const struct nbrec_logical_switch_port *nbsp)
{
@@ -4689,8 +4695,8 @@ destroy_northd_tracked_data(struct northd_data *nd)
static bool
lsp_can_be_inc_processed(const struct nbrec_logical_switch_port *nbsp)
{
- /* Support only normal VIF and remote ports for now. */
- if (nbsp->type[0] && !lsp_is_remote(nbsp)) {
+ /* Support only normal VIF, remote and localport ports for now. */
+ if (nbsp->type[0] && !lsp_is_remote(nbsp) && !lsp_is_localport(nbsp)) {
return false;
}
@@ -10835,7 +10841,7 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op,
*/
if (check_lsp_is_up &&
!lsp_is_up(op->nbsp) && !lsp_is_router(op->nbsp) &&
- strcmp(op->nbsp->type, "localport")) {
+ !lsp_is_localport(op->nbsp)) {
return;
}
@@ -11946,6 +11946,40 @@ check_recompute_counter 0 0 0 0 0 0
CHECK_NO_CHANGE_AFTER_RECOMPUTE(1)
+dnl Localports should be incrementally processed
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb lsp-add ls0 lp0 \
+ -- lsp-set-type lp0 localport \
+ -- lsp-set-addresses lp0 "aa:aa:aa:00:00:30 192.168.0.30"
+check_recompute_counter 0 0 0 0 0 0
+
+# A localport gets an ARP responder reply flow regardless of its "up" state.
+AT_CHECK([ovn-sbctl dump-flows ls0 | grep ls_in_arp_rsp | \
+ grep 'arp.tpa == 192.168.0.30' | grep -c 'arp.op = 2'], [0], [1
+])
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb \
+ lsp-set-addresses lp0 "aa:aa:aa:00:00:31 192.168.0.31"
+check_recompute_counter 0 0 0 0 0 0
+
+AT_CHECK([ovn-sbctl dump-flows ls0 | grep ls_in_arp_rsp | \
+ grep 'arp.tpa == 192.168.0.31' | grep -c 'arp.op = 2'], [0], [1
+])
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb lsp-del lp0
+check_recompute_counter 0 0 0 0 0 0
+
+AT_CHECK([ovn-sbctl dump-flows ls0 | grep ls_in_arp_rsp | \
+ grep -c 'arp.tpa == 192.168.0.30'], [1], [0
+])
+AT_CHECK([ovn-sbctl dump-flows ls0 | grep ls_in_arp_rsp | \
+ grep -c 'arp.tpa == 192.168.0.31'], [1], [0
+])
+
+CHECK_NO_CHANGE_AFTER_RECOMPUTE(1)
+
check ovn-nbctl --wait=hv ls-del ls0
OVN_CLEANUP([hv1])
Commit b337750e45be ("northd: Incremental processing of VIF changes in 'northd' node.") skipped non-VIF ports from processing, and 860d5e4138ed ("northd: Enable incremental processing for remote ports.") later observed that "remote" ports are almost identical to VIF ports. The same holds for ports of type "localport": every flow whose content differs from a plain VIF (most notably the ARP/ND responder flows, which a localport gets regardless of its "up" state) is owned by the port's own lflow_ref and is regenerated by the existing per-port incremental path, and a localport mutates no aggregate od->* state that a VIF would not. Enable that processing path for localport ports. Also use the new lsp_is_localport() helper in build_lswitch_arp_nd_responder_known_ips(), which so far open coded the same type check. Add a test covering incremental create/update/delete of a localport, including that its ARP responder reply flow is present regardless of the "up" state and removed on deletion. Assisted-by: Claude Opus 4.8, Claude Code Signed-off-by: Lucas Vargas Dias <lucas.vdias@magalu.cloud> --- northd/northd.c | 12 +++++++++--- tests/ovn-northd.at | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-)