Description
Summary
grout's datapath drops all received ICMPv6 Router Advertisements (type 134) as
"unsupported", and never punts them to the per-interface control-plane TAP. Because
FRR's BGP unnumbered (neighbor <iface> interface remote-as ...) relies on receiving
the peer's Router Advertisement to auto-discover the peer's link-local next-hop, BGP
sessions over grout ports stay stuck in Idle forever. Numbered eBGP over the same
port works fine, which isolates the problem to RA handling specifically.
Details / root cause
In modules/ip6/datapath/icmp6_input.c, Router Advertisements fall into the
default/ICMP6_TYPE_ROUTER_ADVERT branch, which only punts to the control plane if a
callback has been registered for that ICMPv6 type — otherwise the packet is sent to the
icmp6_input_unsupported DROP node:
case ICMP6_TYPE_ROUTER_ADVERT:
default:
if (icmp6_cb[icmp6->type] != NULL) {
control_output_set_cb(mbuf, icmp6_cb[icmp6->type], gr_clock_ns());
next = CONTROL;
} else {
next = UNSUPPORTED; // -> icmp6_input_unsupported (GR_DROP_REGISTER)
}
The only registered ICMPv6 callbacks are ECHO_REPLY and the four error types
(modules/ip6/control/icmp6.c):
icmp6_input_register_callback(ICMP6_TYPE_ECHO_REPLY, icmp6_input_cb);
icmp6_input_register_callback(ICMP6_ERR_DEST_UNREACH, icmp6_input_cb);
icmp6_input_register_callback(ICMP6_ERR_TTL_EXCEEDED, icmp6_input_cb);
icmp6_input_register_callback(ICMP6_ERR_PKT_TOO_BIG, icmp6_input_cb);
icmp6_input_register_callback(ICMP6_ERR_PARAM_PROBLEM, icmp6_input_cb);
There is no ICMP6_TYPE_ROUTER_ADVERT callback anywhere, and router_advert.c is
send-only (it generates grout's own RAs; there is no RA receiver). So received RAs are
always dropped and are never delivered to the kernel control-plane TAP where FRR listens.
By contrast, local TCP (e.g. BGP :179) is correctly punted to FRR:
modules/l4/l4_input_local.c sends non-UDP local traffic to the MANAGEMENT edge
(l4_loopback_output -> iface_cp_tx -> the interface cp_fd TAP). ICMPv6 is
registered as its own local proto handler (ip6_input_local_add_proto(IPPROTO_ICMPV6, "icmp6_input")), so RAs are intercepted before ever reaching that generic punt path.
Steps to reproduce
- Create a grout net_tap port and connect it (L2) to an FRR/Linux peer that sends
IPv6 Router Advertisements on the link (e.g. an FRR leaf using neighbor <iface> interface remote-as external, which enables RA on the interface).
- Run FRR with the grout dataplane plugin inside grout's netns and configure BGP
unnumbered over the grout port:
router bgp 64497
neighbor uplink1 interface remote-as external
- Observe:
vtysh -c "show bgp summary" shows the neighbor stuck in Idle (never up).
grcli graph stats shows a growing icmp6_input_unsupported counter and no
corresponding control-plane RX (iface_cp_rx) for the RAs. tcpdump on the peer
confirms RAs are being sent toward grout, but FRR never learns the peer link-local.
- Switch the same link to numbered p2p (assign IPs to the grout port and the peer)
and the BGP session comes up immediately — confirming only RA delivery is broken.
Expected behaviour
Received Router Advertisements on a grout port should be punted to that interface's
control-plane TAP (like other local control traffic) so a userspace routing daemon
(FRR/BIRD) can consume them, enabling BGP unnumbered / SLAAC-style next-hop discovery.
At minimum, a way to register an RA punt callback (or a per-interface "punt RA to control
plane" knob) would unblock this.
Environment
- FRR: BGP unnumbered eBGP over the grout uplink port.
Version
grout:edge (main / DPDK 25.11). Also reproduced against grout 0.16.2.
Description
Summary
grout's datapath drops all received ICMPv6 Router Advertisements (type 134) as
"unsupported", and never punts them to the per-interface control-plane TAP. Because
FRR's BGP unnumbered (
neighbor <iface> interface remote-as ...) relies on receivingthe peer's Router Advertisement to auto-discover the peer's link-local next-hop, BGP
sessions over grout ports stay stuck in
Idleforever. Numbered eBGP over the sameport works fine, which isolates the problem to RA handling specifically.
Details / root cause
In
modules/ip6/datapath/icmp6_input.c, Router Advertisements fall into thedefault/ICMP6_TYPE_ROUTER_ADVERTbranch, which only punts to the control plane if acallback has been registered for that ICMPv6 type — otherwise the packet is sent to the
icmp6_input_unsupportedDROP node:The only registered ICMPv6 callbacks are ECHO_REPLY and the four error types
(
modules/ip6/control/icmp6.c):There is no
ICMP6_TYPE_ROUTER_ADVERTcallback anywhere, androuter_advert.cissend-only (it generates grout's own RAs; there is no RA receiver). So received RAs are
always dropped and are never delivered to the kernel control-plane TAP where FRR listens.
By contrast, local TCP (e.g. BGP :179) is correctly punted to FRR:
modules/l4/l4_input_local.csends non-UDP local traffic to theMANAGEMENTedge(
l4_loopback_output->iface_cp_tx-> the interfacecp_fdTAP). ICMPv6 isregistered as its own local proto handler (
ip6_input_local_add_proto(IPPROTO_ICMPV6, "icmp6_input")), so RAs are intercepted before ever reaching that generic punt path.Steps to reproduce
IPv6 Router Advertisements on the link (e.g. an FRR leaf using
neighbor <iface> interface remote-as external, which enables RA on the interface).unnumbered over the grout port:
router bgp 64497
neighbor uplink1 interface remote-as external
vtysh -c "show bgp summary"shows the neighbor stuck inIdle(never up).grcli graph statsshows a growingicmp6_input_unsupportedcounter and nocorresponding control-plane RX (
iface_cp_rx) for the RAs. tcpdump on the peerconfirms RAs are being sent toward grout, but FRR never learns the peer link-local.
and the BGP session comes up immediately — confirming only RA delivery is broken.
Expected behaviour
Received Router Advertisements on a grout port should be punted to that interface's
control-plane TAP (like other local control traffic) so a userspace routing daemon
(FRR/BIRD) can consume them, enabling BGP unnumbered / SLAAC-style next-hop discovery.
At minimum, a way to register an RA punt callback (or a per-interface "punt RA to control
plane" knob) would unblock this.
Environment
Version
grout:edge (main / DPDK 25.11). Also reproduced against grout 0.16.2.