A few readability fixes
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@ -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:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user