Add vpp device support - #3492
Conversation
| create loopback interface instance {{ lb_instance }} | ||
| {% set vpp_if = l.ifname %} | ||
| {% else %} | ||
| {% set vpp_if = 'host-' ~ l.ifname %} |
There was a problem hiding this comment.
I tried using interface_name: host-eth{ifindex} but that breaks the bridge scenario
There was a problem hiding this comment.
I love this! I left a bunch of nits and comments.
The one thing I think you should not do, is autogen a setup.conf or setup.vpp file. It makes it ~impossible to make any changes to the dataplane configuration while operating the netlab. What if you wanted to add a sub-interface, or remove an address, or make an L2XC between two interfaces, or bind an MPLS tunnel? Your users would end up resorting to 'vppctl' debug CLI, which is cumbersome at best, and perilous at worst, because ordering matters, and the CLI/API do very limited syntax and semantic checking.
Also, there will be no config persistence if they restart the container. There is no vppctl show run or vppctl write mem, by design it is a configurable dataplane with an API that is meant to be configured by another system. Users will risk crashing the dataplane if they do things in the wrong order, or with the wrong arguments.
Consider using vppcfg and have ansible generate /etc/vpp/vppcfg.yaml, and explain to users how to edit that file and run vppcfg plan and vppcfg apply. When starting the container, you can generate the file you're now hand-crafting with vppcfg plan --novpp -c vppcfg.yaml -o vppcfg.vpp and start the dataplane with that instead. I guarantee you that is a better user experience, even if you rely on an external component (you can pip install it).
Good luck with the netlab integration!
I hear what you're saying, and in a production setup that makes total sense. The Netlab workflow / mental model deviates from that though, in ways that fundamentally impact these usage concerns. Netlab provides an abstracted single topology definition file from which all configuration is derived. This "vendor neutral" intent gets mapped to platform specific syntax - soon including VPP. That means that if a user wants to add a sub interface, they'd edit this Netlab topology file and redeploy the lab. That would work for VPP, but also Arista, SR Linux, FRR or any of the other platforms. Same for addressing, MPLS tunnels, etc. Basically the same idea as your vppcfg - abstract YAML syntax mapped to platform specific commands in the right order and validated - but applied to all platforms. A major benefit for you/VPP will be that once we finalize this config mapping, we can validate against the Netlab 250+ integration tests, and run virtual interop tests between any and all supported platforms. |
Well, there is no canonical "one true way" to use netlab. Certainly I would not always restart Netlab with an edited topology file just to make some changes to the running config of a device. Sometimes it makes sense to do that, sometimes it doesn't. And if the topology device it's one of the devices with a long boot time, yeah, forget that, I wont restart. To save time Ill just duplicate the topology , modify it, and dump the new config. Netlab create only, not a full deploy. Reconcile manually on the long running lab, if needed, copy / paste does the rest. Vppctl is really not the end of the world. As of today, it's the only way to really dig and learn VPP. Regardless you use vppcfg as planner or write the config yourself, there is no other way to learn VPP but vppctl command line. And crashing things or getting invalid configs is part of the learning experience. I am good with it as is, without using vppcfg planner. |
You’re right of course, it is not that black and white |
4973c4e to
fa057ca
Compare
|
@jbemmel What is the status of this one? Do you want to add more things, or should we focus on merging it in the near future? I have a personal interest in the platform. |
Thanks for the trigger - I think this is ready for review. It adds vpp as a device with either BIRD or frr as control_plane; the initial integration tests pass (with some minor exceptions). Adding other things to make it useful (ospf, bgp, etc.) should be done in separate PRs |
There was a problem hiding this comment.
Pull request overview
This PR adds a new VPP (FD.io Vector Packet Processor) containerlab daemon/device (device: vpp) with a locally buildable image (netlab clab build vpp), integrates it into the daemon/framework plumbing, and documents how to build/use it.
Changes:
- Added VPP device quirks to select/merge a Linux control plane (BIRD default, optional FRR) and control which daemon/module artifacts get generated and bound into the container.
- Added VPP daemon templates (VPP startup config, runtime start script, setup CLI config, MPLS stub, and a Dockerfile template for local image builds).
- Updated documentation to list VPP as a platform daemon and describe build/use caveats and workflow.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| netsim/devices/vpp.py | Adds VPP-specific quirks and control-plane selection/merge logic (BIRD/FRR). |
| netsim/daemons/vpp/vpp.j2 | New VPP startup.conf template. |
| netsim/daemons/vpp/start.vpp.j2 | New entrypoint script to start VPP, handle unnumbered peers, and launch the selected control-plane daemon. |
| netsim/daemons/vpp/setup.vpp.j2 | New VPP CLI setup template (interfaces, MTU, addressing, RA, unnumbered, exec extra .vpp snippets). |
| netsim/daemons/vpp/ospf.areas.j2 | Placeholder note for OSPF areas handling with bird control plane. |
| netsim/daemons/vpp/mpls.vpp.j2 | Minimal MPLS setup snippet for VPP. |
| netsim/daemons/vpp/hosts.j2 | Reuses linux hosts template for VPP. |
| netsim/daemons/vpp/Dockerfile.j2 | Dockerfile template for building netlab/vpp with optional version pinning and BIRD/FRR installed. |
| netsim/daemons/vpp/daemons.j2 | Includes FRR daemons template for VPP use. |
| netsim/daemons/vpp/bird.j2 | Includes BIRD template for VPP use. |
| netsim/daemons/vpp.yml | Registers VPP daemon/device defaults (clab build/image, features, config templates, and control_plane attribute). |
| netsim/daemons/bird/bird.j2 | Prevents BIRD from including its own config via _daemon_config when used as a control plane for other devices. |
| netsim/ansible/templates/mpls/vpp.initial.j2 | Adds VPP-specific MPLS sysctl setting for initial config. |
| netsim/ansible/templates/initial/vpp.j2 | Adds VPP initial script creating dataplane netns and generating clab-interfaces.vpp. |
| docs/platforms.md | Documents VPP as a platform daemon and its configuration/deployment characteristics. |
| docs/netlab/defaults.md | Adds VPP image default example. |
| docs/netlab/clab.md | References VPP build documentation from clab build docs. |
| docs/labs/vpp.md | New documentation page for building/using VPP containers and control-plane selection. |
| docs/labs/clab.md | Adds VPP to containerlab lab-image list and build instructions section. |
| docs/caveats.md | Adds VPP caveats section (must build image; clab-only). |
Comments suppressed due to low confidence (1)
netsim/daemons/vpp/start.vpp.j2:21
- This interface readiness loop also has no timeout; a missing/misnamed interface will block startup forever.
{% for l in interfaces if l._unnumbered_peer is defined %}
until ip -n "$NETNS" link show {{ l.ifname }} >/dev/null 2>&1; do sleep 0.1; done
ip -n "$NETNS" addr flush dev {{ l.ifname }} scope global 2>/dev/null || true
ipspace
left a comment
There was a problem hiding this comment.
Starting with a few documentation nits and a major question: why do you think it's a good idea to define VPP as a daemon (as opposed to a regular device)?
After all, you start the VPP daemon at the end of the initial configuration and delay the start of the BIRD process until the dataplane configuration is completed.
|
|
||
| To use a custom container image, specify it with the **image** node parameter or the **defaults.daemons._daemon_.clab.image** [default setting](topo-defaults). | ||
|
|
||
| See [Building BIRD containers](../labs/bird.md) and [Building VPP containers](../labs/vpp.md) for configurable software releases. |
| ## VPP (Vector Packet Processor) | ||
|
|
||
| * You must build the VPP container image with the **netlab clab build vpp** command. See [](build-vpp) for version options. | ||
| * VPP is available only on the [containerlab](labs/clab.md) provider. |
There was a problem hiding this comment.
Isn't this clear enough from the "platforms" table?
| |-----------------------|:--:|:--:| :--:| | ||
| | Arista EOS | ✅ | ✅ | ✅ | | ||
| | BIRD | ✅ | ✅ | ❌ | | ||
| | VPP | ✅ | ❌ | ✅ | |
| |--------|----------|---------------------------------| | ||
| | bird | clab | **bash** scripts or daemon configuration files[^BBS] | | ||
| | dnsmasq | clab | **bash** scripts or daemon configuration files[^DBS] | | ||
| | vpp | clab | **bash** scripts, daemon configuration files, and VPP CLI configuration files[^VPPC] | |
There was a problem hiding this comment.
Please use case-insensitive sort ;)
I initially conceptualized this as "BIRD with a different data plane", hence I started from a daemon. It wasn't so much "a good idea" but more "a logical progression". I guess I never really paid much attention to the difference between devices and daemons, it's not a distinction I tend to make naturally. We could easily reconceive VPP as a device - I'll make that change |
Thank you! |
Move VPP to netsim/daemons with a custom netlab/vpp image, host-netns initial provisioning, split startup/setup templates, and IPv6 RA support. Co-authored-by: Cursor <cursoragent@cursor.com>
Add minimal user docs for building and using the VPP daemon, including router/host/bridge roles and ns config mode. Co-authored-by: Cursor <cursoragent@cursor.com>
Emit one ip6 nd prefix line with optional flags and declare initial module roles for clab. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Thanks for making that change, but why do you still have files in the "daemons/vpp" directory? |
Leave only Dockerfile.j2 under daemons/vpp for netlab clab build. Co-authored-by: Cursor <cursoragent@cursor.com>
Move MPLS under ansible/templates, drop the unused OSPF areas stub, and rename the VPP start template to netlab-start.sh. Co-authored-by: Cursor <cursoragent@cursor.com>
FRR was fed bash VLAN scripts via vtysh, and Linux bridges on LCP taps do not forward between host-interfaces. Apply vlan as VPP CLI, wait for LCP before starting the control plane, and run shell vs vtysh by shebang. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
VPP VLAN snippets (*.vpp) were pulled into bird.conf and crashed bird. Co-authored-by: Cursor <cursoragent@cursor.com>
Bridge-only access ports worked, but IRB labs had no L3 interface in the bridge-domain, so host-to-DUT and inter-subnet pings failed. Co-authored-by: Cursor <cursoragent@cursor.com>
IRB host-to-switch pings target the DUT loopback (10.0.0.x); setup.vpp had filtered all virtual_interface entries and never created loop0. Co-authored-by: Cursor <cursoragent@cursor.com>
Bridge-trunk labs failed because vlan_member subifs were never created before L2 bridge assignment; pop-1 rewrite is required for access/trunk. Co-authored-by: Cursor <cursoragent@cursor.com>
Skip unused bird plugin daemon_config maps and configure L3 VLAN subinterfaces with IP/LCP instead of L2 tag-rewrite. Co-authored-by: Cursor <cursoragent@cursor.com>
Move bridge-domain, subif, and BVI setup into initial/vpp.vlan.j2 (skip unsupported BVI MTU) and keep access-port bridging in vlan/vpp.j2. Co-authored-by: Cursor <cursoragent@cursor.com>
Defer vlan-init until after parent TAP MACs match host-interface hw-addr so af_packet does not reject secondary MACs on subif LCP. Co-authored-by: Cursor <cursoragent@cursor.com>
both pass The bridge test was failing for frr, so I also added proper vlan support. Those tests now pass too :) |
ipspace
left a comment
There was a problem hiding this comment.
Great job, with a few leftover bits and pieces.
I cleaned up a few documentation quirks. You also forgot to add VPP to a lot of "supported platforms" tables, but if neither your AI friend nor you care about that, neither do I 🤷🏻♂️
I also disabled features that work only on Linux but not VPP, or on FRR but not BIRD. If you want to have them, add corresponding device quirks. Starting a device, not getting any errors, and having a broken network is not the best user experience.
MTU on VLANs is probably broken, and the loopback interface is not working with OSPFv3. Will open separate bug reports for that.
I tried setting MTU on the VLANs but it failed with an error that the underlying device doesn't support it - so I left it out. Note that all the VLAN tests pass - perhaps MTU on VLANs could use a more specific test, so it gets flagged? I didn't fully test OSPF yet - I figured it might be better to merge the baseline first, and then incrementally fix some remaining quirks. |
Thinking more about this, it may be better to model this as 2 devices e.g. |
I was thinking along the exact same lines ;) Yes, that would make a lot of sense, and be (probably) simpler than trying to deal with two sets of control-plane features. |
OSPF is the only protocol that reliably complains about the MTU mismatch. You could try to use dataplane tricks, but you know how "reliable" those are. |
Wait before moving forward with this. I plan to implement "device plugins" for cases where we need more functionality (beyond post-transform quirks). I'll try it out on the "kind" device, and if it works, it might be easier to implement feature merge etc. |
Are all the docs tables not generatable by the feature yamls? Seems odd that those are handled separately? |
Summary
Adds VPP as a buildable containerlab device (vpp), similar to BIRD:
netlab clab build vppproduces netlab/vpp:latest, then lab nodes can use it under provider: clab.This is a rework of the earlier VPP branch. It deliberately does not use Containerlab’s fdio_vpp kind; it uses the same daemon/image pattern as BIRD while keeping comparable dataplane plumbing (VPP + Linux CP in the dataplane netns).
Highlights
initial test results: