aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.env36
-rw-r--r--tests/1-node.yml32
-rw-r--r--tests/2-nodes-hicn-light.yml53
-rw-r--r--tests/2-nodes-vpp-bridge.yml114
-rw-r--r--tests/2-nodes-vpp-memif-local-remote.yml116
-rw-r--r--tests/2-nodes-vpp-memif-replication.yml124
-rw-r--r--tests/2-nodes-vpp-memif.yml116
-rw-r--r--tests/2-nodes.yml45
-rw-r--r--tests/Dockerfile.ci40
-rw-r--r--tests/Makefile42
-rw-r--r--tests/build.yml41
-rwxr-xr-xtests/channel.sh22
-rwxr-xr-xtests/config.sh700
-rw-r--r--tests/functional-tests/2-nodes-hicn-light.robot84
-rw-r--r--tests/functional-tests/2-nodes-vpp-bridge.robot53
-rw-r--r--tests/functional-tests/2-nodes-vpp-memif-replication.robot46
-rw-r--r--tests/functional-tests/2-nodes-vpp-memif.robot46
-rw-r--r--tests/functional-tests/hicn-light-control.robot48
-rw-r--r--tests/functional-tests/hicn-light-ping.robot30
-rw-r--r--tests/hiperf-local.sh21
-rw-r--r--tests/resources/libraries/robot/common.robot39
-rw-r--r--tests/resources/libraries/robot/runtest.robot293
-rw-r--r--tests/run-functional.sh40
23 files changed, 2181 insertions, 0 deletions
diff --git a/tests/.env b/tests/.env
new file mode 100644
index 000000000..1e06ca0c8
--- /dev/null
+++ b/tests/.env
@@ -0,0 +1,36 @@
+# Topologies
+TOPOLOGY_1_NODE=1-node
+TOPOLOGY_2_NODES=2-nodes
+
+# Container names
+TEST_LIGHT=hicn-light
+TEST_VPP_BRIDGE=vpp-bridge
+TEST_VPP_MEMIF=vpp-memif
+TEST_VPP_MEMIF_REPLICATION=vpp-memif-replication
+TEST_VPP_MEMIF_LOCALREMOTE=vpp-memif-local-remote
+
+# Names
+RTC_PRODUCER=b002:0:0:0:abcd::/80
+RAAQM_PRODUCER=b002::2
+PING_PRODUCER=b002::3
+RAAQM_PRODUCER_NEW=b002::4
+
+# Test keys
+HMAC_KEY="hunter2"
+
+# Log
+FORWARDER_LOG_PATH=/tmp/forwarder.log
+
+# IP addresses
+TOPOLOGY_2_NODES_IP_NETWORK=192.168.1.0/24
+TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT=192.168.1.2
+TOPOLOGY_2_NODES_IP_ADDRESS_SERVER=192.168.1.3
+TOPOLOGY_2_NODES_IP_GATEWAY=192.168.1.254
+
+TOPOLOGY_2_NODES_IP6_NETWORK=2001::/64
+TOPOLOGY_2_NODES_IP6_ADDRESS_CLIENT=2001::1
+TOPOLOGY_2_NODES_IP6_ADDRESS_SERVER=2001::2
+
+TOPOLOGY_1_NODE_IP_NETWORK=192.168.2.0/24
+TOPOLOGY_1_NODE_IP_ADDRESS=192.168.2.2
+TOPOLOGY_1_NODE_IP_GATEWAY=192.168.2.254
diff --git a/tests/1-node.yml b/tests/1-node.yml
new file mode 100644
index 000000000..9e496d7b8
--- /dev/null
+++ b/tests/1-node.yml
@@ -0,0 +1,32 @@
+version: "3"
+services:
+ client:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ - BASE_IMAGE
+ image: hicn-base
+ container_name: forwarder
+ working_dir: /workspace
+ volumes:
+ - ..:/workspace:z
+ networks:
+ the-network:
+ ipv4_address: ${TOPOLOGY_1_NODE_IP_ADDRESS}
+ entrypoint: [/bin/bash, -ex, -c]
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo hicn-light-daemon --log-file /tmp/lite_client.log
+
+networks:
+ the-network:
+ driver: bridge
+ ipam:
+ config:
+ - subnet: ${TOPOLOGY_1_NODE_IP_NETWORK}
+ gateway: ${TOPOLOGY_1_NODE_IP_GATEWAY}
diff --git a/tests/2-nodes-hicn-light.yml b/tests/2-nodes-hicn-light.yml
new file mode 100644
index 000000000..849432464
--- /dev/null
+++ b/tests/2-nodes-hicn-light.yml
@@ -0,0 +1,53 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_LIGHT}-client
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ tee -a /tmp/hicn-light.conf <<EOF
+ add listener udp local0 ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT} 9199 eth0
+ add connection udp conn0 ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT} 9199 ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER} 9199
+ add route conn0 b002::/64 1
+ EOF
+
+ rm -f ${FORWARDER_LOG_PATH}
+
+ sudo hicn-light-daemon \
+ --daemon \
+ --log-file ${FORWARDER_LOG_PATH} \
+ --config /tmp/hicn-light.conf
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_LIGHT}-server
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ tee -a /tmp/hicn-light.conf <<EOF
+ add listener udp local0 ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER} 9199 eth0
+ add connection udp conn0 ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER} 9199 ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT} 9199
+ EOF
+
+ rm -f ${FORWARDER_LOG_PATH}
+
+ sudo hicn-light-daemon \
+ --daemon \
+ --log-file ${FORWARDER_LOG_PATH} \
+ --config /tmp/hicn-light.conf --capacity 0
+
+ sleep 4
+
+ hiperf -q -z hicnlight_module -S -R -B 4000kbps ${RTC_PRODUCER} -P 2 -k ${HMAC_KEY} &
+ hiperf -q -z hicnlight_module -S ${RAAQM_PRODUCER}/128 &
+ hiperf -q -z hicnlight_module -S ${RAAQM_PRODUCER_NEW}/128 &
+ hicn-ping-server -z hicnlight_module -s 0 -n ${PING_PRODUCER}/128 &
+
+ tail -f /dev/null
diff --git a/tests/2-nodes-vpp-bridge.yml b/tests/2-nodes-vpp-bridge.yml
new file mode 100644
index 000000000..e9d0cf809
--- /dev/null
+++ b/tests/2-nodes-vpp-bridge.yml
@@ -0,0 +1,114 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_BRIDGE}-client
+ cap_add:
+ - NET_ADMIN
+ devices:
+ - /dev/net/tun:/dev/net/tun
+ - /dev/vhost-net:/dev/vhost-net
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip link set br0 up
+ sudo ip link set eth0 master br0
+ sudo ip addr del ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT}/24 dev eth0
+
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ create tap id 0 host-bridge br0
+ set int state tap0 up
+ set int ip addr tap0 ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT}/24
+ set int ip addr tap0 ${TOPOLOGY_2_NODES_IP6_ADDRESS_CLIENT}/64
+ ip route add b002::1/64 via ${TOPOLOGY_2_NODES_IP6_ADDRESS_SERVER} tap0
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+ sudo vppctl hicn enable b002::1/64
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_VPP_BRIDGE}-server
+ cap_add:
+ - NET_ADMIN
+ devices:
+ - /dev/net/tun:/dev/net/tun
+ - /dev/vhost-net:/dev/vhost-net
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo ip link add br0 type bridge
+ sudo ip link set br0 up
+ sudo ip link set eth0 master br0
+ sudo ip addr del ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER}/24 dev eth0
+
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ create tap id 0 host-bridge br0
+ set int state tap0 up
+ set int ip addr tap0 ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER}/24
+ set int ip addr tap0 ${TOPOLOGY_2_NODES_IP6_ADDRESS_SERVER}/64
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 -k ${HMAC_KEY} &
+ sleep 1
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
+ sleep 1
+ sudo hicn-ping-server -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
+
+ tail -f /dev/null
diff --git a/tests/2-nodes-vpp-memif-local-remote.yml b/tests/2-nodes-vpp-memif-local-remote.yml
new file mode 100644
index 000000000..90f4b9ebc
--- /dev/null
+++ b/tests/2-nodes-vpp-memif-local-remote.yml
@@ -0,0 +1,116 @@
+version: "3"
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_MEMIF}-client
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ buffers { buffers-per-numa 600000 }
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip master
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT}/24
+ set int ip addr memif1/0 ${TOPOLOGY_2_NODES_IP6_ADDRESS_CLIENT}/64
+ comment { Add route }
+ ip route add ${RAAQM_PRODUCER}/128 via ${TOPOLOGY_2_NODES_IP6_ADDRESS_SERVER} memif1/0
+ EOF
+
+ sudo rm /memif/memif1.sock
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
+ sleep 1
+
+ sudo vppctl hicn strategy set 3 prefix ${RAAQM_PRODUCER}/128
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_VPP_MEMIF}-server
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ buffers { buffers-per-numa 600000 }
+
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip slave
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER}/24
+ set int ip addr memif1/0 ${TOPOLOGY_2_NODES_IP6_ADDRESS_SERVER}/64
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
+
+ tail -f /dev/null
diff --git a/tests/2-nodes-vpp-memif-replication.yml b/tests/2-nodes-vpp-memif-replication.yml
new file mode 100644
index 000000000..f74757aac
--- /dev/null
+++ b/tests/2-nodes-vpp-memif-replication.yml
@@ -0,0 +1,124 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_MEMIF_REPLICATION}-client
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ buffers { buffers-per-numa 600000 }
+ plugins {
+ path /hicn-root/lib/vpp_plugins:/usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:01 master
+ set int state memif1/0 up
+ set int ip addr memif1/0 192.168.1.1/24
+ set int ip addr memif1/0 2001::1/64
+ set ip neighbor memif1/0 2001::2 aa:bb:cc:dd:ee:02 static
+ ip route add b002::1/64 via 2001::2 memif1/0
+ create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:01 master
+ set int state memif1/1 up
+ set int ip addr memif1/1 192.168.2.1/24
+ set int ip addr memif1/1 2002::1/64
+ set ip neighbor memif1/1 2002::2 aa:bb:bb:bb:ee:02 static
+ ip route add b002::1/64 via 2002::2 memif1/1
+ EOF
+
+ sudo rm /memif/memif1.sock
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo vppctl hicn enable b002::1/64
+ sudo vppctl hicn strategy set 2 prefix b002::/64
+
+ tail -f /dev/null
+ server:
+ container_name: ${TEST_VPP_MEMIF_REPLICATION}-server
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ buffers { buffers-per-numa 600000 }
+
+ plugins {
+ path /hicn-root/lib/vpp_plugins:/usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:02 slave
+ set int state memif1/0 up
+ set int ip addr memif1/0 192.168.1.2/24
+ set int ip addr memif1/0 2001::2/64
+ set ip neighbor memif1/0 2001::1 aa:bb:cc:dd:ee:01 static
+ create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:02 slave
+ set int state memif1/1 up
+ set int ip addr memif1/1 192.168.2.2/24
+ set int ip addr memif1/1 2002::2/64
+ set ip neighbor memif1/1 2002::1 aa:bb:bb:bb:ee:01 static
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 10
+
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 -k ${HMAC_KEY} &
+ sleep 5
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
+ sleep 5
+ sudo hicn-ping-server -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
+
+ tail -f /dev/null
diff --git a/tests/2-nodes-vpp-memif.yml b/tests/2-nodes-vpp-memif.yml
new file mode 100644
index 000000000..7240f8b2c
--- /dev/null
+++ b/tests/2-nodes-vpp-memif.yml
@@ -0,0 +1,116 @@
+version: "3"
+services:
+ client:
+ container_name: ${TEST_VPP_MEMIF}-client
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 1 }
+ buffers { buffers-per-numa 600000 }
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+
+ unix {
+ startup-config /etc/vpp/client-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/client-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip master
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 192.168.1.1/24
+ set int ip addr memif1/0 2001::1/64
+ comment { Add route }
+ ip route add b002::1/64 via 2001::2 memif1/0
+ EOF
+
+ sudo rm /memif/memif1.sock
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 5
+
+ sudo vppctl hicn enable b002::1/64
+
+ tail -f /dev/null
+
+ server:
+ container_name: ${TEST_VPP_MEMIF}-server
+ networks: []
+ volumes:
+ - /tmp/memif:/memif:z
+ - ..:/workspace:z
+ command:
+ - |
+ if [ -d /workspace/build-dev ]; then
+ sudo ninja -C /workspace/build-dev install
+ fi
+
+ sudo mkdir -p /var/log/vpp
+ sudo tee /etc/vpp/startup.conf <<EOF
+ cpu { main-core 2 }
+ buffers { buffers-per-numa 600000 }
+
+ plugins {
+ path /usr/lib/$$(arch)-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins
+ plugin default { disable }
+ plugin acl_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin dhcp_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin dns_plugin.so { enable }
+ plugin ping_plugin.so { enable }
+ plugin memif_plugin.so { enable }
+ plugin nsim_plugin.so { enable }
+ plugin hicn_plugin.so { enable }
+ }
+ unix {
+ startup-config /etc/vpp/server-up.txt
+ cli-listen /run/vpp/cli.sock
+ log ${FORWARDER_LOG_PATH}
+ }
+ EOF
+
+ sudo tee /etc/vpp/server-up.txt <<EOF
+ comment { Creating memif }
+ create memif socket id 1 filename /memif/memif1.sock
+ create interface memif id 0 socket-id 1 mode ip slave
+ set int state memif1/0 up
+ comment { Configuring memif }
+ set int ip addr memif1/0 192.168.1.2/24
+ set int ip addr memif1/0 2001::2/64
+ EOF
+
+ sudo vpp -c /etc/vpp/startup.conf
+ sleep 10
+
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 -k ${HMAC_KEY} &
+ sleep 5
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
+ sleep 5
+ sudo hicn-ping-server -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
+
+ tail -f /dev/null
diff --git a/tests/2-nodes.yml b/tests/2-nodes.yml
new file mode 100644
index 000000000..51b9aeb89
--- /dev/null
+++ b/tests/2-nodes.yml
@@ -0,0 +1,45 @@
+version: "3"
+services:
+ client:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ - BASE_IMAGE
+ hostname: client
+ privileged: false
+ working_dir: /workspace
+ networks:
+ p2p-link:
+ ipv4_address: ${TOPOLOGY_2_NODES_IP_ADDRESS_CLIENT}
+ volumes:
+ - ..:/workspace:z
+ entrypoint: [/bin/bash, -x, -c]
+ command:
+ - tail -f /dev/null
+
+ server:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ args:
+ - BASE_IMAGE
+ hostname: server
+ privileged: false
+ working_dir: /workspace
+ networks:
+ p2p-link:
+ ipv4_address: ${TOPOLOGY_2_NODES_IP_ADDRESS_SERVER}
+ volumes:
+ - ..:/workspace:z
+ entrypoint: [/bin/bash, -x, -c]
+ command:
+ - tail -f /dev/null
+
+networks:
+ p2p-link:
+ driver: bridge
+ ipam:
+ config:
+ - subnet: ${TOPOLOGY_2_NODES_IP_NETWORK}
+ gateway: ${TOPOLOGY_2_NODES_IP_GATEWAY}
diff --git a/tests/Dockerfile.ci b/tests/Dockerfile.ci
new file mode 100644
index 000000000..b4c03f7e3
--- /dev/null
+++ b/tests/Dockerfile.ci
@@ -0,0 +1,40 @@
+FROM ubuntu:focal
+
+ARG DEBIAN_FRONTEND=noninteractive
+ARG DEB_FOLDER="./packages"
+
+WORKDIR /hicn-release
+
+################################################################
+# Copy DEB files
+################################################################
+COPY ${DEB_FOLDER} deb
+
+################################################################
+# Install VPP and hicn debs
+################################################################
+ARG VERSION_PATH=/tmp/versions.cmake
+COPY versions.cmake ${VERSION_PATH}
+ARG INSTALL_VPP_SCRIPT=/tmp/install-vpp.sh
+COPY scripts/install-vpp.sh ${INSTALL_VPP_SCRIPT}
+
+RUN bash -x ${INSTALL_VPP_SCRIPT} \
+ && cd deb \
+ && apt-get install -y \
+ iproute2 sudo \
+ ./libhicn_*.deb \
+ ./hicn-light_*.deb \
+ ./hicn-plugin_*.deb \
+ ./libhicnctrl_*.deb \
+ ./libhicnctrl-modules_*.deb \
+ ./libhicntransport-io-modules_*.deb \
+ ./libhicntransport_*.deb \
+ ./facemgr_*.deb \
+ ./hicn-apps_*.deb \
+ && rm ${VERSION_PATH} \
+ && rm -rf deb \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y \
+ && apt-get clean
+
+WORKDIR /
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 000000000..a31a6f1a6
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,42 @@
+# Use when building for the first time,
+# then `make test` forces a rebuild if local changes
+build:
+ DOCKERFILE=Dockerfile.dev BUILD_SOFTWARE=1 \
+ docker-compose -f build.yml up --force-recreate --remove-orphans
+
+# Rebuild from scratch (to avoid cmake cache)
+rebuild:
+ DOCKERFILE=Dockerfile.dev BUILD_SOFTWARE=1 \
+ REBUILD=1 \
+ docker-compose -f build.yml up --force-recreate --remove-orphans
+
+# Force base image creation from scratch
+rebase:
+ DOCKERFILE=Dockerfile.dev \
+ docker-compose -f build.yml build --pull --no-cache
+
+# If local changes, hicn is re-built
+test:
+ docker-compose -f 1-node.yml up --force-recreate --remove-orphans -d
+
+log:
+ docker exec forwarder tail -f -n +1 /tmp/lite_client.log
+
+shell:
+ docker exec -it forwarder bash
+
+down:
+ docker-compose -f 1-node.yml down
+
+functional-ctrl:
+ sleep 1 # Wait for the forwarder to be ready
+ bash config.sh ctrl listeners
+ bash config.sh ctrl connections
+ bash config.sh ctrl routes
+
+functional-ping-manifest:
+ bash config.sh ping manifest
+functional-ping-signature:
+ bash config.sh ping signature
+functional-ping-timeout:
+ bash config.sh ping timeout \ No newline at end of file
diff --git a/tests/build.yml b/tests/build.yml
new file mode 100644
index 000000000..859262632
--- /dev/null
+++ b/tests/build.yml
@@ -0,0 +1,41 @@
+version: "3"
+services:
+ dev:
+ build:
+ context: ..
+ dockerfile: ${DOCKERFILE}
+ image: hicn-base
+ stdin_open: true
+ tty: true
+ working_dir: /workspace
+ container_name: dev
+ hostname: dev
+ environment:
+ - BUILD_SOFTWARE
+ volumes:
+ - ..:/workspace:z
+ entrypoint: [/bin/bash, -ex, -c]
+ command:
+ - |
+ whoami
+
+ if [[ "${BUILD_SOFTWARE}" -ne 1 ]]; then
+ exit 0
+ fi
+
+ if [[ ! -z "${REBUILD}" ]]; then
+ rm -fr build-dev
+ fi
+
+ git config --global --add safe.directory \*
+
+ mkdir -p build-dev
+ cd build-dev
+ cmake -G Ninja \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DBUILD_APPS=ON \
+ -DBUILD_TESTS=ON \
+ -DENABLE_RELY=OFF \
+ -DBUILD_HICNPLUGIN=ON ..
+ sudo ninja install
diff --git a/tests/channel.sh b/tests/channel.sh
new file mode 100755
index 000000000..59335da65
--- /dev/null
+++ b/tests/channel.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+set -e
+
+DEV=$2
+RATE=$3mbit
+DELAY=$4ms
+JITTER=$5ms
+LOSS=$6
+
+if [[ $1 -eq "set" ]]; then
+ tc qdisc add dev "$DEV" root handle 1:0 htb default 1
+ tc class add dev "$DEV" parent 1:0 classid 1:1 htb rate "$RATE"
+ tc qdisc add dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY"
+ "$JITTER" loss random "$LOSS"
+ echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%"
+elif [[ $1 -eq "change" ]]; then
+ tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" "$JITTER" loss random "$LOSS"
+ echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%"
+else
+ echo "set or change"
+fi
diff --git a/tests/config.sh b/tests/config.sh
new file mode 100755
index 000000000..00d148e42
--- /dev/null
+++ b/tests/config.sh
@@ -0,0 +1,700 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+SCRIPT_PATH=$(
+ cd "$(dirname "${BASH_SOURCE}")"
+ pwd -P
+)
+
+# Import test configurations and names
+source ${SCRIPT_PATH}/.env
+
+set -a
+DOCKERFILE=${DOCKERFILE:-Dockerfile.dev}
+BUILD_SOFTWARE=${BUILD_SOFTWARE:-1}
+PRIVILEGED=${TEST_PRIVILEGED:-false}
+set +a
+
+HIPERF_CMD_RTC="ENABLE_LOG_PREFIX=OFF /usr/bin/hiperf -q -n 50 -C -H -R ${RTC_PRODUCER} -P 2 -k ${HMAC_KEY}"
+HIPERF_CMD_MEMIF_RTC="${HIPERF_CMD_RTC} -z memif_module"
+POSTPROCESS_COMMAND_RAAQM_RTC='tail -n +3 | \
+ tr -s " " | \
+ cut -f 4 -d " " | \
+ sort -n | \
+ tail -n 40 | \
+ head -n 35 | \
+ awk "BEGIN { \
+ c=0; \
+ s=0; \
+ }{ \
+ a[n++]=\$1; \
+ s+=\$1; \
+ } END { \
+ print int(a[0]), int(a[n-1]), int(s/n) \
+ }"'
+
+HIPERF_CMD_RAAQM="ENABLE_LOG_PREFIX=OFF /usr/bin/hiperf -q -n 50 -i 200 -C -H ${RAAQM_PRODUCER}"
+HIPERF_CMD_RAAQM_NEW="ENABLE_LOG_PREFIX=OFF /usr/bin/hiperf -q -n 50 -i 200 -C -H ${RAAQM_PRODUCER_NEW} -w new"
+HIPERF_CMD_CBR="${HIPERF_CMD_RAAQM} -W 350 -M 0"
+HIPERF_CMD_CBR_NEW="${HIPERF_CMD_RAAQM_NEW} -W 350 -M 0"
+HIPERF_CMD_MEMIF_RAAQM="${HIPERF_CMD_RAAQM} -z memif_module"
+HIPERF_CMD_MEMIF_CBR="${HIPERF_CMD_CBR} -z memif_module"
+
+PING_CMD="ENABLE_LOG_PREFIX=OFF LOG_LEVEL=1 hicn-ping-client -m 50 -i 200000 -n ${PING_PRODUCER}"
+PING_CMD_NEW="ENABLE_LOG_PREFIX=OFF LOG_LEVEL=1 hicn-ping-client -m 50 -i 200000 -n ${PING_PRODUCER} -w new"
+PING_CMD_MEMIF="${PING_CMD} -z memif_module"
+POSTPROCESS_COMMAND_PING='grep trip | \
+ cut -f 4 -d " " | \
+ sort -n | \
+ tail -n 40 | \
+ head -n 35 | \
+ awk "BEGIN { \
+ c=0; \
+ s=0; \
+ }{ \
+ a[n++]=\$1; \
+ s+=\$1; \
+ } END { \
+ print int(a[0]), int(a[n-1]), int(s/n) \
+ }"'
+
+declare -a topologies
+declare -a configurations
+
+# Fill topology array using the same values in the .env file
+for topology in $(compgen -A variable | grep TOPOLOGY_); do
+ topologies+=("${!topology}")
+done
+
+# Fill configurations array using the same values in the .env file
+for test in $(compgen -A variable | grep TEST_); do
+ configurations+=("${!test}")
+done
+
+declare -A tests=(
+ ["hicn-light-rtc"]="${HIPERF_CMD_RTC} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-rtc"]="${HIPERF_CMD_MEMIF_RTC} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-rtc"]="${HIPERF_CMD_MEMIF_RTC} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-rtc"]="${HIPERF_CMD_MEMIF_RTC} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-requin"]="${HIPERF_CMD_RAAQM} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["hicn-light-requin-new-packet-format"]="${HIPERF_CMD_RAAQM_NEW} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-requin"]="${HIPERF_CMD_MEMIF_RAAQM} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-requin"]="${HIPERF_CMD_MEMIF_RAAQM} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-requin"]="${HIPERF_CMD_MEMIF_RAAQM} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-cbr"]="${HIPERF_CMD_CBR} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["hicn-light-cbr-new-packet-format"]="${HIPERF_CMD_CBR_NEW} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-bridge-cbr"]="${HIPERF_CMD_MEMIF_CBR} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-cbr"]="${HIPERF_CMD_MEMIF_CBR} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+ ["vpp-memif-replication-cbr"]="${HIPERF_CMD_MEMIF_CBR} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}"
+
+ ["hicn-light-latency"]="${PING_CMD} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-bridge-latency"]="${PING_CMD_MEMIF} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-memif-latency"]="${PING_CMD_MEMIF} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["vpp-memif-replication-latency"]="${PING_CMD_MEMIF} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+ ["hicn-light-latency-new-packet-format"]="${PING_CMD_NEW} 2>&1 | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}"
+)
+
+declare -A link_model=(
+ ["500-0-0-0"]="500 0 0 0"
+ ["500-1-0-0"]="500 1 0 0"
+ ["500-5-0-0"]="500 5 0 0"
+ ["500-200-0-0"]="500 200 0 0"
+ ["100-1-0-0"]="100 1 0 0"
+ ["100-10-0-0"]="100 10 0 0"
+ ["100-15-0-0"]="100 15 0 0"
+ ["200-5-0-0"]="200 5 0 0"
+ ["300-5-0-0"]="300 5 0 0"
+ ["400-5-0-0"]="400 5 0 0"
+ ["1000-1-0-0"]="1000 1 0 0"
+ ["10-50-1-10"]="10 50 1 10"
+)
+
+function topology_exists() {
+ [[ "${topologies[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function test_exists() {
+ [[ "${!tests[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function conf_exists() {
+ [[ "${configurations[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+# test-name client/server link-model
+function setchannel() {
+ topology=${1}
+ configuration=${2}
+ service=${3}
+ device=${4}
+
+ if ! conf_exists "${configuration}"; then
+ error "Error: topology does not exist."
+ fi
+
+ local DOCKER_COMMAND="docker-compose -f ${topology}.yml -f ${topology}-${configuration}.yml exec -T"
+ ${DOCKER_COMMAND} "${service}" bash -c "/workspace/tests/config.sh link set ${device} ${link_model[${3}]}"
+}
+
+# test-name client/server link-model
+function changechannel() {
+ topology=${1}
+ configuration=${2}
+ service=${3}
+ device=${4}
+
+ if ! conf_exists "${configuration}"; then
+ error "Error: topology does not exist."
+ fi
+
+ local DOCKER_COMMAND="docker-compose -f ${topology}.yml -f ${topology}-${configuration}.yml exec -T"
+ ${DOCKER_COMMAND} "${service}" bash -c "/workspace/tests/config.sh link change ${device} ${link_model[${3}]}"
+}
+
+# channel set/change dev rate delay jitter lossrate
+function channel() {
+ DEV=${2}
+ RATE=${3}mbit
+ DELAY=${4}ms
+ JITTER=${5}ms
+ LOSS=${6}
+ if [[ $1 == set ]]; then
+ sudo tc qdisc add dev "${DEV}" root handle 1:0 htb default 1
+ sudo tc class add dev "${DEV}" parent 1:0 classid 1:1 htb rate "$RATE"
+ sudo tc qdisc add dev "${DEV}" parent 1:1 handle 2:0 netem delay "${DELAY}" \
+ "${JITTER}" loss random "${LOSS}"
+ echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%"
+ elif [[ ${1} == change ]]; then
+ sudo tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" \
+ "${JITTER}" loss random "${LOSS}"
+ echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%"
+ else
+ sudo tc qdisc del dev "${DEV}" root
+ echo "set or change"
+ fi
+}
+
+function error() {
+ echo >&2 "${@}"
+ return 1
+}
+
+function build() {
+ docker-compose -f build.yml build
+ docker-compose -f build.yml up --force-recreate --remove-orphans
+}
+
+function setup() {
+ topology=${1}
+ conf=${2}
+
+ if ! topology_exists "${topology}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if [[ "${topology}" == "1-node" && "${conf}" == "None" ]]; then
+ docker-compose -f "${topology}".yml build
+ docker-compose -f "${topology}".yml up --remove-orphans --force-recreate -d
+
+ sleep 1
+ return
+ fi
+
+ if ! conf_exists "${conf}"; then
+ error "Error: topology conf does not exist."
+ fi
+
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml build
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml up --remove-orphans --force-recreate -d
+
+ sleep 10
+
+ # Check logs
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml logs
+}
+
+function start() {
+ topology=${1}
+ conf=${2}
+ test=${3}
+
+ if ! conf_exists "${conf}"; then
+ error "Error: configuration does not exist."
+ fi
+
+ TESTNAME="${conf}-${test}"
+
+ if ! test_exists "${TESTNAME}"; then
+ error "Error: test does not exist."
+ fi
+
+ local DOCKER_COMMAND="docker-compose -f ${topology}.yml -f ${topology}-${conf}.yml exec -T"
+
+ ${DOCKER_COMMAND} client bash -x /workspace/tests/config.sh runtest "${tests[${TESTNAME}]}"
+
+ # Print also forwader log
+ echo "Forwarder Log - CLIENT"
+ ${DOCKER_COMMAND} client sudo cat "${FORWARDER_LOG_PATH}"
+
+ echo
+
+ echo "Forwarder Log - SERVER"
+ ${DOCKER_COMMAND} server sudo cat "${FORWARDER_LOG_PATH}"
+}
+
+function stop() {
+ topology="${1}"
+ conf="${2}"
+
+ if ! topology_exists "${topology}"; then
+ error "Error: topology does not exist."
+ fi
+
+ if [[ "${topology}" == "1-node" && "${conf}" == "None" ]]; then
+ docker-compose -f "${topology}".yml down || true
+ return
+ fi
+
+ if ! conf_exists "${conf}"; then
+ error "Error: tect configuration does not exist."
+ fi
+
+ LOG_FILE="${SCRIPT_PATH}/${topology}-${conf}.log"
+ rm -f "${LOG_FILE}"
+ docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml down || true
+}
+
+function stopall() {
+ for topology in "${topologies[@]}"; do
+ for conf in "${configurations[@]}"; do
+ stop "${topology}" "${conf}"
+ done
+ done
+}
+
+function runtest() {
+ echo "${@}" | sudo -i
+}
+
+################################################################
+# Test commands (hicn-light-control)
+################################################################
+INTERFACE="eth0"
+ADDRESS="${TOPOLOGY_1_NODE_IP_ADDRESS}"
+LISTENER_NAME="udp0"
+LISTENER_NAME_2="udp1"
+CONN_NAME="conn0"
+CONN_NAME_2="conn1"
+PREFIX="b001::/16"
+COST=1
+
+#---------------------------------------------------------------
+# Helpers
+#---------------------------------------------------------------
+
+DOCKER_COMMAND="docker-compose -f 1-node.yml exec -T client"
+
+function exec_command() {
+ command=$1
+
+ output=$(${DOCKER_COMMAND} hicn-light-control "$command" 2>&1)
+ echo "$output"
+}
+
+function assert_cmd_success() {
+ command=$1
+ output=$(exec_command "${command}")
+
+ if [[ -z "$output" ]]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ exit 0
+ fi
+}
+
+function assert_cmd_failure() {
+ command=$1
+ output=$(exec_command "${command}")
+
+ if [[ ! -z "$output" ]]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ exit 0
+ fi
+}
+
+#---------------------------------------------------------------
+# Tests for listeners, connections, routes
+#---------------------------------------------------------------
+function test_listeners() {
+ echo -n "Add listeners: "
+ command="add listener udp $LISTENER_NAME $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add listener udp $LISTENER_NAME_2 127.0.0.1 12345 $INTERFACE"
+ assert_cmd_success "${command}"
+
+ echo -n "List listeners: "
+ command="list listener"
+ output=$(exec_command "${command}")
+
+ if [[ "${output}" =~ "udp0 inet4://${ADDRESS}:9695" &&
+ "${output}" =~ "udp1 inet4://127.0.0.1:12345" &&
+ "${output}" =~ "interface=lo" &&
+ "${output}" =~ "interface=$INTERFACE" &&
+ ! "${output}" =~ "ERROR" ]]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ echo $output
+ exit 0
+ fi
+
+ echo -n "Remove listener using symbolic: "
+ command="remove listener $LISTENER_NAME"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove listener using ID: "
+ command="remove listener 2"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove non-existing listener using symbolic: "
+ command="remove listener $LISTENER_NAME_2"
+ assert_cmd_failure "${command}"
+
+ echo -n "Remove non-existing listener using ID: "
+ command="remove listener 5"
+ assert_cmd_failure "${command}"
+
+ echo -n "Add duplicated listener (same symbolic): "
+ command="add listener udp $LISTENER_NAME $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add listener udp $LISTENER_NAME 127.0.0.1 12345 $INTERFACE"
+ assert_cmd_failure "${command}"
+
+ echo -n "Add duplicated listener (same endpoints): "
+ command="add listener udp $LISTENER_NAME $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add listener udp $LISTENER_NAME_2 $ADDRESS 9695 $INTERFACE"
+ assert_cmd_failure "${command}"
+}
+
+function test_connections() {
+ echo -n "Add connections: "
+ command="add listener udp $LISTENER_NAME $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add connection udp $CONN_NAME $ADDRESS 9695 $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add connection udp $CONN_NAME_2 $ADDRESS 9695 $ADDRESS 12345 $INTERFACE"
+ assert_cmd_success "${command}"
+
+ echo -n "List connections: "
+ command="list connection"
+ output=$(exec_command "${command}")
+
+ if [[ "${output}" =~ "inet4://${ADDRESS}:12345" &&
+ "${output}" =~ "inet4://${ADDRESS}:9695" &&
+ "${output}" =~ "conn0" && "${output}" =~ "conn1" &&
+ ! "${output}" =~ "ERROR" ]]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ echo $output
+ exit 0
+ fi
+
+ echo -n "Remove connection using symbolic: "
+ command="remove connection $CONN_NAME"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove connection using ID: "
+ command="remove connection 2"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove non-existing connection using symbolic: "
+ command="remove connection $CONN_NAME"
+ assert_cmd_failure "${command}"
+
+ echo -n "Remove non-existing connection using ID: "
+ command="remove connection 5"
+ assert_cmd_failure "${command}"
+
+ echo -n "Add duplicated connection (same symbolic): "
+ command="add connection udp $CONN_NAME $ADDRESS 9695 $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add connection udp $CONN_NAME $ADDRESS 12345 $ADDRESS 9695 $INTERFACE"
+ assert_cmd_failure "${command}"
+
+ # This case is allowed, success code is returned and symbolic is not updated
+ echo -n "Add duplicated connection (different symbolic, same endpoints): "
+ command="add connection udp $CONN_NAME_2 $ADDRESS 9695 $ADDRESS 9695 $INTERFACE"
+ assert_cmd_success "${command}"
+}
+
+function test_routes() {
+ echo -n "Add route: "
+ command="add listener udp $LISTENER_NAME $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add connection udp $CONN_NAME $ADDRESS 9695 $ADDRESS 9695 $INTERFACE"
+ _=$(exec_command "${command}")
+ command="add route $CONN_NAME $PREFIX $COST"
+ assert_cmd_success "${command}"
+
+ echo -n "List routes: "
+ command="list route"
+ output=$(exec_command "${command}")
+
+ if [[ "${output}" =~ "b001::" && "${output}" =~ "16" &&
+ ! "${output}" =~ "ERROR" ]]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ echo "$output"
+ exit 0
+ fi
+
+ echo -n "Remove route using symbolic: "
+ command="remove route $CONN_NAME $PREFIX"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove route using ID: "
+ command="add route $CONN_NAME $PREFIX $COST"
+ _=$(exec_command "${command}")
+ command="remove route 1 $PREFIX"
+ assert_cmd_success "${command}"
+
+ echo -n "Remove non-existing route using symbolic: "
+ command="remove connection $CONN_NAME $PREFIX"
+ assert_cmd_failure "${command}"
+
+ echo -n "Remove non-existing route using ID: "
+ command="remove route 5 $PREFIX"
+ assert_cmd_failure "${command}"
+
+ echo -n "Add route and face without interface"
+ command="add route $PREFIX $COST udp $ADDRESS 9695 127.0.0.1 9695 $INTERFACE"
+ assert_cmd_success "${command}"
+
+ echo -n "Add route and face without interface"
+ command="add route $PREFIX $COST udp $ADDRESS 9695 127.0.0.1 9695"
+ assert_cmd_success "${command}"
+}
+
+declare -A ctrl_tests=(
+ ["listeners"]="test_listeners"
+ ["connections"]="test_connections"
+ ["routes"]="test_routes"
+)
+
+function ctrl_test_exists() {
+ [[ "${!ctrl_tests[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function ctrl() {
+ type=$1
+ if ! ctrl_test_exists "${type}"; then
+ error "Error: hicn-light-contrl test does not exist."
+ exit 1
+ fi
+
+ ${ctrl_tests[${type}]}
+}
+
+################################################################
+# Test ping
+################################################################
+function test_ping_manifest() {
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-server -a intmanifest >/tmp/ping_server.log 2>&1 &'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each (1 in header + 2 in manifest)
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 6 -a 2 intmanifest 2>&1 | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 single interest
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 7 -a 2 intmanifest 2>&1 | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 interest w/ 2 suffixes
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 8 -a 2 intmanifest 2>&1 | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 single interest,
+ # using random prefix/suffix generation
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 7 -a 2 intmanifest -b RANDOM 2>&1 | grep "Sent" >>/tmp/ping_client.log'
+
+ # No 'failed' expected
+ ping_server_logs=$(${DOCKER_COMMAND} cat /tmp/ping_server.log)
+ if [[ $(echo $ping_server_logs | grep failed | wc -l) -ne 0 ]]; then
+ echo "******** Server logs (ping) ********"
+ echo "$ping_server_logs"
+ exit 1
+ fi
+
+ # No 'Timeouts: 0' expected
+ ping_client_logs=$(${DOCKER_COMMAND} cat /tmp/ping_client.log)
+ if [[ $(echo $ping_client_logs | grep -v "Timeouts: 0" | wc -l) -ne 0 ]]; then
+ echo "******** Client logs (ping) ********"
+ echo "$ping_client_logs"
+ exit 1
+ fi
+}
+
+function test_ping_wrong_signature() {
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-server -a intmanifest >/tmp/ping_server.log 2>&1 &'
+ sleep 1
+
+ # Signature mismatch ('intmamifest' on server vs 'wrong_sign' on client)
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 6 -a 2 wrong_sig'
+
+ # 'failed' expected
+ ping_server_logs=$(${DOCKER_COMMAND} cat /tmp/ping_server.log)
+ if [[ $(echo $ping_server_logs | grep "failed" | wc -l) -eq 0 ]]; then
+ echo "******** Server logs (signature fail) ********"
+ echo "$ping_server_logs"
+ exit 1
+ fi
+}
+
+function test_ping_no_server() {
+ # Server not started to check for ping client timeout
+ ${DOCKER_COMMAND} bash -c 'hicn-ping-client -m 6 2>&1 | grep "Sent" >/tmp/ping_client.log'
+
+ # 'Timeouts: 6' expected
+ ping_client_logs=$(${DOCKER_COMMAND} cat /tmp/ping_client.log)
+ if [[ $(echo $ping_client_logs | grep "Timeouts: 6" | wc -l) -eq 0 ]]; then
+ echo "******** Client logs (timeout) ********"
+ echo "$ping_client_logs"
+ exit 1
+ fi
+}
+
+declare -A ping_tests=(
+ ["manifest"]="test_ping_manifest"
+ ["signature"]="test_ping_wrong_signature"
+ ["timeout"]="test_ping_no_server"
+)
+
+function ping_test_exists() {
+ [[ "${!ping_tests[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function ping() {
+ type=$1
+ if ! ping_test_exists "${type}"; then
+ error "Error: hicn-ping test does not exist."
+ exit 1
+ fi
+
+ ${ping_tests[${type}]}
+}
+
+#---------------------------------------------------------------
+# Tests for local-remote strategy
+#---------------------------------------------------------------
+
+function localremote() {
+ local DOCKER_COMMAND="docker-compose -f 2-nodes.yml -f 2-nodes-vpp-memif-local-remote.yml exec -T"
+
+ ${DOCKER_COMMAND} "client" sudo bash -c "${HIPERF_CMD_MEMIF_CBR}"
+ ${DOCKER_COMMAND} "client" sudo /usr/bin/vppctl hicn face show > /tmp/output
+
+ # Check that producer face has received 0 packets
+ INTEREST_TX="$(cat /tmp/output | grep -A 9 producer | grep "Interest tx" | awk '{print $4}')"
+ INTEREST_TX="${INTEREST_TX%%[[:cntrl:]]}"
+ if [[ ${INTEREST_TX} != "0" ]]; then
+ echo "Received interest on local interface."
+ exit 1
+ fi
+
+ # Check that producer face has sent 0 packets
+ DATA_RX="$(cat /tmp/output | grep -A 9 producer | grep "Data rx" | awk '{print $4}')"
+ DATA_RX="${DATA_RX%%[[:cntrl:]]}"
+ if [[ ${DATA_RX} != "0" ]]; then
+ echo "Received data on local interface."
+ exit 1
+ fi
+
+ # Check that remote face has sent > 0 packets
+ DATA_RX="$(cat /tmp/output | grep -A 9 ${TOPOLOGY_2_NODES_IP6_ADDRESS_CLIENT} | grep "Data rx" | awk '{print $4}')"
+ DATA_RX="${DATA_RX%%[[:cntrl:]]}"
+ if [[ ${DATA_RX} == "0" ]]; then
+ echo "No data received on remote interface."
+ exit 1
+ fi
+
+ # Check that remote face has sent > 0 packets
+ INTEREST_TX="$(cat /tmp/output | grep -A 9 ${TOPOLOGY_2_NODES_IP6_ADDRESS_CLIENT} | grep "Interest tx" | awk '{print $4}')"
+ INTEREST_TX="${INTEREST_TX%%[[:cntrl:]]}"
+ if [[ ${INTEREST_TX} == "0" ]]; then
+ echo "No interest sent on remote interface."
+ exit 1
+ fi
+}
+
+#--------------------------------------------------------------#
+
+while (("${#}")); do
+ case "$1" in
+ 'build')
+ build
+ shift
+ ;;
+ 'link')
+ shift
+ channel "$@"
+ shift 6
+ ;;
+ 'setchannel')
+ shift
+ setchannel "$@"
+ shift 5
+ ;;
+ 'changechannel')
+ shift
+ changechannel "$@"
+ shift 5
+ ;;
+ 'setup')
+ setup "${2}" "${3}"
+ shift 3
+ ;;
+ 'start')
+ start "${2}" "${3}" "${4}"
+ shift 4
+ ;;
+ 'stop')
+ stop "${2}" "${3}"
+ shift 3
+ ;;
+ 'stopall')
+ stopall
+ shift
+ ;;
+ 'runtest')
+ runtest "${@:2}"
+ break
+ ;;
+ 'ctrl')
+ ctrl "${2}"
+ break
+ ;;
+ 'ping')
+ ping "${2}"
+ break
+ ;;
+ 'localremote')
+ localremote
+ break
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+done
+
+exit 0
diff --git a/tests/functional-tests/2-nodes-hicn-light.robot b/tests/functional-tests/2-nodes-hicn-light.robot
new file mode 100644
index 000000000..1686ca9e6
--- /dev/null
+++ b/tests/functional-tests/2-nodes-hicn-light.robot
@@ -0,0 +1,84 @@
+*** Settings ***
+Resource ../resources/libraries/robot/runtest.robot
+Resource ../resources/libraries/robot/common.robot
+
+Suite Setup Run Keywords
+... Build Topology
+... 2-nodes
+... hicn-light
+... AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Throughput Testing Raaqm Mobile
+ Run Throughput Test Raaqm
+ ... 2-nodes
+ ... hicn-light
+ ... 200
+ ... 500
+ ... 400
+
+Throughput Testing Raaqm Mobile New Packet Format
+ Run Throughput Test Raaqm New Packet Format
+ ... 2-nodes
+ ... hicn-light
+ ... 200
+ ... 500
+ ... 400
+
+Throughput Testing CBR Mobile
+ Run Throughput Test CBR
+ ... 2-nodes
+ ... hicn-light
+ ... 20
+ ... 500
+ ... 400
+
+Throughput Testing CBR Mobile New Packet Format
+ Run Throughput Test CBR New Packet Format
+ ... 2-nodes
+ ... hicn-light
+ ... 200
+ ... 500
+ ... 400
+
+RTC Testing Mobile
+ Run RTC Test
+ ... 2-nodes
+ ... hicn-light
+ ... 4
+ ... 4
+ ... 4
+
+Latency Testing Mobile
+ Set Link
+ ... 2-nodes
+ ... hicn-light
+ ... 500
+ ... 1
+ ... 0
+ ... 0
+ Run Latency Test
+ ... 2-nodes
+ ... hicn-light
+ ... 3000
+ ... 3000
+ ... 3000
+
+Latency Testing Mobile New Packet Format
+ Set Link
+ ... 2-nodes
+ ... hicn-light
+ ... 500
+ ... 1
+ ... 0
+ ... 0
+ Run Latency Test New Packet Format
+ ... 2-nodes
+ ... hicn-light
+ ... 3000
+ ... 3000
+ ... 3000
diff --git a/tests/functional-tests/2-nodes-vpp-bridge.robot b/tests/functional-tests/2-nodes-vpp-bridge.robot
new file mode 100644
index 000000000..fd3d42fe0
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-bridge.robot
@@ -0,0 +1,53 @@
+*** Settings ***
+Resource ../resources/libraries/robot/runtest.robot
+Resource ../resources/libraries/robot/common.robot
+
+Suite Setup Run Keywords
+... Build Topology
+... 2-nodes
+... vpp-bridge
+... AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Throughput Testing Raaqm Server VPP bridge
+ Run Throughput Test Raaqm
+ ... 2-nodes
+ ... vpp-bridge
+ ... 500
+ ... 500
+ ... 500
+
+Throughput Testing CBR Server VPP bridge
+ Run Throughput Test CBR
+ ... 2-nodes
+ ... vpp-bridge
+ ... 1000
+ ... 1300
+ ... 1200
+
+RTC Testing Server VPP bridge
+ Run RTC Test
+ ... 2-nodes
+ ... vpp-bridge
+ ... 4
+ ... 4
+ ... 4
+
+Latency Testing Server VPP bridge
+ Set Link
+ ... 2-nodes
+ ... hicn-light
+ ... 500
+ ... 1
+ ... 0
+ ... 0
+ Run Latency Test
+ ... 2-nodes
+ ... vpp-bridge
+ ... 3000
+ ... 3000
+ ... 3000
diff --git a/tests/functional-tests/2-nodes-vpp-memif-replication.robot b/tests/functional-tests/2-nodes-vpp-memif-replication.robot
new file mode 100644
index 000000000..186eb5c94
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-memif-replication.robot
@@ -0,0 +1,46 @@
+*** Settings ***
+Resource ../resources/libraries/robot/runtest.robot
+Resource ../resources/libraries/robot/common.robot
+
+Suite Setup Run Keywords
+... Build Topology
+... 2-nodes
+... vpp-memif-replication
+... AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Throughput Testing Raaqm Server VPP memif replication
+ Run Throughput Test Raaqm
+ ... 2-nodes
+ ... vpp-memif-replication
+ ... 500
+ ... 500
+ ... 500
+
+Throughput Testing CBR Server VPP memif
+ Run Throughput Test CBR
+ ... 2-nodes
+ ... vpp-memif-replication
+ ... 2000
+ ... 2000
+ ... 2000
+
+RTC Testing Server VPP memif replication
+ Run RTC Test
+ ... 2-nodes
+ ... vpp-memif-replication
+ ... 4
+ ... 4
+ ... 4
+
+Latency Testing Server VPP memif replication
+ Run Latency Test
+ ... 2-nodes
+ ... vpp-memif-replication
+ ... 3000
+ ... 3000
+ ... 3000
diff --git a/tests/functional-tests/2-nodes-vpp-memif.robot b/tests/functional-tests/2-nodes-vpp-memif.robot
new file mode 100644
index 000000000..ed9ab1143
--- /dev/null
+++ b/tests/functional-tests/2-nodes-vpp-memif.robot
@@ -0,0 +1,46 @@
+*** Settings ***
+Resource ../resources/libraries/robot/runtest.robot
+Resource ../resources/libraries/robot/common.robot
+
+Suite Setup Run Keywords
+... Build Topology
+... 2-nodes
+... vpp-memif
+... AND
+... Check Environment
+Suite Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Throughput Testing Raaqm Server VPP memif
+ Run Throughput Test Raaqm
+ ... 2-nodes
+ ... vpp-memif
+ ... 500
+ ... 500
+ ... 500
+
+Throughput Testing CBR Server VPP memif
+ Run Throughput Test CBR
+ ... 2-nodes
+ ... vpp-memif
+ ... 2000
+ ... 2000
+ ... 2000
+
+RTC Testing Server VPP memif
+ Run RTC Test
+ ... 2-nodes
+ ... vpp-memif
+ ... 4
+ ... 4
+ ... 4
+
+Latency Testing Server VPP memif
+ Run Latency Test
+ ... 2-nodes
+ ... vpp-memif
+ ... 3000
+ ... 3000
+ ... 3000
diff --git a/tests/functional-tests/hicn-light-control.robot b/tests/functional-tests/hicn-light-control.robot
new file mode 100644
index 000000000..147226188
--- /dev/null
+++ b/tests/functional-tests/hicn-light-control.robot
@@ -0,0 +1,48 @@
+*** Settings ***
+Resource ../resources/libraries/robot/common.robot
+
+Test Setup Run Keywords
+... Build Topology
+... 1-node
+... AND
+... Check Environment
+Test Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Listeners
+ Log to console Test listeners
+ ${result} = Run Process
+ ... bash
+ ... -x
+ ... ${EXECDIR}/config.sh
+ ... ctrl
+ ... listeners
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+ Should Not Contain ${result.stdout} FAILED
+
+Connections
+ Log to console Test connections
+ ${result} = Run Process
+ ... bash
+ ... -x
+ ... ${EXECDIR}/config.sh
+ ... ctrl
+ ... connections
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+ Should Not Contain ${result.stdout} FAILED
+
+Routes
+ Log to console Test routes
+ ${result} = Run Process
+ ... bash
+ ... -x
+ ... ${EXECDIR}/config.sh
+ ... ctrl
+ ... routes
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+ Should Not Contain ${result.stdout} FAILED
diff --git a/tests/functional-tests/hicn-light-ping.robot b/tests/functional-tests/hicn-light-ping.robot
new file mode 100644
index 000000000..ba6beed42
--- /dev/null
+++ b/tests/functional-tests/hicn-light-ping.robot
@@ -0,0 +1,30 @@
+*** Settings ***
+Resource ../resources/libraries/robot/common.robot
+
+Test Setup Run Keywords
+... Build Topology
+... 1-node
+... AND
+... Check Environment
+Test Teardown Run Keywords
+... Destroy Topology
+
+
+*** Test Cases ***
+Ping with manifest
+ Log to console Test ping with manifest
+ ${result} = Run Process bash -x ${EXECDIR}/config.sh ping manifest
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Ping wrong signature
+ Log to console Test ping with wrong signature
+ ${result} = Run Process bash -x ${EXECDIR}/config.sh ping signature
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Ping timeout
+ Log to console Test ping timeout
+ ${result} = Run Process bash -x ${EXECDIR}/config.sh ping timeout
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
diff --git a/tests/hiperf-local.sh b/tests/hiperf-local.sh
new file mode 100644
index 000000000..1ef11eb72
--- /dev/null
+++ b/tests/hiperf-local.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+set -eo pipefail
+
+if [[ "$(basename $(pwd))" != build* ]]; then
+ echo "Error: launch script from build dir"
+ exit 1
+fi
+
+# Stop forwarder and hiperf if already running
+sudo killall -9 hicn-light-daemon hiperf 2>/dev/null || true
+
+# Start forwarder and hiperf server in background
+ninja && sudo ./build-root/bin/hicn-light-daemon --daemon --log-file /tmp/lite_client.log >/dev/null
+./build-root/bin/hiperf -z hicnlightng_module -S b001::/16 &
+
+# Run hiperf client for 20 seconds
+sleep 1
+./build-root/bin/hiperf -z hicnlightng_module -C b001:: -W 50 -n 20
+
+# Clean up
+sudo killall -9 hicn-light-daemon hiperf
diff --git a/tests/resources/libraries/robot/common.robot b/tests/resources/libraries/robot/common.robot
new file mode 100644
index 000000000..921d79b4d
--- /dev/null
+++ b/tests/resources/libraries/robot/common.robot
@@ -0,0 +1,39 @@
+*** Settings ***
+Library OperatingSystem
+Library Process
+Library String
+
+
+*** Keywords ***
+Build Topology
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_CONFIGURATION}=${NONE}
+ Log to console
+ ... Building topology ${TEST_TOPOLOGY} ${TEST_CONFIGURATION}
+ ${result_setup} = Run Process
+ ... ${EXECDIR}/config.sh
+ ... build
+ ... setup
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_CONFIGURATION}
+ ... stdout=${TEMPDIR}/stdout.txt
+ ... stderr=${TEMPDIR}/stderr.txt
+ Log to console Done
+ Log Many
+ ... stdout: ${result_setup.stdout}
+ ... stderr: ${result_setup.stderr}
+ Should Be Equal As Integers ${result_setup.rc} 0
+
+Check Environment
+ ${result} = Run Process docker ps
+ Log Many
+ ... stdout: ${result.stdout}
+ ... stderr: ${result.stderr}
+
+Destroy Topology
+ ${result_teardown} = Run Process ${EXECDIR}/config.sh stopall
+ Log Many
+ ... stdout: ${result_teardown.stdout}
+ ... stderr: ${result_teardown.stderr}
+ Should Be Equal As Integers ${result_teardown.rc} 0
diff --git a/tests/resources/libraries/robot/runtest.robot b/tests/resources/libraries/robot/runtest.robot
new file mode 100644
index 000000000..5ce4787f6
--- /dev/null
+++ b/tests/resources/libraries/robot/runtest.robot
@@ -0,0 +1,293 @@
+*** Settings ***
+Library OperatingSystem
+Library Process
+Library String
+
+
+*** Keywords ***
+Infra ${VALUE}
+ Run Process ${EXECDIR}/config.sh ${VALUE}
+
+Run Test
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${TESTID}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ ${result_test} = Run Process
+ ... ${EXECDIR}/config.sh
+ ... start
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... ${TESTID}
+ ... stdout=${TEMPDIR}/stdout.txt
+ ... stderr=${TEMPDIR}/stderr.txt
+ Log Many stdout: ${result_test.stdout} stderr: ${result_test.stderr}
+ ${min_max_avg_line} = Get Line ${result_test.stdout} 0
+ @{min_max_avg} = Split String ${min_max_avg_line.strip()}
+ Log To Console Min Max Average Array: @{min_max_avg}
+ IF '${TESTID}' == 'rtc'
+ Should Be True
+ ... ${min_max_avg}[0] == ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] != ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] == ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] != ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] == ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] != ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'requin'
+ Should Be True
+ ... ${min_max_avg}[0] >= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] >= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] >= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'requin-new-packet-format'
+ Should Be True
+ ... ${min_max_avg}[0] >= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] >= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] >= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'latency'
+ Should Be True
+ ... ${min_max_avg}[0] <= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] > ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] <= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] > ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] <= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] > ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'latency-new-packet-format'
+ Should Be True
+ ... ${min_max_avg}[0] <= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] > ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] <= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] > ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] <= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] > ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'cbr'
+ Should Be True
+ ... ${min_max_avg}[0] >= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] >= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] >= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE IF '${TESTID}' == 'cbr-new-packet-format'
+ Should Be True
+ ... ${min_max_avg}[0] >= ${EXPECTED_MIN}
+ ... msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})"
+ Should Be True
+ ... ${min_max_avg}[1] >= ${EXPECTED_MAX}
+ ... msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})"
+ Should Be True
+ ... ${min_max_avg}[2] >= ${EXPECTED_AVG}
+ ... msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})"
+ ELSE
+ Fail "Provided Test ID does not exist"
+ END
+
+Set Link
+ [Documentation]
+ ... Configure link rate/delay/jitter/loss
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${RATE} Rate of the link
+ ... ${DELAY} Delay of the link
+ ... ${JITTER} Jitter of the link
+ ... ${LOSS} Loss of the link
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${RATE}=${NONE}
+ ... ${DELAY}=${NONE}
+ ... ${JITTER}=${NONE}
+ ... ${LOSS}=${NONE}
+ ${result_link} = Run Process
+ ... ${EXECDIR}/config.sh
+ ... setchannel
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... server
+ ... eth0
+ ... ${RATE}-${DELAY}-${JITTER}-${LOSS}
+ Log Many stdout: ${result_link.stdout} stderr: ${result_link.stderr}
+
+Run Latency Test
+ [Documentation]
+ ... Run hicn-ping on the \${TEST_SETUP} topology and measure latency.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min latency
+ ... ${EXPECTED_MAX} The expected max latency
+ ... ${EXPECTED_AVG} The expected avg latency
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... latency
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run Throughput Test Raaqm
+ [Documentation]
+ ... Run hiperf on the \${TEST_TOPOLOGY}-\${TEST_SETUP} topology
+ ... and measure throughput.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... requin
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run Throughput Test Raaqm New Packet Format
+ [Documentation]
+ ... Run hiperf on the \${TEST_SETUP} topology and measure throughput.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... requin-new-packet-format
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run Throughput Test CBR
+ [Documentation]
+ ... Run hiperf on the \${TEST_SETUP} topology and measure throughput.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... cbr
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run Throughput Test CBR New Packet Format
+ [Documentation]
+ ... Run hiperf on the \${TEST_SETUP} topology and measure throughput.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min throughput
+ ... ${EXPECTED_MAX} The expected max throughput
+ ... ${EXPECTED_AVG} The expected avg throughput
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... cbr-new-packet-format
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run RTC Test
+ [Documentation]
+ ... Run hiperf RTC on the \${TEST_SETUP} topology and check consumer syncs to
+ ... producer bitrate.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min bitrate
+ ... ${EXPECTED_MAX} The expected max bitrate
+ ... ${EXPECTED_AVG} The expected avg bitrate
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... rtc
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
+
+Run Latency Test New Packet Format
+ [Documentation]
+ ... Run hicn-ping on the \${TEST_SETUP} topology with the new
+ ... packet format and measure latency.
+ ... Arguments:
+ ... ${TEST_TOPOLOGY} The topology of the test.
+ ... ${TEST_SETUP} The setup of the test.
+ ... ${EXPECTED_MIN} The expected min latency
+ ... ${EXPECTED_MAX} The expected max latency
+ ... ${EXPECTED_AVG} The expected avg latency
+ [Arguments]
+ ... ${TEST_TOPOLOGY}=${NONE}
+ ... ${TEST_SETUP}=${NONE}
+ ... ${EXPECTED_MIN}=${NONE}
+ ... ${EXPECTED_MAX}=${NONE}
+ ... ${EXPECTED_AVG}=${NONE}
+ Run Test
+ ... ${TEST_TOPOLOGY}
+ ... ${TEST_SETUP}
+ ... latency-new-packet-format
+ ... ${EXPECTED_MIN}
+ ... ${EXPECTED_MAX}
+ ... ${EXPECTED_AVG}
diff --git a/tests/run-functional.sh b/tests/run-functional.sh
new file mode 100644
index 000000000..34515ac85
--- /dev/null
+++ b/tests/run-functional.sh
@@ -0,0 +1,40 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SCRIPT_PATH=$(
+ cd "$(dirname "${BASH_SOURCE}")"
+ pwd -P
+)
+
+pushd "${SCRIPT_PATH}" || exit 1
+
+declare -a REPORTS
+
+for t in functional-tests/*; do
+ [[ -e "$t" ]] || break # handle the case of no test files
+
+ test=$(basename "$t")
+
+ robot --NoStatusRC \
+ --outputdir report_"${test}" \
+ functional-tests/"${test}"
+
+ REPORTS+=(report_"${test}"/output.xml)
+done
+
+rebot --output output.xml \
+ -l log.html -r report.html \
+ --nostatusrc \
+ "${REPORTS[@]}"
+
+popd || exit 1