A few readability fixes
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-05-04 17:30:04 +02:00
parent 4f81d377a0
commit 0972cf4aa1

View File

@ -61,19 +61,19 @@ CMD ["/sbin/init-container.sh"]
``` ```
A few notable additions: A few notable additions:
* ***vppcfg*** is the utility I wrote and described in a previous [[article]({{< ref * ***vppcfg*** is a handy utility I wrote and discussed in a previous [[article]({{< ref
2022-04-02-vppcfg-2 >}})]. It's purpose is to take YAML file that describes the configuration of 2022-04-02-vppcfg-2 >}})]. Its purpose is to take YAML file that describes the configuration of
the dataplane (like which interfaces, sub-interfaces, MTU, IP addresses and so on), and apply the dataplane (like which interfaces, sub-interfaces, MTU, IP addresses and so on), and then
this safely to a running dataplane. You can check it out in the apply this safely to a running dataplane. You can check it out in my
[[vppcfg](https://git.ipng.ch/ipng/vppcfg)] git repository. [[vppcfg](https://git.ipng.ch/ipng/vppcfg)] git repository.
* ***openssh-server*** will come in handy to log in to the container, in addition to the already * ***openssh-server*** will come in handy to log in to the container, in addition to the already
available `docker exec`. available `docker exec`.
* ***bird2*** which will be my controlplane of choice. In a future date, I might also add FRR, * ***bird2*** which will be my controlplane of choice. At a future date, I might also add FRR,
which may be a good alterantive for some. VPP works well with both. You can check out Bird on which may be a good alterantive for some. VPP works well with both. You can check out Bird on
the nic.cz [[website](https://bird.network.cz/?get_doc&f=bird.html&v=20)]. the nic.cz [[website](https://bird.network.cz/?get_doc&f=bird.html&v=20)].
I'll add a couple of default config files for Bird and VPP, and replace the CMD with a generic I'll add a couple of default config files for Bird and VPP, and replace the CMD with a generic
`init-container.sh` in which I can do any late binding stuff. `/sbin/init-container.sh` in which I can do any late binding stuff before launching VPP.
### Initializing the Container ### Initializing the Container
@ -93,7 +93,8 @@ echo "Creating dataplane namespace"
#### VPP Containerlab: SSH #### VPP Containerlab: SSH
Then, I'll set the root password and start aan SSH daemon which allows for password-less logins: Then, I'll set the root password (which is `vpp` by the way), and start aan SSH daemon which allows
for password-less logins:
``` ```
echo "Starting SSH, with credentials root:vpp" echo "Starting SSH, with credentials root:vpp"
@ -104,8 +105,9 @@ sed -i -e 's,^root:.*,root:$y$j9T$kG8pyZEVmwLXEtXekQCRK.$9iJxq/bEx5buni1hrC8Vmvk
#### VPP Containerlab: Bird2 #### VPP Containerlab: Bird2
I can already predict that Bird2 won't be the only option for a controlplane. Therefore, I'll make I can already predict that Bird2 won't be the only option for a controlplane, even though I'm a huge
it configurable: fan of it. Therefore, I'll make it configurable to leave the door open for other controlplane
implementations in the future:
``` ```
BIRD_ENABLED=${BIRD_ENABLED:="true"} BIRD_ENABLED=${BIRD_ENABLED:="true"}
@ -120,20 +122,21 @@ if [ "$BIRD_ENABLED" == "true" ]; then
fi fi
``` ```
I remember that Bird won't start if it cannot determine its _router id_. When I start it in the I am reminded that Bird won't start if it cannot determine its _router id_. When I start it in the
`dataplane` namespace, it will immediately exit. But luckily, it logs its complaint and it's easily `dataplane` namespace, it will immediately exit, because there will be no IP addresses configured
addressed. I decide to take the management IPv4 address, from `eth0` and write that into the yet. But luckily, it logs its complaint and it's easily addressed. I decide to take the management
`bird.conf` file, which does some basic initialization which I've described in a previous IPv4 address from `eth0` and write that into the `bird.conf` file, which otherwise does some basic
[[article]({{< ref 2021-09-02-vpp-5 >}})], so I'll skip that here. However, I do include an empty initialization that I described in a previous [[article]({{< ref 2021-09-02-vpp-5 >}})], so I'll
file called `/etc/bird/bird-local.conf` for users to further configure Bird2. skip that here. However, I do include an empty file called `/etc/bird/bird-local.conf` for users to
further configure Bird2.
#### VPP Containerlab: Binding veth pairs #### VPP Containerlab: Binding veth pairs
When Containerlab starts the VPP container, it'll offer it a set of `veth` ports that connect this When Containerlab starts the VPP container, it'll offer it a set of `veth` ports that connect this
container to any other node in the lab. This is done by the `links` list in the topology file container to other nodes in the lab. This is done by the `links` list in the topology file
[[ref](https://containerlab.dev/manual/network/)]. It's my goal to take all of the interfaces [[ref](https://containerlab.dev/manual/network/)]. It's my goal to take all of the interfaces
that are of type `veth`, and generate a little snippet to grab them and bind them into VPP, as that are of type `veth`, and generate a little snippet to grab them and bind them into VPP while
follows: setting their MTU to 9216 to allow for jumbo frames:
``` ```
CLAB_VPP_FILE=${CLAB_VPP_FILE:=/etc/vpp/clab.vpp} CLAB_VPP_FILE=${CLAB_VPP_FILE:=/etc/vpp/clab.vpp}
@ -155,6 +158,12 @@ EOF
done done
``` ```
{{< image width="5em" float="left" src="/assets/shared/warning.png" alt="Warning" >}}
One thing I realized is that VPP will assign a random MAC address on its copy of the `veth` port,
which is not great. I'll explicitly configure it with the same MAC address as the `veth` interface
itself, otherwise I'd have to put the interface into promiscuous mode.
#### VPP Containerlab: VPPcfg #### VPP Containerlab: VPPcfg
I'm almost ready, but I have one more detail. The user will be able to offer a I'm almost ready, but I have one more detail. The user will be able to offer a
@ -171,8 +180,8 @@ if [ -r /etc/vpp/vppcfg.yaml ]; then
fi fi
``` ```
Once VPP starts, it'll execute `/etc/vpp/bootstrap.vpp`, which in turn executes these newly Once the VPP process starts, it'll execute `/etc/vpp/bootstrap.vpp`, which in turn executes these
generated `/etc/vpp/clab.vpp` to grab the `veth` interfaces, and then `/etc/vpp/vppcfg.vpp` to newly generated `/etc/vpp/clab.vpp` to grab the `veth` interfaces, and then `/etc/vpp/vppcfg.vpp` to
further configure the dataplane. Easy peasy! further configure the dataplane. Easy peasy!
### Adding VPP to Containerlab ### Adding VPP to Containerlab
@ -183,7 +192,8 @@ get me started. I fork the repo, create a branch so that Roman can also add a fe
together we start hacking in [[PR#2571](https://github.com/srl-labs/containerlab/pull/2571)]. together we start hacking in [[PR#2571](https://github.com/srl-labs/containerlab/pull/2571)].
First, I add the documentation skeleton in `docs/manual/kinds/fdio_vpp.md`, which links in from a First, I add the documentation skeleton in `docs/manual/kinds/fdio_vpp.md`, which links in from a
few other places, and will be where the end-user facing documentation will live. few other places, and will be where the end-user facing documentation will live. That's about half
the contributed LOC, right there!
Next, I'll create a Go module in `nodes/fdio_vpp/fdio_vpp.go` which doesn't do much other than Next, I'll create a Go module in `nodes/fdio_vpp/fdio_vpp.go` which doesn't do much other than
creating the `struct`, and its required `Register` and `Init` functions. The `Init` function ensures creating the `struct`, and its required `Register` and `Init` functions. The `Init` function ensures
@ -196,10 +206,10 @@ So, containerlab informs the container using an environment variable called `CLA
script simply sleeps for a while until that exact amount of interfaces are present. Ok, cool beans. script simply sleeps for a while until that exact amount of interfaces are present. Ok, cool beans.
Roman helps me a bit with Go templating. You see, I think it'll be slick to have the CLI prompt for Roman helps me a bit with Go templating. You see, I think it'll be slick to have the CLI prompt for
the VPP containers to reflect their hostname, because normally, VPP will assign `vpp# `. When the VPP containers to reflect their hostname, because normally, VPP will assign `vpp# `. I add the
running many VPP containers in the lab, it could get confusing. So, I add the template in template in `nodes/fdio_vpp/vpp_startup_config.go.tpl` and it only has one variable expansion: `unix
`nodes/fdio_vpp/vpp_startup_config.go.tpl` and it only has one variable: `cli-prompt {{ .ShortName { cli-prompt {{ .ShortName }}# }`. But I totally think it's worth it, because when running many VPP
}}# `, et voila! containers in the lab, it could otherwise get confusing.
Roman also shows me a trick in the function `PostDeploy()`, which will write the user's SSH pubkeys Roman also shows me a trick in the function `PostDeploy()`, which will write the user's SSH pubkeys
to `/root/.ssh/authorized_keys`. This allows users to log in without having to use password to `/root/.ssh/authorized_keys`. This allows users to log in without having to use password
@ -208,7 +218,7 @@ authentication.
Collectively, we decide to punt on the `SaveConfig` function until we're a bit further along. I have Collectively, we decide to punt on the `SaveConfig` function until we're a bit further along. I have
an idea how this would work, basically along the lines of calling `vppcfg dump` and bind-mounting an idea how this would work, basically along the lines of calling `vppcfg dump` and bind-mounting
that file into the lab directory somewhere. This way, upon restarting, the YAML file can be re-read that file into the lab directory somewhere. This way, upon restarting, the YAML file can be re-read
and the dataplane initialized. and the dataplane initialized. But it'll be for another day.
After the main module is finished, all I have to do is add it to `clab/register.go` and that's just After the main module is finished, all I have to do is add it to `clab/register.go` and that's just
about it. In about 170 lines of code, 50 lines of Go template, and 170 lines of Markdown, this about it. In about 170 lines of code, 50 lines of Go template, and 170 lines of Markdown, this
@ -234,7 +244,7 @@ one Alpine linux container, in the following topology:
{{< image src="/assets/containerlab/learn-vpp.png" alt="Containerlab Topo" width="100%" >}} {{< image src="/assets/containerlab/learn-vpp.png" alt="Containerlab Topo" width="100%" >}}
Two relevant files for VPP are included in this Two relevant files for each VPP router are included in this
[[repository](https://git.ipng.ch/ipng/vpp-containerlab)]: [[repository](https://git.ipng.ch/ipng/vpp-containerlab)]:
1. `config/vpp*/vppcfg.yaml` configures the dataplane interfaces, including a loopback address. 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. 1. `config/vpp*/bird-local.conf` configures the controlplane to enable BFD and OSPF.
@ -261,7 +271,7 @@ loopbacks:
addresses: [ 10.82.98.0/32, 2001:db8:8298::/128 ] addresses: [ 10.82.98.0/32, 2001:db8:8298::/128 ]
``` ```
Then, I enable BFD, OSPF and OSPFv3 on `eth2' and 'loop0` on both of the VPP routers: Then, I enable BFD, OSPF and OSPFv3 on `eth2` and `loop0` on both of the VPP routers:
``` ```
pim@summer:~/src/vpp-containerlab$ cat config/vpp1/bird-local.conf pim@summer:~/src/vpp-containerlab$ cat config/vpp1/bird-local.conf
protocol bfd bfd1 { protocol bfd bfd1 {
@ -287,8 +297,8 @@ protocol ospf v3 ospf6 {
#### Containerlab: playtime! #### Containerlab: playtime!
Once the lab comes up, I can SSH to the VPP containers (`vpp1` and `vpp2`) for which Roman's code Once the lab comes up, I can SSH to the VPP containers (`vpp1` and `vpp2`) which have my SSH pubkeys
saw to it that my SSH keys are installed. Otherwise, I could still log in as user `root` using installed thanks to Roman's work. Barring that, I could still log in as user `root` using
password `vpp`. VPP runs its own network namespace called `dataplane`, which is very similar to SR password `vpp`. VPP runs its own network namespace called `dataplane`, which is very similar to SR
Linux default `network-instance`. I can join that namespace to take a closer look: Linux default `network-instance`. I can join that namespace to take a closer look: