Skip to content
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
cb58c6c
Initial device- and configuration templates
ipspace Oct 13, 2024
defca05
Fixes after the initial tests
ipspace Oct 14, 2024
4c775d1
Replace VPP device with a buildable clab daemon.
jbemmel Jun 16, 2026
43dcbe9
Document VPP clab daemon support.
jbemmel Jun 16, 2026
54f8652
Simplify VPP RA prefix configuration.
jbemmel Jun 16, 2026
e39b256
Fix VPP RA prefix flags and host IPv6 autoconfig.
jbemmel Jun 16, 2026
99d3189
Remove redundant VPP clab hosts template symlinks.
jbemmel Jun 16, 2026
b14f3d8
Wait for netlab initial before starting VPP in clab.
jbemmel Jun 16, 2026
4580e97
Keep daemon config keys ending in .conf through cleanup.
jbemmel Jun 16, 2026
78436bd
Fix VPP config-done marker when deployed via netns exec.
jbemmel Jun 16, 2026
5cafa0e
Fix VPP clab initial deploy and startup configuration.
jbemmel Jun 16, 2026
1a823e2
Align VPP interface naming and startup configuration.
jbemmel Jun 16, 2026
710169d
Fix VPP extra loopback instance numbering.
jbemmel Jun 16, 2026
3cffa77
Use eth{ifindex} interface names and map to VPP host-* in setup.
jbemmel Jun 16, 2026
a30f9d6
Document that VPP supports router and bridge roles only.
jbemmel Jun 16, 2026
e4b1b7f
Create VPP config-done marker in the initial script.
jbemmel Jun 16, 2026
a8102f5
Trim redundant VPP role documentation.
jbemmel Jun 16, 2026
16c5ce8
Fix VPP clab configuration deployment documentation.
jbemmel Jun 16, 2026
65311d9
Use node-specific VPP CLI prompt in startup.conf.
jbemmel Jun 16, 2026
dd99f90
Factor loopback check out of VPP setup.conf RA blocks.
jbemmel Jun 16, 2026
86ce14d
Move VPP setup into config directory
jbemmel Jun 18, 2026
4b5dd16
Move VPP MPLS setup into module config
jbemmel Jun 18, 2026
98d1454
Update VPP platform config documentation
jbemmel Jun 18, 2026
39ae9bc
Add VPP unnumbered interface support
jbemmel Jun 18, 2026
b098ac5
Set VPP interface MTU in setup
jbemmel Jun 18, 2026
2017031
Fix VPP container startup and MTU validation.
jbemmel Jun 24, 2026
ced2a74
Stabilize MTU validation after PMTU updates.
jbemmel Jun 24, 2026
d674e69
Move VPP MPLS sysctl into module initial template.
jbemmel Jul 7, 2026
80cbe3b
Fix VPP clab-interfaces generation to use only dataplane eth links.
jbemmel Jul 7, 2026
70cbf32
Clean up VPP setup template neighbor-config and Jinja indentation.
jbemmel Jul 7, 2026
db9ca69
Add vpp_control_plane device setting with BIRD2 and FRR in the image.
jbemmel Jul 7, 2026
032bb21
Keep ansible_network_os frr for VPP nodes.
jbemmel Jul 7, 2026
14e2d14
Fix VPP bird control plane integration for OSPF labs.
jbemmel Jul 7, 2026
fc01818
Add VPP FRR control-plane startup and rename control_plane setting.
jbemmel Jul 7, 2026
730d608
Fix VPP bird control plane startup after CP group_vars merge.
jbemmel Jul 7, 2026
4f0ae71
Declare VPP OSPF feature flags explicitly and drop bogus merge syntax.
jbemmel Jul 7, 2026
57353f6
Fix VPP IPv4 unnumbered for bird and reject bird/IS-IS.
jbemmel Jul 8, 2026
c214402
Fix empty VPP peer-address bash function breaking IPv6-only labs.
jbemmel Jul 8, 2026
cfc1f7b
Revert MTU PMTU-cache flush changes from VPP branch.
jbemmel Jul 24, 2026
22f122b
Doc: Explain VPP control_plane bird/frr selection.
jbemmel Jul 24, 2026
6cb98db
Convert VPP from a clab daemon into a regular device.
jbemmel Jul 30, 2026
27eaf3e
Add VPP resolv.conf template to fix missing template warning
jbemmel Jul 30, 2026
de2ab33
Fix: Keep path:mode node configs out of VPP daemon includes
jbemmel Jul 30, 2026
81b0e71
Doc: Sort VPP alphabetically in containerlab device table
jbemmel Jul 30, 2026
3fbac61
Doc: Remove premature VPP note from 26.07 release notes
jbemmel Jul 30, 2026
7b5596d
Move VPP config templates to the clab provider path.
jbemmel Jul 30, 2026
45ff871
Cleanup: Relocate VPP module templates and rename start script.
jbemmel Jul 30, 2026
4cb972d
Fix: Use VPP bridge-domains for VLAN bridging with FRR CP.
jbemmel Jul 30, 2026
f262af4
Cleanup: Tighten VPP VLAN bridge-domain template loops.
jbemmel Jul 30, 2026
48e4612
Fix: Only include *.conf files in BIRD daemon config.
jbemmel Jul 30, 2026
cb911a5
Fix: Create VPP BVIs for IRB VLAN SVIs.
jbemmel Jul 30, 2026
86fd5b4
Fix: Configure VPP loopbacks skipped as virtual interfaces.
jbemmel Jul 30, 2026
f421f7e
Fix: Create VPP trunk subinterfaces with VLAN tag-rewrite.
jbemmel Jul 30, 2026
3008dfa
Fix: Support VPP routed VLAN trunks with bird control plane.
jbemmel Jul 30, 2026
d30a847
Cleanup: Split VPP VLAN create vs L2 into initial/vlan templates.
jbemmel Jul 30, 2026
d2b56b0
Fix: Align VPP LCP TAP MACs before VLAN subinterface create.
jbemmel Jul 30, 2026
9e593fc
Minor documentation fixes, disabling broken features
ipspace Jul 31, 2026
0f89687
Merge branch 'dev' into vpp-support
ipspace Aug 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ Netlab enables VRRPv3 by default on Dell OS10, overriding any platform defaults.

* You have to build the *dnsmasq* container image with the **netlab clab build dnsmasq** command.

(caveats-vpp)=
## VPP (Vector Packet Processor)

* You must [build the VPP container image](build-vpp) with the **netlab clab build vpp** command.
* VPP can use FRR or BIRD control plane. [More details](vpp-control-plane).

(caveats-exos)=
## Extreme Networks EXOS

Expand Down
8 changes: 5 additions & 3 deletions docs/labs/clab.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ Lab topology file created by **[netlab up](../netlab/up.md)** or **[netlab creat
| Mikrotik RouterOS 7 | vrnetlab/vr-routeros:7.6 |
| Nokia SR Linux | ghcr.io/nokia/srlinux:24.10.1 |
| Nokia SR OS | vrnetlab/vr-sros:latest |
| VPP [❗](build-vpp) | netlab/vpp:latest |
| VyOS | ghcr.io/sysoleg/vyos-container |

* Cumulus VX, FRR, Linux, Nokia SR Linux, and VyOS images are automatically downloaded from public container registries.
* Build the BIRD, dnsmasq, and Netscaler images with the **netlab clab build** command. BIRD supports several build targets and configurable source releases — see [](build-bird) for details.
* FRR, Linux, Nokia SR Linux, and VyOS images are automatically downloaded from public container registries.
* Build the [BIRD](build-bird), dnsmasq, [VPP](build-vpp), and [Netscaler](build-netscaler) images with the **netlab clab build** command. BIRD and VPP FD.io build process supports configurable software releases.
* The Arista cEOS image has to be [downloaded and installed manually](ceos.md).
* Nokia SR OS and SR-SIM container images require a license; see also [vrnetlab instructions](https://containerlab.srlinux.dev/manual/vrnetlab/).
* Follow Cisco's documentation to install the IOS XRd container, making sure the container image name matches the one _netlab_ uses (alternatively, [change the default image name](default-device-image) for the IOS XRd container).
Expand Down Expand Up @@ -433,13 +434,14 @@ server.

```{eval-rst}
.. toctree::
:caption: Installing Container Images
:caption: Building and Installing Container Images
:maxdepth: 1
:hidden:

ceos.md
bird.md
linux.md
netscaler.md
vpp.md
..
```
38 changes: 38 additions & 0 deletions docs/labs/vpp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(build-vpp)=
# Using a VPP Container

VPP is a [containerlab](lab-clab) device using a locally built **netlab/vpp:latest** image.

* Build the container with `netlab clab build vpp`
* Pin the FD.io release with **defaults.devices.vpp.clab.sw_version** (optional; latest release is used by default), then run `netlab clab build vpp`
* Use `device: vpp` in the lab topology

VPP nodes default to the **router** role and also support the **bridge** role. They do not support the **host** role.

The image installs VPP packages from the FD.io Packagecloud repository selected with **defaults.devices.vpp.clab.repo** (default: `release`).

(vpp-control-plane)=
## Control Plane

VPP runs a Linux control-plane daemon in the dataplane network namespace. The default is **bird**; set **control_plane** to **frr** when you need FRRouting (for example IS-IS).

Lab-wide default:

```
defaults.devices.vpp.control_plane: frr
```

Per-node override:

```
nodes:
r1:
device: vpp
control_plane: frr
```

Version pin example:

```
defaults.devices.vpp.clab.sw_version: 25.06-release
```
2 changes: 2 additions & 0 deletions docs/netlab/clab.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ $ netlab clab build bird --version 2.17.4 --tag netlab/bird:latest

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 [](build-bird) for the **--version** parameter and [](build-vpp) for pinning the FD.io release with **defaults.devices.vpp.clab.sw_version**.

(netlab-clab-cleanup)=
## Docker Cleanup

Expand Down
1 change: 1 addition & 0 deletions docs/netlab/defaults.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ You can also use glob expressions to select the parameters you want to display.
$ netlab defaults '*clab.image'
daemons.bird.clab.image = netlab/bird:latest
daemons.dnsmasq.clab.image = netlab/dnsmasq:latest
devices.vpp.clab.image = netlab/vpp:latest
devices.arubacx.clab.image = vrnetlab/vr-aoscx:20240129204649
devices.cat8000v.clab.image = vrnetlab/vr-c8000v:17.13.01a
devices.csr.clab.image = vrnetlab/cisco_csr1000v:17.03.08
Expand Down
12 changes: 12 additions & 0 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
| Nokia SR-SIM [❗](caveats-srsim) | srsim | full |
| OpenBSD [❗](caveats-openbsd) | openbsd | best effort |
| Sonic [❗](caveats-sonic) | sonic | minimal |
| VPP (fd.io) [❗](caveats-vpp) | vpp | minimal |
| VyOS 1.4 [❗](caveats-vyos) | vyos | full |

[^SROSBE]: With the launch of the Nokia SR SIM, we stopped running integration tests for the SR-OS VM, assuming the behavior of the two products would be nearly identical.
Expand Down Expand Up @@ -89,6 +90,7 @@ Most devices behave as routers (or layer-3 switches); the following devices can
| Generic Linux | ❌ | ✅ | ✅ |
| Kubernetes in Docker | ❌ | ✅ | ❌ |
| Open BSD | ✅ | ✅ | ❌ |
| VPP | ✅ | ❌ | ✅ |

**Notes:**

Expand Down Expand Up @@ -145,6 +147,7 @@ You cannot use all supported network devices with all virtualization providers.
| Nokia SR-SIM | ❌ | ✅ |
| OpenBSD | [✅](build-openbsd) | [✅](clab-vrnetlab) |
| Sonic | [✅](build-sonic) | ❌ |
| VPP | ❌ | ✅ |
| VyOS | ✅ | ✅[❗](caveats-vyos) |

**Note:**
Expand Down Expand Up @@ -211,6 +214,7 @@ Ansible playbooks included with **netlab** can deploy and collect device configu
| Nokia SR OS[^SROS] | ✅ | ✅ |
| OpenBSD | ✅ | ❌ |
| Sonic | ✅ | ✅ |
| VPP FD.io | ✅ | ❌ |
| VyOS | ✅ | ✅ |

**Note:** *netlab* can deploy daemon configurations, but cannot collect them. Use the **netlab initial -o** command to create daemon configuration files in a custom directory.
Expand All @@ -228,6 +232,9 @@ Ansible playbooks included with **netlab** can deploy and collect device configu
(platform-config-mode)=
_netlab_ uses Ansible playbooks and device-specific task lists to deploy device configuration snippets onto most devices, with these notable exceptions:

:::{table}
:class: table-wrap

| Device | Provider | Configuration deployment method |
|--------|----------|---------------------------------|
| bird | clab | **bash** scripts or daemon configuration files[^BBS] |
Expand All @@ -236,6 +243,8 @@ _netlab_ uses Ansible playbooks and device-specific task lists to deploy device
| Junos cRPD | clab | **bash** scripts[^cRBS] |
| KinD | clab | **bash** scripts copied into and executed in containers |
| linux | clab | host- or container-side **bash** scripts[^LBS] |
| vpp | clab | **bash** scripts, node configuration files, and VPP CLI configuration files[^VPPC] |
:::

[^FRRBV]: Configurations starting with a *shebang* are assumed to be Linux scripts; all other configurations are assumed to be **vtysh** scripts and get a `#!/usr/bin/vtysh -f` shebang prepended to them.

Expand All @@ -245,6 +254,8 @@ _netlab_ uses Ansible playbooks and device-specific task lists to deploy device

[^DBS]: Initial device configurations, VLANs, static routes, and link aggregation are configured with **bash** scripts. All other features are configured with the dnsmasq configuration files.

[^VPPC]: Initial device configuration is deployed with **bash** scripts executed within the container. VPP **startup.conf** is deployed as a node configuration file. The VPP startup configuration loads `/etc/vpp/config/setup.vpp`, a generated VPP CLI configuration file; the initial script creates `/etc/vpp/config/clab-interfaces.vpp`. The container waits for **netlab initial** to finish before starting VPP.

[^cRBS]: The configuration deployment uses a custom **bash** script that calls **cli** command to execute **load merge** followed by **commit**. The custom script is used as the *shebang* interpreter for the configuration snippets.

Several other devices can use alternate (faster) configuration methods that are not enabled by default; you have to set the **netlab_config_mode** group variable[^NCMGV] or node parameter to use them:
Expand Down Expand Up @@ -358,6 +369,7 @@ The following interface addresses are supported on various platforms; most daemo
| Nokia SR OS[^SROS] | ✅ | ✅ | ✅ | ❌ |
| OpenBSD | ✅ | ✅ | ❌ | ❌ |
| Sonic | ✅ | ✅ | ✅ | ❌ |
| VPP | ✅ | ✅ | ✅ | ✅ |
| VyOS | ✅ | ✅ | ✅ | ❌ |

```{tip}
Expand Down
34 changes: 34 additions & 0 deletions netsim/ansible/templates/initial/vpp.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{% from '_extra_initial.j2' import extra_initial with context %}
#!/usr/bin/env bash
#

NETNS=${NETNS:="dataplane"}
CLAB_VPP_FILE="/etc/vpp/config/clab-interfaces.vpp"

echo "Creating dataplane namespace"
/usr/bin/mkdir -p /etc/netns/$NETNS
/usr/bin/touch /etc/netns/$NETNS/resolv.conf
/usr/sbin/ip netns add $NETNS
/usr/bin/nsenter --net=/run/netns/$NETNS /usr/sbin/ip link set lo up

echo "Generating $CLAB_VPP_FILE"
mkdir -p $(dirname $CLAB_VPP_FILE)
: > $CLAB_VPP_FILE
MTU=9216
for IFNAME in $(ip -br link | awk '{ print $1 }' | cut -f1 -d@ | grep -E '^eth[1-9][0-9]*$' | sort); do
MAC=$(ip -br link show dev $IFNAME | awk '{ print $3 }')
echo " * $IFNAME hw-addr $MAC mtu $MTU"
ip link set $IFNAME up mtu $MTU
cat << EOF >> $CLAB_VPP_FILE
create host-interface name $IFNAME hw-addr $MAC
set interface mtu $MTU host-$IFNAME
set interface state host-$IFNAME up

EOF
done

{{ extra_initial() }}

touch /var/run/initial.done

exit 0
63 changes: 63 additions & 0 deletions netsim/ansible/templates/initial/vpp.vlan.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{#
Create VPP VLAN objects (bridge-domains, trunk subifs, BVIs). Access-port
bridge assignment lives in vlan/vpp.j2. Routed subif LCP peers are created
by lcp-auto-subint after netlab-start aligns parent TAP MACs with host-*.
BVI must be attached to its BD immediately after create; BVI still needs
an explicit lcp create.
#}
{% for vname,vdata in vlans|default({})|dictsort
if vdata.mode|default('irb') != 'route' %}
create bridge-domain {{ vdata.id }}
{% endfor %}
{% for ifdata in interfaces if ifdata.type|default('') == 'vlan_member'
and ifdata.vlan.access_id is defined
and ifdata.parent_ifname is defined %}
{% set vpp_if = 'host-' ~ ifdata.ifname %}
create sub-interfaces host-{{ ifdata.parent_ifname }} {{ ifdata.vlan.access_id }}
{% if ifdata.mtu is defined %}
set interface mtu {{ ifdata.mtu }} {{ vpp_if }}
{% endif %}
set interface state {{ vpp_if }} up
{% if ifdata.vlan.mode|default('irb') == 'route' %}
{% if ifdata.ipv4 is defined and ifdata.ipv4 is string %}
set interface ip address {{ vpp_if }} {{ ifdata.ipv4 }}
{% endif %}
{% if ifdata.ipv6 is defined and ifdata.ipv6 is string and ifdata.ipv6|ansible.utils.ipv6 %}
set interface ip address {{ vpp_if }} {{ ifdata.ipv6 }}
{% if role == 'router' %}
{% if ifdata.ra.disable|default(false) is true %}
ip6 nd {{ vpp_if }} ra-suppress
{% else %}
ip6 nd {{ vpp_if }} ra-interval 5
{% set nd_prefix = ifdata.ipv6|ansible.utils.ipaddr(0) %}
ip6 nd {{ vpp_if }} prefix {{ nd_prefix }} default
{% endif %}
{% endif %}
{% endif %}
{# LCP for VLAN subifs comes from lcp-auto-subint on the parent #}
{% endif %}
{% endfor %}
{% for ifdata in interfaces if ifdata.type|default('') == 'svi'
and ((ifdata.ipv4 is defined and ifdata.ipv4 is string)
or (ifdata.ipv6 is defined and ifdata.ipv6 is string)) %}
{% set bd = vlans[ifdata.vlan.name].id %}
bvi create instance {{ bd }}
set interface l2 bridge bvi{{ bd }} {{ bd }} bvi
set interface state bvi{{ bd }} up
{% if ifdata.ipv4 is defined and ifdata.ipv4 is string %}
set interface ip address bvi{{ bd }} {{ ifdata.ipv4 }}
{% endif %}
{% if ifdata.ipv6 is defined and ifdata.ipv6 is string and ifdata.ipv6|ansible.utils.ipv6 %}
set interface ip address bvi{{ bd }} {{ ifdata.ipv6 }}
{% if role == 'router' %}
{% if ifdata.ra.disable|default(false) is true %}
ip6 nd bvi{{ bd }} ra-suppress
{% else %}
ip6 nd bvi{{ bd }} ra-interval 5
{% set nd_prefix = ifdata.ipv6|ansible.utils.ipaddr(0) %}
ip6 nd bvi{{ bd }} prefix {{ nd_prefix }} default
{% endif %}
{% endif %}
{% endif %}
lcp create bvi{{ bd }} host-if {{ ifdata.ifname }}
{% endfor %}
1 change: 1 addition & 0 deletions netsim/ansible/templates/mpls/vpp.initial.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sysctl -w net.mpls.platform_labels=1048575
1 change: 1 addition & 0 deletions netsim/ansible/templates/mpls/vpp.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mpls table add 0
16 changes: 16 additions & 0 deletions netsim/ansible/templates/vlan/vpp.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{#
VPP interface VLAN parameters (access/trunk membership). Bridge-domains,
subinterfaces, and BVIs (including BVI-to-BD attach) are created in
initial/vpp.vlan.j2.
#}
{% for ifdata in interfaces if ifdata.type|default('') == 'vlan_member'
and ifdata.vlan.access_id is defined
and ifdata.vlan.mode|default('irb') != 'route' %}
set interface l2 tag-rewrite host-{{ ifdata.ifname }} pop 1
{% endfor %}
{% for ifdata in interfaces if ifdata.vlan is defined and ifdata.type|default('') != 'svi' %}
{% set vname = ifdata.vlan.access|default(ifdata.vlan.native) %}
{% if vname is defined and vlans[vname].mode|default('irb') != 'route' %}
set interface l2 bridge host-{{ ifdata.ifname }} {{ vlans[vname].id }}
{% endif %}
{% endfor %}
3 changes: 2 additions & 1 deletion netsim/daemons/bird/bird.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ log stderr all;
{% include 'radv.j2' %}
{% endif %}

{% for k,v in _daemon_config.items() if k != device|default(netlab_device_type) and not v.endswith('.sh') %}
{% for k,v in _daemon_config.items()
if k not in [device|default(netlab_device_type), 'bird'] and v.endswith('.conf') %}
include "{{ v }}";
{% endfor %}
Loading