Is it platform specific
generic (VPP platform / docker-syncd-vpp, libsaivs vslib)
Importance or Severity
High
Description of the bug
On the VPP platform, an IP neighbor whose router interface is a VLAN SVI (Vlan<id>, SAI_ROUTER_INTERFACE_TYPE_VLAN, realized in VPP as a BVI bvi<vlan_id>) is never programmed into the VPP data plane. No neighbor adjacency and no /32 (or /128) host route are installed on the BVI.
As a result, routed traffic destined to a host that sits on a VLAN subnet (e.g. uplink → downlink to a server on Vlan1000) has no host route to match. It falls through to the connected /21 glean entry on the BVI, where VPP emits an ARP and drops the triggering packet. Downstream delivery to SVI hosts is silently dropped until (and unless) VPP happens to resolve the host by its own ARP.
Root cause is in SwitchVpp::addRemoveIpNbr() (vslib/vpp/SwitchVppNbr.cpp). It resolves SAI_ROUTER_INTERFACE_ATTR_PORT_ID before it branches on the RIF type:
attr.id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
CHECK_STATUS(get(SAI_OBJECT_TYPE_ROUTER_INTERFACE, nbr_entry.rif_id, 1, &attr));
auto port_obj_type = objectTypeQuery(attr.value.oid);
if (port_obj_type != SAI_OBJECT_TYPE_PORT && port_obj_type != SAI_OBJECT_TYPE_LAG)
{
return SAI_STATUS_SUCCESS; // <-- VLAN SVI RIF has no PORT_ID => returns here, neighbor never programmed
}
A VLAN SVI RIF has no SAI_ROUTER_INTERFACE_ATTR_PORT_ID (it references a VLAN, not a single port), so the neighbor is dropped before the RIF type is ever considered. Only PORT and SUB_PORT RIFs are handled.
This is the neighbor/host-route counterpart of the RIF-attribute-update bug tracked separately (VLAN RIF updates); both stem from resolving PORT_ID before dispatching on RIF type.
Steps to Reproduce
- Deploy a VPP KVM testbed with a VLAN SVI, e.g.
Vlan1000 with an IP (dual-ToR t0 exercises this heavily; the server-facing /32s live on the SVI).
- Create an IP neighbor on the SVI (learned normally, or via mux/host-route programming). The SAI
NEIGHBOR_ENTRY appears in ASIC_DB with a valid DST_MAC.
- Inspect the VPP data plane:
docker exec syncd vppctl show ip neighbor | grep <host> → absent
docker exec syncd vppctl show ip fib <host> → only the connected /21 glean, no /32.
- Route a packet to that host from an uplink → it is dropped at
ip4-glean (no host route/adjacency).
Actual Behavior and Expected Behavior
Actual: A SAI NEIGHBOR_ENTRY on a VLAN SVI RIF is accepted by SONiC (present in ASIC_DB, MAC learned in the VPP L2 FDB) but not realized in VPP L3 — no adjacency, no host route. Downstream packets to the host glean-and-drop.
Expected: Creating the neighbor should install the L3 adjacency and the host route on the BVI (bvi<vlan_id>), so routed traffic to the host forwards immediately — matching ASIC behavior, where a NEIGHBOR_ENTRY installs the host route regardless of whether the switch has itself ARPed the host. addRemoveIpNbr() should dispatch on RIF type first and resolve the BVI for SAI_ROUTER_INTERFACE_TYPE_VLAN (mirroring vpp_create_bvi_interface()), instead of requiring PORT_ID.
Relevant log output
# ASIC_DB has the neighbor with a valid MAC:
redis-cli -n 1 keys '*NEIGHBOR_ENTRY*192.168.0.2*'
ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY:{"ip":"192.168.0.2","rif":"oid:0x6...","switch_id":"oid:0x21..."}
SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS = 0E:4D:33:65:C0:01
# ... but VPP has no L3 neighbor for it:
docker exec syncd vppctl show ip neighbor | grep 192.168.0.2
(absent)
# ... and the VPP FIB has only the connected /21 glean (no /32 host route):
docker exec syncd vppctl show ip fib 192.168.0.2
192.168.0.0/21 fib:0 index:150 locks:2
... cfg-flags:glean, bvi1000
forwarding: unicast-ip4-chain
[0] [@4]: ipv4-glean: [src:192.168.0.0/21] bvi1000: ... ffffffffffff22ada23408760806
Output of show version, show techsupport
SONiC Software Version: SONiC.master.1182394-fc9ea17bb
Distribution: Debian 13.5
Kernel: 6.12.41+deb13-sonic-amd64
Platform: x86_64-kvm_x86_64-r0
HwSKU: Force10-S6000
ASIC: vpp
ASIC Count: 1
Fix
Dispatch on RIF type before resolving PORT_ID; for SAI_ROUTER_INTERFACE_TYPE_VLAN, resolve the BVI (bvi<vlan_id>) and program the neighbor adjacency + host route there (static, since SONiC owns the SVI neighbor lifecycle).
Is it platform specific
generic (VPP platform /
docker-syncd-vpp,libsaivsvslib)Importance or Severity
High
Description of the bug
On the VPP platform, an IP neighbor whose router interface is a VLAN SVI (
Vlan<id>,SAI_ROUTER_INTERFACE_TYPE_VLAN, realized in VPP as a BVIbvi<vlan_id>) is never programmed into the VPP data plane. No neighbor adjacency and no/32(or/128) host route are installed on the BVI.As a result, routed traffic destined to a host that sits on a VLAN subnet (e.g. uplink → downlink to a server on
Vlan1000) has no host route to match. It falls through to the connected/21glean entry on the BVI, where VPP emits an ARP and drops the triggering packet. Downstream delivery to SVI hosts is silently dropped until (and unless) VPP happens to resolve the host by its own ARP.Root cause is in
SwitchVpp::addRemoveIpNbr()(vslib/vpp/SwitchVppNbr.cpp). It resolvesSAI_ROUTER_INTERFACE_ATTR_PORT_IDbefore it branches on the RIF type:A VLAN SVI RIF has no
SAI_ROUTER_INTERFACE_ATTR_PORT_ID(it references a VLAN, not a single port), so the neighbor is dropped before the RIF type is ever considered. OnlyPORTandSUB_PORTRIFs are handled.This is the neighbor/host-route counterpart of the RIF-attribute-update bug tracked separately (VLAN RIF updates); both stem from resolving
PORT_IDbefore dispatching on RIF type.Steps to Reproduce
Vlan1000with an IP (dual-ToR t0 exercises this heavily; the server-facing/32s live on the SVI).NEIGHBOR_ENTRYappears inASIC_DBwith a validDST_MAC.docker exec syncd vppctl show ip neighbor | grep <host>→ absentdocker exec syncd vppctl show ip fib <host>→ only the connected/21glean, no/32.ip4-glean(no host route/adjacency).Actual Behavior and Expected Behavior
Actual: A SAI
NEIGHBOR_ENTRYon a VLAN SVI RIF is accepted by SONiC (present inASIC_DB, MAC learned in the VPP L2 FDB) but not realized in VPP L3 — no adjacency, no host route. Downstream packets to the host glean-and-drop.Expected: Creating the neighbor should install the L3 adjacency and the host route on the BVI (
bvi<vlan_id>), so routed traffic to the host forwards immediately — matching ASIC behavior, where aNEIGHBOR_ENTRYinstalls the host route regardless of whether the switch has itself ARPed the host.addRemoveIpNbr()should dispatch on RIF type first and resolve the BVI forSAI_ROUTER_INTERFACE_TYPE_VLAN(mirroringvpp_create_bvi_interface()), instead of requiringPORT_ID.Relevant log output
Output of
show version,show techsupportFix
Dispatch on RIF type before resolving
PORT_ID; forSAI_ROUTER_INTERFACE_TYPE_VLAN, resolve the BVI (bvi<vlan_id>) and program the neighbor adjacency + host route there (static, since SONiC owns the SVI neighbor lifecycle).