Neigh suppression#588
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
8f47020 to
fab7eb3
Compare
fab7eb3 to
96d65cc
Compare
24acc09 to
3fdc6fd
Compare
032876e to
becd129
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
frr/rt_grout.c (1)
1148-1153: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winCarry
vrf_idin the key-based remote neighbor install/delete.Both helpers leave
req->nh.vrf_idunset, defaulting it toGR_VRF_ID_UNDEF. Because bridge neighbor suppression performs VRF-scoped lookups, these entries won't be matched correctly within the bridge's actual VRF.
frr/rt_grout.c#L1148-L1153: Assignreq->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx));when building the add request.frr/rt_grout.c#L1191-L1194: Assignreq->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx));when building the delete request.🐛 Proposed fixes
For
neigh_install_nexthop:req->exist_ok = true; req->nh.type = GR_NH_T_L3; req->nh.origin = zebra2origin(dplane_ctx_get_type(ctx)); req->nh.iface_id = iface_id; + req->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)); l3 = (struct gr_nexthop_info_l3 *)req->nh.info;For
neigh_delete_nexthop:req->missing_ok = true; req->nh.type = GR_NH_T_L3; req->nh.iface_id = iface_id; + req->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)); l3 = (struct gr_nexthop_info_l3 *)req->nh.info;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frr/rt_grout.c` around lines 1148 - 1153, Set req->nh.vrf_id using vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)) in both neigh_install_nexthop’s add request and neigh_delete_nexthop’s delete request, alongside the existing nexthop fields, so both key-based remote neighbor operations carry the active VRF.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@modules/l2/datapath/bridge_input.c`:
- Around line 95-102: Update the edge normalization at the next label in the
bridge input flow so both FLOOD and NEIGH_SUPPRESS outcomes are converted to
FLOOD_DISABLED when GR_BRIDGE_F_FLOOD is unset. Preserve the existing edge
selection and allow either edge to reach its normal handler when flooding is
enabled.
In `@smoke/evpn_l2l3vni_frr_test.sh`:
- Around line 222-225: Update each failure branch invoking fail in
smoke/evpn_l2l3vni_frr_test.sh at lines 222-225, 232-235, 243-246, and 256, and
smoke/evpn_l3vpn_vxlan6_frr_test.sh at lines 206-209, 216-219, 231, and 237.
Explicitly handle the nonzero result from fail within the surrounding loop, such
as breaking the loop or returning an appropriate status, so set -e does not
terminate the script before controlled cleanup or flow completion.
---
Duplicate comments:
In `@frr/rt_grout.c`:
- Around line 1148-1153: Set req->nh.vrf_id using
vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)) in both neigh_install_nexthop’s add
request and neigh_delete_nexthop’s delete request, alongside the existing
nexthop fields, so both key-based remote neighbor operations carry the active
VRF.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 877954ff-d2a3-4ed5-86c7-6155afd6e8f8
⛔ Files ignored due to path filters (1)
docs/graph.svgis excluded by!**/*.svg
📒 Files selected for processing (29)
.clang-format.github/workflows/check.ymlREADME.mdapi/gr_api.hapi/gr_macro.hfrr/rt_grout.cmodules/infra/api/gr_infra.hmodules/infra/api/gr_nexthop.hmodules/infra/api/nexthop.cmodules/infra/cli/cli_iface.hmodules/infra/cli/iface.cmodules/infra/cli/nexthop.cmodules/infra/control/nexthop.cmodules/ip/control/nexthop.cmodules/ip/datapath/arp_input_reply.cmodules/ip6/control/nexthop.cmodules/ip6/datapath/ndp_na_input.cmodules/l2/api/gr_l2.hmodules/l2/cli/bridge.cmodules/l2/cli/fdb.cmodules/l2/control/bridge.cmodules/l2/datapath/bridge_input.cmodules/l2/datapath/bridge_neigh_suppress.cmodules/l2/datapath/meson.buildsmoke/bridge_neigh_suppress_test.shsmoke/evpn_l2l3vni_frr_test.shsmoke/evpn_l3vpn_frr_test.shsmoke/evpn_l3vpn_vxlan6_frr_test.shsmoke/evpn_neigh_suppress_frr_test.sh
🚧 Files skipped from review as they are similar to previous changes (13)
- .clang-format
- modules/l2/datapath/meson.build
- modules/l2/cli/fdb.c
- modules/infra/cli/iface.c
- api/gr_macro.h
- modules/l2/api/gr_l2.h
- modules/ip/datapath/arp_input_reply.c
- modules/ip6/datapath/ndp_na_input.c
- modules/l2/datapath/bridge_neigh_suppress.c
- modules/infra/api/nexthop.c
- modules/infra/cli/cli_iface.h
- modules/infra/control/nexthop.c
- modules/infra/cli/nexthop.c
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
♻️ Duplicate comments (1)
frr/rt_grout.c (1)
1148-1153: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winCarry
vrf_idin the key-based remote neighbor install/delete.Both helpers leave
req->nh.vrf_idunset, defaulting it toGR_VRF_ID_UNDEF. Because bridge neighbor suppression performs VRF-scoped lookups, these entries won't be matched correctly within the bridge's actual VRF.
frr/rt_grout.c#L1148-L1153: Assignreq->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx));when building the add request.frr/rt_grout.c#L1191-L1194: Assignreq->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx));when building the delete request.🐛 Proposed fixes
For
neigh_install_nexthop:req->exist_ok = true; req->nh.type = GR_NH_T_L3; req->nh.origin = zebra2origin(dplane_ctx_get_type(ctx)); req->nh.iface_id = iface_id; + req->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)); l3 = (struct gr_nexthop_info_l3 *)req->nh.info;For
neigh_delete_nexthop:req->missing_ok = true; req->nh.type = GR_NH_T_L3; req->nh.iface_id = iface_id; + req->nh.vrf_id = vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)); l3 = (struct gr_nexthop_info_l3 *)req->nh.info;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frr/rt_grout.c` around lines 1148 - 1153, Set req->nh.vrf_id using vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)) in both neigh_install_nexthop’s add request and neigh_delete_nexthop’s delete request, alongside the existing nexthop fields, so both key-based remote neighbor operations carry the active VRF.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@modules/l2/datapath/bridge_input.c`:
- Around line 95-102: Update the edge normalization at the next label in the
bridge input flow so both FLOOD and NEIGH_SUPPRESS outcomes are converted to
FLOOD_DISABLED when GR_BRIDGE_F_FLOOD is unset. Preserve the existing edge
selection and allow either edge to reach its normal handler when flooding is
enabled.
In `@smoke/evpn_l2l3vni_frr_test.sh`:
- Around line 222-225: Update each failure branch invoking fail in
smoke/evpn_l2l3vni_frr_test.sh at lines 222-225, 232-235, 243-246, and 256, and
smoke/evpn_l3vpn_vxlan6_frr_test.sh at lines 206-209, 216-219, 231, and 237.
Explicitly handle the nonzero result from fail within the surrounding loop, such
as breaking the loop or returning an appropriate status, so set -e does not
terminate the script before controlled cleanup or flow completion.
---
Duplicate comments:
In `@frr/rt_grout.c`:
- Around line 1148-1153: Set req->nh.vrf_id using
vrf_frr_to_grout(dplane_ctx_get_vrf(ctx)) in both neigh_install_nexthop’s add
request and neigh_delete_nexthop’s delete request, alongside the existing
nexthop fields, so both key-based remote neighbor operations carry the active
VRF.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 877954ff-d2a3-4ed5-86c7-6155afd6e8f8
⛔ Files ignored due to path filters (1)
docs/graph.svgis excluded by!**/*.svg
📒 Files selected for processing (29)
.clang-format.github/workflows/check.ymlREADME.mdapi/gr_api.hapi/gr_macro.hfrr/rt_grout.cmodules/infra/api/gr_infra.hmodules/infra/api/gr_nexthop.hmodules/infra/api/nexthop.cmodules/infra/cli/cli_iface.hmodules/infra/cli/iface.cmodules/infra/cli/nexthop.cmodules/infra/control/nexthop.cmodules/ip/control/nexthop.cmodules/ip/datapath/arp_input_reply.cmodules/ip6/control/nexthop.cmodules/ip6/datapath/ndp_na_input.cmodules/l2/api/gr_l2.hmodules/l2/cli/bridge.cmodules/l2/cli/fdb.cmodules/l2/control/bridge.cmodules/l2/datapath/bridge_input.cmodules/l2/datapath/bridge_neigh_suppress.cmodules/l2/datapath/meson.buildsmoke/bridge_neigh_suppress_test.shsmoke/evpn_l2l3vni_frr_test.shsmoke/evpn_l3vpn_frr_test.shsmoke/evpn_l3vpn_vxlan6_frr_test.shsmoke/evpn_neigh_suppress_frr_test.sh
🚧 Files skipped from review as they are similar to previous changes (13)
- .clang-format
- modules/l2/datapath/meson.build
- modules/l2/cli/fdb.c
- modules/infra/cli/iface.c
- api/gr_macro.h
- modules/l2/api/gr_l2.h
- modules/ip/datapath/arp_input_reply.c
- modules/ip6/datapath/ndp_na_input.c
- modules/l2/datapath/bridge_neigh_suppress.c
- modules/infra/api/nexthop.c
- modules/infra/cli/cli_iface.h
- modules/infra/control/nexthop.c
- modules/infra/cli/nexthop.c
🛑 Comments failed to post (2)
modules/l2/datapath/bridge_input.c (1)
95-102: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash # Description: Verify if bridge_flood.c enforces GR_BRIDGE_F_FLOOD rg "GR_BRIDGE_F_FLOOD" modules/l2/datapath/bridge_flood.c || echo "GR_BRIDGE_F_FLOOD check missing in bridge_flood.c"Repository: DPDK/grout
Length of output: 198
🏁 Script executed:
#!/bin/bash set -euo pipefail # Map the relevant files and inspect the control flow around the edges. git ls-files modules/l2/datapath/bridge_input.c modules/l2/datapath/bridge_flood.c modules/l2/datapath/bridge_neigh_suppress.c echo echo "== bridge_input.c ==" ast-grep outline modules/l2/datapath/bridge_input.c --view expanded || true echo sed -n '1,180p' modules/l2/datapath/bridge_input.c echo echo "== bridge_neigh_suppress.c ==" ast-grep outline modules/l2/datapath/bridge_neigh_suppress.c --view expanded || true echo sed -n '1,220p' modules/l2/datapath/bridge_neigh_suppress.c echo echo "== bridge_flood.c ==" ast-grep outline modules/l2/datapath/bridge_flood.c --view expanded || true echo sed -n '1,220p' modules/l2/datapath/bridge_flood.cRepository: DPDK/grout
Length of output: 13104
🏁 Script executed:
#!/bin/bash set -euo pipefail # Check whether the flood edge is used anywhere else and whether the disable flag is enforced centrally. rg -n "FLOOD_DISABLED|GR_BRIDGE_F_FLOOD|NEIGH_SUPPRESS|bridge_flood|bridge_neigh_suppress" modules/l2/datapathRepository: DPDK/grout
Length of output: 1823
🏁 Script executed:
#!/bin/bash set -euo pipefail # Read only the relevant line ranges if the files are large. for f in modules/l2/datapath/bridge_input.c modules/l2/datapath/bridge_neigh_suppress.c modules/l2/datapath/bridge_flood.c; do echo "===== $f =====" wc -l "$f" doneRepository: DPDK/grout
Length of output: 424
NEIGH_SUPPRESSstill bypassesGR_BRIDGE_F_FLOODmodules/l2/datapath/bridge_input.c:95-102When
GR_BRIDGE_F_NEIGH_SUPPRESSis enabled, any framebridge_neigh_suppresssends to itsFLOODedge reachesbridge_flooddirectly, and that path never applies the flood-disable flag. Flood-disabled bridges can still forward those frames; route that fallback toFLOOD_DISABLEDinstead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@modules/l2/datapath/bridge_input.c` around lines 95 - 102, Update the edge normalization at the next label in the bridge input flow so both FLOOD and NEIGH_SUPPRESS outcomes are converted to FLOOD_DISABLED when GR_BRIDGE_F_FLOOD is unset. Preserve the existing edge selection and allow either edge to reach its normal handler when flooding is enabled.smoke/evpn_l2l3vni_frr_test.sh (1)
222-225: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Avoid
if ... failpatterns underset -eto ensure controlled flow.Based on learnings, calling
fail(which returns 1) inside anifblock or&&chain underset -ecauses the shell to exit immediately at the statement itself, terminating the script instead of allowing for controlled flow or cleanup.
Refactor these calls to explicitly handle the failure by breaking out of the loop or returning a status (e.g.,fail "..." || breakorfail "..." || exit 1) to prevent the implicit shell termination trap.
smoke/evpn_l2l3vni_frr_test.sh#L222-L225: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l2l3vni_frr_test.sh#L232-L235: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l2l3vni_frr_test.sh#L243-L246: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l2l3vni_frr_test.sh#L256-L256: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l3vpn_vxlan6_frr_test.sh#L206-L209: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l3vpn_vxlan6_frr_test.sh#L216-L219: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l3vpn_vxlan6_frr_test.sh#L231-L231: Refactor to explicitly handle the failure (e.g.,fail "..." || break).smoke/evpn_l3vpn_vxlan6_frr_test.sh#L237-L237: Refactor to explicitly handle the failure (e.g.,fail "..." || break).📍 Affects 2 files
smoke/evpn_l2l3vni_frr_test.sh#L222-L225(this comment)smoke/evpn_l2l3vni_frr_test.sh#L232-L235smoke/evpn_l2l3vni_frr_test.sh#L243-L246smoke/evpn_l2l3vni_frr_test.sh#L256-L256smoke/evpn_l3vpn_vxlan6_frr_test.sh#L206-L209smoke/evpn_l3vpn_vxlan6_frr_test.sh#L216-L219smoke/evpn_l3vpn_vxlan6_frr_test.sh#L231-L231smoke/evpn_l3vpn_vxlan6_frr_test.sh#L237-L237🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@smoke/evpn_l2l3vni_frr_test.sh` around lines 222 - 225, Update each failure branch invoking fail in smoke/evpn_l2l3vni_frr_test.sh at lines 222-225, 232-235, 243-246, and 256, and smoke/evpn_l3vpn_vxlan6_frr_test.sh at lines 206-209, 216-219, 231, and 237. Explicitly handle the nonzero result from fail within the surrounding loop, such as breaking the loop or returning an appropriate status, so set -e does not terminate the script before controlled cleanup or flow completion.Source: Learnings
Some foreach macros were missing from the clang-format configuration file. Add them. The complete list was generated with the following command: git grep -i _foreach | sed -En 's/.*\<([a-z0-9_]*_foreach[a-z0-9_]*)\>.*/ - \1/Ip' | LC_ALL=C sort -u Signed-off-by: Robin Jarry <rjarry@redhat.com>
Add a per-interface flag to control neighbor snooping. Configurable via grcli: interface set port p0 neigh_snoop on/off. When GR_IFACE_F_NEIGH_SNOOP is enabled on an interface, forward unsolicited ARP replies and Neighbor Advertisements to the control plane instead of dropping them. The existing arp_probe_input_cb and ndp_probe_input_cb callbacks already handle creating nexthops for unknown senders, so no control plane changes are needed. This allows grout to passively learn IP+MAC bindings from ARP/NDP traffic observed on an interface, similar to Linux's arp_accept sysctl. Signed-off-by: Robin Jarry <rjarry@redhat.com>
ARP/NDP-learned nexthops were created with GR_NH_ORIGIN_INTERNAL which suppresses event generation. Add GR_NH_ORIGIN_NEIGH so these nexthops produce GR_EVENT_NEXTHOP_NEW and GR_EVENT_NEXTHOP_UPDATE events that the FRR plugin can receive and translate into neighbor entries for zebra. The associated host routes (/32, /128) remain GR_NH_ORIGIN_INTERNAL since they are internal plumbing and should not be visible to FRR. The neighbor are not synced yet in zebra. This will be done in the next commit. Signed-off-by: Robin Jarry <rjarry@redhat.com>
Change GR_NH_DEL to accept a full struct gr_nexthop instead of just an
ID. The handler uses nexthop_lookup() which first tries the ID if
specified or falls back to the type-specific key-based lookup (e.g.
vrf+addr for L3). This will allow the FRR plugin to delete remote
nexthops installed from EVPN neighbor entries without tracking their
auto-allocated IDs.
The nexthop type ids must be changed to avoid an error when deleting
a nexthop from its ID which has already been deleted indirectly:
ZEBRA: GROUT: grout_del_nexthop: nh_id 16
ERROR: AddressSanitizer: heap-buffer-overflow, READ of size 1
#0 in l3_lookup ../modules/infra/control/l3_nexthop.c:112
#1 in nexthop_lookup ../modules/infra/control/nexthop.c:306
DPDK#2 in nh_del ../modules/infra/api/nexthop.c:56
DPDK#3 in read_cb ../main/api.c:315
ZEBRA: GROUT: grout_client_send_recv: ERROR: GR_NH_DEL: Connection reset by peer
Indeed, since nh->type=0 is both the unset value and GR_NH_T_L3, the
nexthop_lookup() code calls l3_lookup() with nh->info pointing to
outside the API message buffer.
The only reliable to guard against this is to make GR_NH_T_L3 != 0.
Shift all enum values up by one and adjust code accordingly.
Signed-off-by: Robin Jarry <rjarry@redhat.com>
When a grout nexthop event arrives for an L3 nexthop with a resolved MAC, push a DPLANE_OP_NEIGH_INSTALL to zebra. On deletion, push DPLANE_OP_NEIGH_DELETE. This makes FRR aware of locally learned neighbors so it can advertise them as Type-2 MAC+IP routes via BGP EVPN. The notification is called before the nh_id check in grout_nexthop_change so that nexthops with nh_id=0 (auto-allocated by the ARP/NDP control plane) still produce neighbor entries in zebra even though they are not registered as zebra nexthop groups. Signed-off-by: Robin Jarry <rjarry@redhat.com>
When the dplane plugin receives DPLANE_OP_NEIGH_INSTALL for a remote MAC/IP (from EVPN Type-2 routes), install the entry as a grout nexthop with GR_NH_F_REMOTE. The iface_id is resolved from the FRR ifindex which points to the bridge (SVI) interface. This allows the bridge suppress node to look up the nexthop and answer ARP/ND requests locally. Both IPv4 and IPv6 neighbors are supported. The existing L3VNI RMAC caching for Type-5 routes is preserved alongside. Signed-off-by: Robin Jarry <rjarry@redhat.com>
Add GR_NH_FLUSH API request and grcli command to delete all nexthops matching a given origin. This is useful for clearing ARP/NDP-learned neighbors (origin neigh) which don't have IDs. Signed-off-by: Robin Jarry <rjarry@redhat.com>
All interface/nexthop flags use "presence" semantics. Having flags to signify the absence of a feature is confusing. Change the semantics of bridge flags to follow the same style. Bump the API version since it changes the semantics of the bridge flag values. Signed-off-by: Robin Jarry <rjarry@redhat.com>
This macro will be useful to format all flag masks. Signed-off-by: Robin Jarry <rjarry@redhat.com>
Use gr_flags_foreach to simplify formatting them. Signed-off-by: Robin Jarry <rjarry@redhat.com>
Add flag to allow enabling ARP/ND suppression on bridge interfaces. When a bridge has GR_BRIDGE_F_NEIGH_SUPPRESS enabled, broadcast and multicast traffic is routed through bridge_neigh_suppress before flooding. The node intercepts ARP requests and IPv6 Neighbor Solicitations, looks up the target IP in the bridge's VRF nexthop table, and replies on behalf of known remote hosts (GR_NH_F_REMOTE with a reachable MAC). For ARP, the Ethernet and ARP headers are rewritten in-place. For ND, the packet is rebuilt from scratch since a Neighbor Advertisement has a different structure than a Neighbor Solicitation. In both cases, the reply is sent directly to iface_output, bypassing eth_output to avoid double Ethernet header prepending. Packets that cannot be suppressed (unknown target, non-ARP/ND, or non-remote nexthop) fall through to bridge_flood as usual. Also add a "remote" flag to the nexthop add l3 CLI command so remote nexthops can be configured manually for testing. Signed-off-by: Robin Jarry <rjarry@redhat.com>
bridge_neigh_suppress_test verifies suppression with a manually configured remote nexthop: an ARP request for a known remote IP gets answered locally by grout with the correct MAC, and is not flooded to other bridge ports. evpn_neigh_suppress_frr_test verifies end-to-end suppression with FRR EVPN. The Linux peer has neigh_suppress on the VXLAN interface and advertise-svi-ip in BGP. Both sides have bridge SVIs and hosts with default routes through them. When hosts ARP for their gateways, VTEPs learn the IP+MAC bindings and advertise Type-2 MAC+IP routes. The remote VTEP installs the nexthops and the suppress node answers ARPs locally. Signed-off-by: Robin Jarry <rjarry@redhat.com>
becd129 to
cdec80f
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@modules/infra/api/gr_nexthop.h`:
- Around line 347-353: Update nh_flush and any equivalent nexthop iteration
loops to cache the result of nexthop_next(nh) before calling nexthop_decref(nh),
then continue from the cached pointer. Preserve filtering and
reference-decrement behavior while ensuring traversal remains complete after the
current nexthop is removed or freed.
In `@smoke/bridge_neigh_suppress_test.sh`:
- Around line 58-61: Prevent fail() from terminating the scripts unexpectedly
under set -e by updating both affected if blocks in
smoke/bridge_neigh_suppress_test.sh (lines 58-61 and 64-67) and all three
affected if blocks in smoke/evpn_neigh_suppress_frr_test.sh (lines 115-118,
129-132, and 172-175); disable errexit for each block and restore it afterward,
or use equivalent explicit error handling while preserving the existing failure
checks and cleanup flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: af05154d-f43a-4f61-869d-fd14dd3928d8
⛔ Files ignored due to path filters (1)
docs/graph.svgis excluded by!**/*.svg
📒 Files selected for processing (33)
.clang-format.github/workflows/check.ymlREADME.mdapi/gr_api.hapi/gr_macro.hcli/complete.ccli/exec.cfrr/rt_grout.cfrr/zebra_dplane_grout.cmodules/infra/api/gr_infra.hmodules/infra/api/gr_nexthop.hmodules/infra/api/nexthop.cmodules/infra/cli/cli_iface.hmodules/infra/cli/iface.cmodules/infra/cli/nexthop.cmodules/infra/control/nexthop.cmodules/infra/control/port.cmodules/ip/control/nexthop.cmodules/ip/datapath/arp_input_reply.cmodules/ip6/control/nexthop.cmodules/ip6/datapath/ndp_na_input.cmodules/l2/api/gr_l2.hmodules/l2/cli/bridge.cmodules/l2/cli/fdb.cmodules/l2/control/bridge.cmodules/l2/datapath/bridge_input.cmodules/l2/datapath/bridge_neigh_suppress.cmodules/l2/datapath/meson.buildsmoke/bridge_neigh_suppress_test.shsmoke/evpn_l2l3vni_frr_test.shsmoke/evpn_l3vpn_frr_test.shsmoke/evpn_l3vpn_vxlan6_frr_test.shsmoke/evpn_neigh_suppress_frr_test.sh
🚧 Files skipped from review as they are similar to previous changes (22)
- modules/l2/datapath/meson.build
- smoke/evpn_l3vpn_frr_test.sh
- .github/workflows/check.yml
- modules/infra/api/gr_infra.h
- api/gr_api.h
- api/gr_macro.h
- smoke/evpn_l3vpn_vxlan6_frr_test.sh
- smoke/evpn_l2l3vni_frr_test.sh
- modules/ip/control/nexthop.c
- modules/l2/api/gr_l2.h
- modules/l2/cli/fdb.c
- modules/infra/cli/cli_iface.h
- modules/l2/control/bridge.c
- modules/infra/cli/iface.c
- modules/ip6/control/nexthop.c
- README.md
- modules/l2/datapath/bridge_input.c
- modules/ip6/datapath/ndp_na_input.c
- modules/l2/datapath/bridge_neigh_suppress.c
- modules/l2/cli/bridge.c
- modules/infra/api/nexthop.c
- frr/rt_grout.c
|
|
||
| // Flush nexthops matching the given origin. | ||
| struct gr_nh_flush_req { | ||
| gr_nh_origin_t origin; | ||
| }; | ||
|
|
||
| GR_REQ(GR_NH_FLUSH, struct gr_nh_flush_req, struct gr_empty); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Hazard: Iterator invalidation and use-after-free in downstream nh_flush handler.
The downstream API handler for GR_NH_FLUSH (nh_flush in modules/infra/api/nexthop.c) iterates using nh = nexthop_next(nh) and destroys matching nexthops via nexthop_decref(nh) within the loop.
If nexthop_decref destroys and frees the nexthop, passing it to nexthop_next on the next iteration leads to a use-after-free. Additionally, if nexthop_next relies on list/hash membership or nh_id (which is safely set to 0 for GR_NH_ORIGIN_NEIGH), the iteration may abort prematurely or skip elements once the current nh is removed from those structures.
Consider modifying nh_flush (and any similar iteration loops) to cache the next pointer before decrementing references to ensure safe traversal.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@modules/infra/api/gr_nexthop.h` around lines 347 - 353, Update nh_flush and
any equivalent nexthop iteration loops to cache the result of nexthop_next(nh)
before calling nexthop_decref(nh), then continue from the cached pointer.
Preserve filtering and reference-decrement behavior while ensuring traversal
remains complete after the current nexthop is removed or freed.
| if grep -q ARP $tmp/tcpdump.out; then | ||
| cat $tmp/tcpdump.out | ||
| fail "ARP request for 10.0.0.99 was flooded to host-b (should have been suppressed)" | ||
| fi |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Avoid fail() inside if blocks without disabling set -e.
Based on learnings, in scripts using set -e, a function returning non-zero inside an if block will cause the shell to exit immediately, abruptly terminating the script instead of allowing further execution or graceful cleanup. To fix this, wrap these blocks with set +e and set -e, or refactor to handle errors using explicit checks/controlled flow.
smoke/bridge_neigh_suppress_test.sh#L58-L61: wrap theifblock withset +eandset -eor refactor.smoke/bridge_neigh_suppress_test.sh#L64-L67: wrap theifblock withset +eandset -eor refactor.smoke/evpn_neigh_suppress_frr_test.sh#L115-L118: wrap theifblock withset +eandset -eor refactor.smoke/evpn_neigh_suppress_frr_test.sh#L129-L132: wrap theifblock withset +eandset -eor refactor.smoke/evpn_neigh_suppress_frr_test.sh#L172-L175: wrap theifblock withset +eandset -eor refactor.
🧰 Tools
🪛 Shellcheck (0.11.0)
[info] 58-58: Double quote to prevent globbing and word splitting.
(SC2086)
[info] 59-59: Double quote to prevent globbing and word splitting.
(SC2086)
📍 Affects 2 files
smoke/bridge_neigh_suppress_test.sh#L58-L61(this comment)smoke/bridge_neigh_suppress_test.sh#L64-L67smoke/evpn_neigh_suppress_frr_test.sh#L115-L118smoke/evpn_neigh_suppress_frr_test.sh#L129-L132smoke/evpn_neigh_suppress_frr_test.sh#L172-L175
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@smoke/bridge_neigh_suppress_test.sh` around lines 58 - 61, Prevent fail()
from terminating the scripts unexpectedly under set -e by updating both affected
if blocks in smoke/bridge_neigh_suppress_test.sh (lines 58-61 and 64-67) and all
three affected if blocks in smoke/evpn_neigh_suppress_frr_test.sh (lines
115-118, 129-132, and 172-175); disable errexit for each block and restore it
afterward, or use equivalent explicit error handling while preserving the
existing failure checks and cleanup flow.
Source: Learnings
Depends on #566
Summary
NEIGH_SUPPRESSdatapath edge andbridge_neigh_suppressgraph node).neigh_suppressbridge configuration and CLI support, including enabling/disablingFLOOD/LEARNvia positive flag semantics and validating the newGR_BRIDGE_F_NEIGH_SUPPRESSbit.neigh_snoopinterface support so ARP/NDP processing is routed to control-plane neighbor-origin nexthop creation even when no existing remote nexthop is found (used to avoid dropping NA/solicitation paths on missing nexthops and to enable creating “neigh” origin nexthops).GR_NH_ORIGIN_NEIGH, changedGR_NH_T_L3value, and updated nexthop deletion to use an embeddedstruct gr_nexthop(plusmissing_ok) instead ofnh_id.GR_NH_FLUSHwithstruct gr_nh_flush_req { gr_nh_origin_t origin; }; implemented flush to iterate nexthops, filter by origin, clean up L3 routes, and decref until refs reach zero.ENOENTwhen lookups fail.grout_neigh_notify/grout_neigh_update_ctx()to emit zebra dplane neighbor install/delete operations for L3 nexthops carrying IP4/IP6 addresses with non-zero MACs, skipping local/link/multicast/flagged/zero-MAC cases.GR_NH_F_REMOTEand using neighbor MAC/IP as appropriate).l3vni_rmac_set()/l3vni_rmac_del(), and added L3VNI-aware handling to redirectreq->nh.iface_idto a VXLAN interface and apply cached RMAC into L3 nexthop info.gr_flags_foreach(f, flags)and removedgr_nh_flags_foreach, updating callers to use the new helper.nexthop_type_ops_foreach.GR_API_VERSIONto5.neigh_snoop,nexthop flush, and correctednexthop delID parsing).bridge_neigh_suppressARP suppression smoke test and added EVPN neighbor-suppression smoke test.nh newtonh update, and addedarpingto build dependencies.