From 647030927abaff0ee6f3b1e475cf3c4026747b01 Mon Sep 17 00:00:00 2001
From: Pim van Pelt <pim@ipng.nl>
Date: Sun, 4 May 2025 12:42:41 +0200
Subject: [PATCH] Update README to add user guide for a simple containerlab

---
 README.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 76 insertions(+), 13 deletions(-)

diff --git a/README.md b/README.md
index 4eef3f5..fabd5ff 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,75 @@
 # VPP Containerlab Docker image
 
+## Example Containerlab
+
+The file `vpp.clab.yml' contains an example topology existing of two VPP instances connected each to
+one Alpine linux container, in the following topology:
+
+![learn-vpp](learn-vpp.png)
+
+You can deploy it using `containerlab deploy --topo vpp.clab.yml`.
+
+Two relevant files for VPP are included in this repository:
+1.   `config/vpp*/vppcfg.yaml` configures the dataplane interfaces, including a loopback address.
+1.   `config/vpp*/bird-local.conf` configures the controlplane to enable BFD and OSPF.
+
+Once the lab comes up, you can SSH to the VPP containers (`vpp1` and `vpp2`) which will have your
+SSH keys installed (if available). Otherwise, you can log in as user `root` using password `vpp`.
+
+VPP runs its own network namespace called `dataplane`, which is very similar to SR Linux default
+`network-instance`. You can join it to take a look:
+
+```
+pim@summer:~/src/vpp-containerlab$ ssh root@vpp1
+root@vpp1:~# nsenter --net=/var/run/netns/dataplane
+root@vpp1:~# ip -br a
+lo               DOWN           
+loop0            UP             10.82.98.0/32 2001:db8:8298::/128 fe80::dcad:ff:fe00:0/64 
+eth1             UNKNOWN        10.82.98.65/28 2001:db8:8298:101::1/64 fe80::a8c1:abff:fe77:acb9/64 
+eth2             UNKNOWN        10.82.98.16/31 2001:db8:8298:1::1/64 fe80::a8c1:abff:fef0:7125/64 
+
+root@vpp1:~# ping 10.82.98.1 ## The vpp2 IPv4 loopback address
+PING 10.82.98.1 (10.82.98.1) 56(84) bytes of data.
+64 bytes from 10.82.98.1: icmp_seq=1 ttl=64 time=9.53 ms
+64 bytes from 10.82.98.1: icmp_seq=2 ttl=64 time=15.9 ms
+^C
+--- 10.82.98.1 ping statistics ---
+2 packets transmitted, 2 received, 0% packet loss, time 1002ms
+rtt min/avg/max/mdev = 9.530/12.735/15.941/3.205 ms
+```
+
+The two clients are running a minimalistic Alpine Linux container, which doesn't ship with SSH by
+default. You can enter the containers as following:
+
+```
+pim@summer:~/src/vpp-containerlab$ docker exec -it client1 sh
+/ # ip addr show dev eth1
+531235: eth1@if531234: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 9500 qdisc noqueue state UP 
+    link/ether 00:c1:ab:00:00:01 brd ff:ff:ff:ff:ff:ff
+    inet 10.82.98.66/28 scope global eth1
+       valid_lft forever preferred_lft forever
+    inet6 2001:db8:8298:101::2/64 scope global 
+       valid_lft forever preferred_lft forever
+    inet6 fe80::2c1:abff:fe00:1/64 scope link 
+       valid_lft forever preferred_lft forever
+/ # traceroute 10.82.98.82
+traceroute to 10.82.98.82 (10.82.98.82), 30 hops max, 46 byte packets
+ 1  10.82.98.65 (10.82.98.65)  5.906 ms  7.086 ms  7.868 ms
+ 2  10.82.98.17 (10.82.98.17)  24.007 ms  23.349 ms  15.933 ms
+ 3  10.82.98.82 (10.82.98.82)  39.978 ms  31.127 ms  31.854 ms
+
+/ # traceroute 2001:db8:8298:102::2
+traceroute to 2001:db8:8298:102::2 (2001:db8:8298:102::2), 30 hops max, 72 byte packets
+ 1  2001:db8:8298:101::1 (2001:db8:8298:101::1)  0.701 ms  7.144 ms  7.900 ms
+ 2  2001:db8:8298:1::2 (2001:db8:8298:1::2)  23.909 ms  22.943 ms  23.893 ms
+ 3  2001:db8:8298:102::2 (2001:db8:8298:102::2)  31.964 ms  30.814 ms  32.000 ms
+```
+
+From the vantage point of `client1`, hop 1 represents the `vpp1` node, which forwards to `vpp2`,
+which finally forwards to `client2`.
+
+## Developer Documentation
+
 This docker container creates a VPP instance based on the latest VPP release. It starts up as per
 normal, using /etc/vpp/startup.conf (which Containerlab might replace when it starts its
 containers). Once started, it'll execute `/etc/vpp/bootstrap.vpp` within the dataplane. There are
@@ -14,7 +84,7 @@ two relevant files:
 For Containerlab users who wish to have more control over their VPP bootstrap, it's possible to
 bind-mount `/etc/vpp/bootstrap.vpp`.
 
-## Building
+### Building
 
 ```bash
 IMG=git.ipng.ch/ipng/vpp-containerlab
@@ -25,7 +95,7 @@ docker push $IMG
 docker push $IMG:$TAG
 ```
 
-## Testing the container standalone
+### Testing standalone container
 
 ```bash
 docker network create --driver=bridge clab-network --subnet=192.0.2.0/24 \
@@ -39,7 +109,7 @@ docker run --cap-add=NET_ADMIN --cap-add=SYS_NICE --cap-add=SYS_PTRACE \
 docker network connect clab-network clab-pim
 ```
 
-### A note on DPDK
+#### A note on DPDK
 
 DPDK will be disabled by default as it requires hugepages and VFIO and/or UIO to use physical
 network cards. If DPDK at some future point is desired, mapping VFIO can be done by adding this:
@@ -51,8 +121,8 @@ or in Containerlab, using the `devices` feature:
 
 ```
 my-node:
-  image: vpp-containerlab:latest
-  kind: vpp
+  image: git.ipng.ch/ipng/vpp-containerlab:latest
+  kind: fdio_vpp
   devices:
     - /dev/vfio/vfio
     - /dev/net/tun
@@ -71,7 +141,7 @@ $ sudo modprobe uio_pci_generic
 Particularly the VFIO driver needs to be present before one can attempt to bindmount
 `/dev/vfio/vfio` into the container!
 
-## Configuring VPP
+### Configuring VPP
 
 When Containerlab starts the docker containers, it'll offer one or more `veth` point to point
 network links, which will show up as `eth1` and further. `eth0` is the default NIC that belongs to
@@ -101,10 +171,3 @@ to take control over these `veth` pairs.
 In addition, you can add more commands that'll execute on startup by copying in
 `/etc/vpp/manual-pre.vpp` (to be executed _before_ the containerlab stuff) or
 `/etc/vpp/manual-post.vpp` (to be executed _after_ the containerlab stuff).
-
-## Example Containerlab
-
-The file `vpp.clab.yml' contains an example topology existing of two VPP instances connected each to
-one Alpine linux container, in the following topology:
-
-![learn-vpp](learn-vpp.png)