aboutsummaryrefslogtreecommitdiffstats
path: root/docs/usecases/vpp_testbench/src/entrypoint_client.sh
blob: 432c27697305f200f45662034fdd3e1e71756c9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/bash
################################################################################
# @brief:       Launcher/entrypoint script plus helper functions for "client
#               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-client.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 client container once it's up and
#           running.
function context_create()
{
    set -x
    echo "Running client. Host: $(hostname)"
    local mtu

    # Setup VXLAN overlay.
    ip link add "${LINK_VXLAN_LINUX}" \
        type vxlan \
        id "${VXLAN_ID_LINUX}" \
        dstport "${VXLAN_PORT}" \
        local "${CLIENT_BRIDGE_IP_DOCKER}" \
        group "${MC_VXLAN_ADDR_LINUX}" \
        dev "${NET_IF_DOCKER}" \
        ttl 1
    ip link set "${LINK_VXLAN_LINUX}" up
    ip addr add "${CLIENT_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 slave
    sleep 1
    ${VPPCTL} set int state memif0/0 up
    ${VPPCTL} set int ip address memif0/0 "${CLIENT_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 "${CLIENT_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 client container.
function context_destroy()
{
    # OS will reclaim interfaces and resources when container is terminated.
    :
}

#------------------------------------------------------------------------------#
# @brief:   Client 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:   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 &

    # 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