blob: 755472a72bff4e7a07f96f414e4f14f645dbbb59 [file] [log] [blame]
#!/bin/bash
################################################################################
# @brief: Launcher/entrypoint script plus helper functions for "server
# side" container in the VPP testbench.
# @author: Matthew Giassa <mgiassa@cisco.com>
# @copyright: (C) Cisco 2021.
################################################################################
################################################################################
# Dependencies.
################################################################################
# Import common settings for server and client. This is supplied via the
# Dockerfile build.
# shellcheck disable=SC1091
. vpp_testbench_helpers.sh
################################################################################
# Globals.
################################################################################
# VPP instance socket.
export VPP_SOCK=/run/vpp/vpp.testbench-server.sock
# Alias for vppctl that uses the correct socket name.
export VPPCTL="vppctl -s ${VPP_SOCK}"
# Our "Docker bridge network". Don't change this value.
export NET_IF_DOCKER="eth0"
# Name of link associated with our VXLAN.
export LINK_VXLAN_LINUX="vxlan-vid-${VXLAN_ID_LINUX}"
################################################################################
# Function definitions.
################################################################################
#------------------------------------------------------------------------------#
# @brief: Alias for vppctl (knowing which API socket to use).
function vc()
{
vppctl -s "${VPP_SOCK}" "${@}"
}
#------------------------------------------------------------------------------#
# @brief: Used to initialize/configure the server container once it's up and
# running.
function context_create()
{
set -x
echo "Running server. Host: $(hostname)"
local mtu
# Setup VXLAN overlay.
ip link add "${LINK_VXLAN_LINUX}" \
type vxlan \
id "${VXLAN_ID_LINUX}" \
dstport "${VXLAN_PORT}" \
local "${SERVER_BRIDGE_IP_DOCKER}" \
group "${MC_VXLAN_ADDR_LINUX}" \
dev "${NET_IF_DOCKER}" \
ttl 1
ip link set "${LINK_VXLAN_LINUX}" up
ip addr add "${SERVER_VXLAN_IP_LINUX}/${MASK_VXLAN_LINUX}" dev "${LINK_VXLAN_LINUX}"
# Get MTU of interface. VXLAN must use a smaller value due to overhead.
mtu="$(cat /sys/class/net/${NET_IF_DOCKER}/mtu)"
# Decrease VXLAN MTU. This should already be handled for us by iproute2, but
# just being cautious.
ip link set dev "${LINK_VXLAN_LINUX}" mtu "$((mtu - 50))"
# Bring-up VPP and create tap interfaces and VXLAN tunnel.
vpp \
unix '{' log /tmp/vpp1.log full-coredump cli-listen ${VPP_SOCK} '}' \
api-segment '{' prefix vpp1 '}' \
api-trace '{' on '}' \
dpdk '{' uio-driver uio_pci_generic no-pci '}'
# Wait for VPP to come up.
while ! ${VPPCTL} show log; do
sleep 1
done
# Bring up the memif interface and assign an IP to it.
${VPPCTL} create interface memif id 0 master
sleep 1
${VPPCTL} set int state memif0/0 up
${VPPCTL} set int ip address memif0/0 "${SERVER_VPP_MEMIF_IP}/${VPP_MEMIF_NM}"
# Create VPP-controlled tap interface bridged to the memif.
${VPPCTL} create tap id 0 host-if-name vpp-tap-0
sleep 1
${VPPCTL} set interface state tap0 up
ip addr add "${SERVER_VPP_TAP_IP_MEMIF}/${VPP_TAP_NM}" dev vpp-tap-0
${VPPCTL} set interface l2 bridge tap0 "${VPP_BRIDGE_DOMAIN_TAP}"
${VPPCTL} set interface l2 bridge memif0/0 "${VPP_BRIDGE_DOMAIN_TAP}"
}
#------------------------------------------------------------------------------#
# @brief: Used to shutdown/cleanup the server container.
function context_destroy()
{
# OS will reclaim interfaces and resources when container is terminated.
:
}
#------------------------------------------------------------------------------#
# @brief: Server worker loop to keep the container alive. Just idles.
function context_loop()
{
# Sleep indefinitely (to keep container alive for testing).
tail -f /dev/null
}
#------------------------------------------------------------------------------#
# @brief: Launches a minimalistic web server via netcat. The Dockerfile
# associated with this project is configured to treat the web server
# replying with "200 OK" as a sort of simple health probe.
function health_check_init()
{
while true; do
echo -e "HTTP/1.1 200 OK\n\nHOST:$(hostname)\nDATE:$(date)" \
| nc -l -p "${DOCKER_HEALTH_PROBE_PORT}" -q 1
done
}
#------------------------------------------------------------------------------#
# @brief: Launches a minimalistic web server via netcat. This instance is
# meant to bind to the Linux VXLAN tunnel we create.
function web_server_vxlan_linux()
{
while true; do
echo -e "HTTP/1.1 200 OK\n\nHOST:$(hostname)\nDATE:$(date)\nHello from the Linux interface." \
| nc -l -s "${SERVER_VXLAN_IP_LINUX}" -p 8000 -q 1
done
}
#------------------------------------------------------------------------------#
# @brief: Launches a minimalistic web server via netcat. This instance is
# meant to bind to the VPP VXLAN tunnel we create.
function web_server_vpp_tap()
{
while true; do
echo -e "HTTP/1.1 200 OK\n\nHOST:$(hostname)\nDATE:$(date)\nHello from the VPP interface." \
| nc -l -s "${SERVER_VPP_TAP_IP_MEMIF}" -p 8000 -q 1
done
}
#------------------------------------------------------------------------------#
# @brief: Main/default entry point.
function main()
{
# Make sure we always cleanup.
trap context_destroy EXIT
# Bring up interfaces.
context_create
# Enable health check responder.
health_check_init &
# Bring up test web servers.
web_server_vxlan_linux &
web_server_vpp_tap &
# Enter our worker loop.
context_loop
}
#------------------------------------------------------------------------------#
# Script is generally intended to be sourced and individual functions called.
# If just run as a standalone script, assume it's being used as the entrypoint
# for a Docker container.
if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then
# Being run. Launch main.
main "${@}"
else
# Being sourced. Do nothing.
:
fi