.. _sec_lab_vpp_intro:
Lab: Taking the VPP Container Testbench for a Spin
==================================================
Assuming the reader has already acquired the test bench build scripts, let's
start with building it.
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> make
# Client image.
DOCKER_BUILDKIT=1 docker build \
--file Dockerfile.vpp_testbench \
--build-arg HEALTHCHECK_PORT=8123 \
--tag vpp-testbench-client:local \
--target client_img \
.
...
...
...
DOCKER_BUILDKIT=1 docker build \
--file Dockerfile.vpp_testbench \
--build-arg HEALTHCHECK_PORT=8123 \
--tag vpp-testbench-server:local \
--target server_img \
.
...
...
...
=> exporting to image
=> => exporting layers
=> => writing image
=> => naming to docker.io/library/vpp-testbench-server:local
0.0s
Done.
Now, let's start up our newly built images as a pair of containers. The various
hashes throughout this document will differ from those shown in your own
console (perfectly fine). First, let's assume there are no running containers
on your system. We'll verify via ``docker ps``:
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
OK: good initial conditions. Now, let's launch the containers:
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> make start
# Create Docker bridge network.
bash -c " . vpp_testbench_helpers.sh; host_only_create_docker_networks; "
6e071e533e239380b2fe92d6e0844c42736ec186226fbb20d89706f9a80f935f
# Launch the containers.
bash -c " . vpp_testbench_helpers.sh; host_only_run_testbench_client_container
vpp-testbench-client:local; host_only_run_testbench_server_container
vpp-testbench-server:local; "
720fed0a94fd715694d73a41317f05a3f36860a6d5ae54db2d7cb7f2dcaf7924
ccf166993d09e399f7b10d372c47cc9e72ce6092ef70ea206c699263da844e1b
# Entrypoint scripts will bring up the various links.
# Use "docker ps" to check status of containers, see if their health
# probes are working as expected (i.e. "health"), etc.
Now, we can use ``docker ps`` to verify if the containers are up and running:
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d8e3ab35111 vpp-testbench-server:local "/entrypoint.sh" 3 seconds ago Up 2 seconds (health: starting) vpp-testbench-server
cc01e64b12da vpp-testbench-client:local "/entrypoint.sh" 4 seconds ago Up 3 seconds (health: starting) vpp-testbench-client
Looking good so far. However, note the "health" status of the containers.
They're not yet ready. We can re-execute the ``docker ps`` command occasionally
until the containers are ready:
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> while true; do docker ps; sleep 1; done
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
42e9bcea7c58 vpp-testbench-server:local "/entrypoint.sh" 1 second ago Up Less than a second (health: starting) vpp-testbench-server
710287b40bd3 vpp-testbench-client:local "/entrypoint.sh" 2 seconds ago Up Less than a second (health: starting) vpp-testbench-client
42e9bcea7c58 vpp-testbench-server:local "/entrypoint.sh" 30 seconds ago Up 29 seconds (health: starting) vpp-testbench-server
710287b40bd3 vpp-testbench-client:local "/entrypoint.sh" 31 seconds ago Up 30 seconds (healthy) vpp-testbench-client
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
42e9bcea7c58 vpp-testbench-server:local "/entrypoint.sh" 31 seconds ago Up 30 seconds (healthy) vpp-testbench-server
710287b40bd3 vpp-testbench-client:local "/entrypoint.sh" 32 seconds ago Up 31 seconds (healthy) vpp-testbench-client
Not the most elegant approach, but it works. Onward.
.. note::
How would one automate this step so that we're not having to manually watch
the console until the containers are ready? What's something that we could
put into a script our our ``Makefile`` to poll the containers until they're
ready to use?
.. raw:: html
Spoiler
.. code-block:: shell
# "Direct" approach.
while true; do
[ '"healthy"' = docker inspect --format "{{json .State.Health.Status }}" vpp-testbench-client] && break
done
# Could also use awk/grep/etc. against the output of "docker ps".
.. raw:: html
Now that our containers are up and running, let's drop a shell into the
"client" container:
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> make shell_client
First, let's take a look at the default network configuration.
.. code-block:: shell
:linenos:
root@478ab126035e:/work# ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: vxlan-vid-42: mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 3a:2c:19:cb:ca:35 brd ff:ff:ff:ff:ff:ff
inet 169.254.10.1/24 scope global vxlan-vid-42
valid_lft forever preferred_lft forever
3: vpp-tap-0: mtu 1500 qdisc mq state UNKNOWN group default qlen 1000
link/ether 02:fe:c5:52:63:12 brd ff:ff:ff:ff:ff:ff
inet 169.254.12.1/24 scope global vpp-tap-0
valid_lft forever preferred_lft forever
635: eth0@if636: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:a9:fe:00:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.0.1/24 brd 169.254.0.255 scope global eth0
valid_lft forever preferred_lft forever
Let's also enumerate the interfaces managed by VPP. For the help of the reader,
there is a shell function, ``vc``, which just launches ``vppctl`` with some
helpful default arguments.
.. code-block:: shell
:linenos:
root@478ab126035e:/work# type vc
vc is a function
vc ()
{
vppctl -s "${VPP_SOCK}" "${@}"
}
root@478ab126035e:/work# vc
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
vpp# show int
Name Idx State MTU (L3/IP4/IP6/MPLS) Counter Count
local0 0 down 0/0/0/0
memif0/0 1 up 9000/0/0/0 rx packets 7
rx bytes 521
tx packets 7
tx bytes 503
tap0 2 up 9000/0/0/0 rx packets 7
rx bytes 503
tx packets 7
tx bytes 521
vpp#
.. note::
One more exercise for the reader:
1. From the client container, how would you ping the server container on the
Linux-managed VXLAN interface?
2. From the client container, how would you ping the server container on the
VPP-managed TAP interface?
3. A couple trivial web servers (using ``netcat``) are running on the server
container. Besides looking at the ``Makefile`` recipes, how could one
determine what ports and interfaces these servers are bound to, and
how would one issue an HTTP GET query against them from the client
container? (hint: you're allowed to log-in to the server container via
``make shell_server``, and the ``netstat`` command may be of use).
.. raw:: html
Spoiler
.. code-block:: shell
1. ping 169.254.10.2
2. ping 169.254.12.2
3. make shell_server
netstat -tulpn
tcp 0 0 169.254.12.2:8000 0.0.0.0:*
LISTEN 47/nc
tcp 0 0 169.254.10.2:8000 0.0.0.0:*
LISTEN 34/nc
exit
make shell_client
root@478ab126035e:/work# curl 169.254.10.2:8000
HOST:14f0df855445
DATE:Fri Nov 19 16:36:57 UTC 2021
Hello from the Linux interface.
root@478ab126035e:/work# curl 169.254.12.2:8000
HOST:14f0df855445
DATE:Fri Nov 19 16:37:04 UTC 2021
Hello from the VPP interface.
exit
.. raw:: html
Now that we've done some quick exercises, let's clean-up the containers and
their associated resources.
.. code-block:: shell
:linenos:
vagrant@ubuntu-focal$> make stop
# Terminate the containers.
bash -c " . vpp_testbench_helpers.sh; host_only_kill_testbench_client_container vpp-testbench-client:local; host_only_kill_testbench_server_container vpp-testbench-server:local; "
vpp-testbench-client
Error: No such container: vpp-testbench-client
vpp-testbench-server
Error: No such container: vpp-testbench-server
# Cleanup Docker bridge network.
bash -c " . vpp_testbench_helpers.sh; host_only_destroy_docker_networks; "
vpp-testbench-net
That's it for this section.