Skip to content

SONiC containerlab: name the link endpoints ethN so docker-sonic-vs maps its ports - #3872

Open
roc-ops wants to merge 2 commits into
ipspace:devfrom
roc-ops:fix/sonic-clab-ports
Open

SONiC containerlab: name the link endpoints ethN so docker-sonic-vs maps its ports#3872
roc-ops wants to merge 2 commits into
ipspace:devfrom
roc-ops:fix/sonic-clab-ports

Conversation

@roc-ops

@roc-ops roc-ops commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

docker-sonic-vs builds its front-panel port map from the ethN netdevs present when the container boots (eth1 becomes Ethernet0), and syncd then creates a TAP named Ethernet<4n> for each mapped port and bridges it to the veth. The sonic device declared no clab.interface.name, so containerlab named the link endpoint Ethernet0 itself: the lane map came out empty, syncd could not create a single TAP, and SONiC's port objects had no relationship to the links -- show interfaces status reported a port down while it carried a Full OSPF adjacency, and config interface shutdown did nothing.

This PR declares clab.interface.name: eth{ifindex + 1}, the same thing eos and srlinux do. With the port a real TAP again, CONFIG_DB reaches the kernel: the initial template goes back to config interface mtu and drops the loop that mirrored CONFIG_DB routed-port addresses onto the netdev by hand. A node now has two netdevs per link and the kernel answers ARP for the port's address on both of them, each with its own MAC; the neighbour caches whichever answers first, so the port's address can end up reachable through a MAC that is not the port's. The template therefore sets arp_ignore=8 on each wire veth before the ports are addressed, leaving the port as the only answerer. The vlan, lag and vxlan datapaths are out of scope here: those features are off on this device and were not re-measured.

Verified:

  • Two SONiC nodes + an FRR node under containerlab: lanemap.ini populated, no TUNSETIFF errors in syslog, show interfaces status shows oper/admin up only on the two ports the lab uses, and OSPF reaches Full with both neighbours.
  • Shutting the far end of a link down makes SONiC report that port oper down (admin still up); bringing it back up restores it.
  • The FRR neighbour's ARP entry for the SONiC port resolves to the TAP's MAC, not the veth's.
  • New transformation test sonic-clab-ifnames; the full transformation suite passes (303 passed, 1 skipped), as do run-yamllint.sh and run-typing.sh.
  • MTU: netdev, CONFIG_DB, APPL_DB and show interfaces status all read 9000 on a 9000-byte link, and an 8972-byte DF ping crosses it.
  • tests/integration/device-module-test -d sonic -p clab initial: every case that deploys a SONiC node passes. The rest abort in netlab create on the device's own declared feature gaps, and 04-mtu needs a cEOS image I do not have locally.

One pre-existing issue is left alone on purpose: initial/01-interfaces warns that a shutdown: True interface still pings on SONiC, because the vtysh block renders a bare no shutdown for every interface. config interface shutdown works now, so that is a separate one-line follow-up.

🤖 Generated with Claude Code

roc-ops and others added 2 commits September 6, 2026 01:45
…ts ports

docker-sonic-vs builds lanemap.ini/port_config.ini from the ethN netdevs present
at boot and syncd then creates a TAP named Ethernet<4n> per mapped port, bridged
to eth<n+1> -- the contract containerlab documents for the sonic-vs kind. The
device declared no clab.interface.name, so containerlab injected the veth as
Ethernet0 itself: the lane map came out empty, syncd failed to create every TAP
(TUNSETIFF: name in use), and SONiC port state and admin control were detached
from the link. "show interfaces status" reported oper/admin down on a port
carrying a Full OSPF adjacency, and "config interface shutdown" changed nothing.

Declare clab.interface.name eth{ifindex + 1} (ifindex starts at 0 here, eth0 is
management), as eos (et{ifindex}) and srlinux (e1-{ifindex}) do.

With the port a syncd TAP rather than the raw veth, CONFIG_DB reaches the netdev
again: the MTU goes back through "config interface mtu" (measured on a 9000-byte
link -- netdev, CONFIG_DB and APPL_DB all agree, an 8972-byte DF ping crosses)
and the loop that mirrored CONFIG_DB INTERFACE rows onto the netdev with
"ip addr add" is gone, because intfmgrd programs routed-port addresses. portmgrd
still leaves every front-panel port admin-down at boot, so "config interface
startup" stays, now issued for the ports the lab uses and under the script's
set -e. The vlan, lag and vxlan datapaths are out of scope: those features
are off on this device (vlan: False, lag: False, vxlan: false) and were not
re-measured.

A node now has two netdevs per link, and the kernel answers ARP for the port's
address on both of them, each with its own MAC. The neighbour caches whichever
replies first, so the port's address becomes reachable through a MAC that is not
the port's, and anything keyed on the port's MAC is left to chance -- measured,
"ip neigh" on the neighbour showed the veth's MAC, and with the sysctl it shows
the TAP's. arp_ignore=8 on each link's veth, set before the ports are addressed,
leaves the port as the only answerer. This surfaced on our fork as an SR-MPLS
L3VPN ping at 100% loss, MPLS input being enabled on the port only; upstream's
sonic device does not enable MPLS.

The transformation case pins the container name on the node interface and, by
covering the whole transformed topology, also pins that the node keeps its own
config_templates rather than inheriting FRR's bind mounts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A containerlab SONiC node has two kernel interfaces per link: the wire veth ethN
that containerlab creates and the port Ethernet<4n> that syncd bridges to it.
Only the port is configured and addressed, and netlab suppresses ARP on the veth
so neighbours resolve the port's MAC.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@roc-ops
roc-ops force-pushed the fix/sonic-clab-ports branch from 31eff8b to ef8f6be Compare September 6, 2026 01:51
@jbemmel

jbemmel commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

This seems convoluted - having to manually orchestrate ARP ignores such that neighbors cache the correct MAC is hideous

I don’t think this is the right solution (it’s additional problems and complexity that comes from AI not understanding design intent)

@roc-ops

roc-ops commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Agreed, and thanks for the pushback. The arp_ignore block was the wrong place for this. The wire veth (ethN) is meant to be silent: SONiC's own virtual-switch harness turns ARP and IPv6 off on it when it attaches links (sonic-swss tests/conftest.py, VirtualServer: "disable arp, so no neigh on physical interfaces"), and real SONiC ships arp_ignore=2 host-wide, which the docker-sonic-vs container never applies. That belongs to whoever creates the veth, so it is now srl-labs/containerlab#3390, doing exactly what the swss harness does in the sonic-vs kind's post-deploy.

Once that lands I will cut this PR down to netlab's part only: the clab.interface.name declaration so docker-sonic-vs maps its ports, removal of the initial-template workarounds that only existed because it did not, the transformation test, and a caveat naming the containerlab version it needs. Leaving this open until then; happy to close and reopen if you prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants