aboutsummaryrefslogtreecommitdiffstats
path: root/app/test/test_link_bonding_mode4.c
diff options
context:
space:
mode:
authorChristian Ehrhardt <christian.ehrhardt@canonical.com>2016-07-06 09:22:35 +0200
committerChristian Ehrhardt <christian.ehrhardt@canonical.com>2016-07-06 16:09:40 +0200
commit8b25d1ad5d2264bdfc2818c7bda74ee2697df6db (patch)
tree8c3c769777f7e66a2d1ba7dd7651b563cfde370b /app/test/test_link_bonding_mode4.c
parent97f17497d162afdb82c8704bf097f0fee3724b2e (diff)
Imported Upstream version 16.07-rc1
Change-Id: I40a523e52f12e8496fdd69e902824b0226c303de Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Diffstat (limited to 'app/test/test_link_bonding_mode4.c')
-rw-r--r--app/test/test_link_bonding_mode4.c215
1 files changed, 206 insertions, 9 deletions
diff --git a/app/test/test_link_bonding_mode4.c b/app/test/test_link_bonding_mode4.c
index 31640cd6..a3f1f088 100644
--- a/app/test/test_link_bonding_mode4.c
+++ b/app/test/test_link_bonding_mode4.c
@@ -151,6 +151,8 @@ static struct rte_eth_conf default_pmd_conf = {
.lpbk_mode = 0,
};
+static uint8_t lacpdu_rx_count[RTE_MAX_ETHPORTS] = {0, };
+
#define FOR_EACH(_i, _item, _array, _size) \
for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
@@ -320,8 +322,26 @@ remove_slave(struct slave_conf *slave)
return 0;
}
+static void
+lacp_recv_cb(uint8_t slave_id, struct rte_mbuf *lacp_pkt)
+{
+ struct ether_hdr *hdr;
+ struct slow_protocol_frame *slow_hdr;
+
+ RTE_VERIFY(lacp_pkt != NULL);
+
+ hdr = rte_pktmbuf_mtod(lacp_pkt, struct ether_hdr *);
+ RTE_VERIFY(hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_SLOW));
+
+ slow_hdr = rte_pktmbuf_mtod(lacp_pkt, struct slow_protocol_frame *);
+ RTE_VERIFY(slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP);
+
+ lacpdu_rx_count[slave_id]++;
+ rte_pktmbuf_free(lacp_pkt);
+}
+
static int
-initialize_bonded_device_with_slaves(uint8_t slave_count, uint8_t start)
+initialize_bonded_device_with_slaves(uint8_t slave_count, uint8_t external_sm)
{
uint8_t i;
@@ -337,9 +357,17 @@ initialize_bonded_device_with_slaves(uint8_t slave_count, uint8_t start)
rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL);
rte_eth_promiscuous_disable(test_params.bonded_port_id);
- if (start)
- TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id),
- "Failed to start bonded device");
+ if (external_sm) {
+ struct rte_eth_bond_8023ad_conf conf;
+
+ rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
+ conf.slowrx_cb = lacp_recv_cb;
+ rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf);
+
+ }
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id),
+ "Failed to start bonded device");
return TEST_SUCCESS;
}
@@ -640,7 +668,7 @@ test_mode4_lacp(void)
{
int retval;
- retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 1);
+ retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
/* Test LACP handshake function */
@@ -738,7 +766,8 @@ test_mode4_rx(void)
struct ether_addr dst_mac;
struct ether_addr bonded_mac;
- retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT, 1);
+ retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT,
+ 0);
TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
retval = bond_handshake();
@@ -915,7 +944,7 @@ test_mode4_tx_burst(void)
struct ether_addr dst_mac = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
struct ether_addr bonded_mac;
- retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1);
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
retval = bond_handshake();
@@ -1099,7 +1128,8 @@ test_mode4_marker(void)
uint8_t i, j;
const uint16_t ethtype_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW);
- retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT, 1);
+ retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT,
+ 0);
TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
/* Test LACP handshake function */
@@ -1184,7 +1214,8 @@ test_mode4_expired(void)
struct rte_eth_bond_8023ad_conf conf;
- retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT, 1);
+ retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT,
+ 0);
/* Set custom timeouts to make test last shorter. */
rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
conf.fast_periodic_ms = 100;
@@ -1266,6 +1297,156 @@ test_mode4_expired(void)
}
static int
+test_mode4_ext_ctrl(void)
+{
+ /*
+ * configure bonded interface without the external sm enabled
+ * . try to transmit lacpdu (should fail)
+ * . try to set collecting and distributing flags (should fail)
+ * reconfigure w/external sm
+ * . transmit one lacpdu on each slave using new api
+ * . make sure each slave receives one lacpdu using the callback api
+ * . transmit one data pdu on each slave (should fail)
+ * . enable distribution and collection, send one data pdu each again
+ */
+
+ int retval;
+ struct slave_conf *slave = NULL;
+ uint8_t i;
+
+ struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
+ struct ether_addr src_mac, dst_mac;
+ struct lacpdu_header lacpdu = {
+ .lacpdu = {
+ .subtype = SLOW_SUBTYPE_LACP,
+ },
+ };
+
+ ether_addr_copy(&parnter_system, &src_mac);
+ ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
+
+ initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
+ ETHER_TYPE_SLOW, 0, 0);
+
+ for (i = 0; i < SLAVE_COUNT; i++) {
+ lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
+ rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
+ &lacpdu, sizeof(lacpdu));
+ rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
+ }
+
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ FOR_EACH_SLAVE(i, slave) {
+ TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx(
+ test_params.bonded_port_id,
+ slave->port_id, lacp_tx_buf[i]),
+ "Slave should not allow manual LACP xmit");
+ TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect(
+ test_params.bonded_port_id,
+ slave->port_id, 1),
+ "Slave should not allow external state controls");
+ }
+
+ free_pkts(lacp_tx_buf, RTE_DIM(lacp_tx_buf));
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Bonded device cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+test_mode4_ext_lacp(void)
+{
+ int retval;
+ struct slave_conf *slave = NULL;
+ uint8_t all_slaves_done = 0, i;
+ uint16_t nb_pkts;
+ const unsigned int delay = bond_get_update_timeout_ms();
+
+ struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
+ struct rte_mbuf *buf[SLAVE_COUNT];
+ struct ether_addr src_mac, dst_mac;
+ struct lacpdu_header lacpdu = {
+ .lacpdu = {
+ .subtype = SLOW_SUBTYPE_LACP,
+ },
+ };
+
+ ether_addr_copy(&parnter_system, &src_mac);
+ ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
+
+ initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
+ ETHER_TYPE_SLOW, 0, 0);
+
+ for (i = 0; i < SLAVE_COUNT; i++) {
+ lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
+ rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
+ &lacpdu, sizeof(lacpdu));
+ rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
+ }
+
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ memset(lacpdu_rx_count, 0, sizeof(lacpdu_rx_count));
+
+ /* Wait for new settings to be applied. */
+ for (i = 0; i < 30; ++i)
+ rte_delay_ms(delay);
+
+ FOR_EACH_SLAVE(i, slave) {
+ retval = rte_eth_bond_8023ad_ext_slowtx(
+ test_params.bonded_port_id,
+ slave->port_id, lacp_tx_buf[i]);
+ TEST_ASSERT_SUCCESS(retval,
+ "Slave should allow manual LACP xmit");
+ }
+
+ nb_pkts = bond_tx(NULL, 0);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly");
+
+ FOR_EACH_SLAVE(i, slave) {
+ nb_pkts = slave_get_pkts(slave, buf, RTE_DIM(buf));
+ TEST_ASSERT_EQUAL(nb_pkts, 1, "found %u packets on slave %d\n",
+ nb_pkts, i);
+ slave_put_pkts(slave, buf, nb_pkts);
+ }
+
+ nb_pkts = bond_rx(buf, RTE_DIM(buf));
+ free_pkts(buf, nb_pkts);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly");
+
+ /* wait for the periodic callback to run */
+ for (i = 0; i < 30 && all_slaves_done == 0; ++i) {
+ uint8_t s, total = 0;
+
+ rte_delay_ms(delay);
+ FOR_EACH_SLAVE(s, slave) {
+ total += lacpdu_rx_count[slave->port_id];
+ }
+
+ if (total >= SLAVE_COUNT)
+ all_slaves_done = 1;
+ }
+
+ FOR_EACH_SLAVE(i, slave) {
+ TEST_ASSERT_EQUAL(lacpdu_rx_count[slave->port_id], 1,
+ "Slave port %u should have received 1 lacpdu (count=%u)",
+ slave->port_id,
+ lacpdu_rx_count[slave->port_id]);
+ }
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+static int
check_environment(void)
{
struct slave_conf *port;
@@ -1381,6 +1562,18 @@ test_mode4_expired_wrapper(void)
return test_mode4_executor(&test_mode4_expired);
}
+static int
+test_mode4_ext_ctrl_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_ext_ctrl);
+}
+
+static int
+test_mode4_ext_lacp_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_ext_lacp);
+}
+
static struct unit_test_suite link_bonding_mode4_test_suite = {
.suite_name = "Link Bonding mode 4 Unit Test Suite",
.setup = test_setup,
@@ -1391,6 +1584,10 @@ static struct unit_test_suite link_bonding_mode4_test_suite = {
TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper),
TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper),
TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper),
+ TEST_CASE_NAMED("test_mode4_ext_ctrl",
+ test_mode4_ext_ctrl_wrapper),
+ TEST_CASE_NAMED("test_mode4_ext_lacp",
+ test_mode4_ext_lacp_wrapper),
TEST_CASES_END() /**< NULL terminate unit test array */
}
/ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
#!/bin/bash
# Copyright (c) 2016 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 ght (c) 2016 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not usecopy 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.

set -x

RETURN_STATUS=0

cat /etc/hostname
cat /etc/hosts

PYBOT_ARGS="--noncritical MULTI_THREAD"

JOB_ARCHIVE_ARTIFACTS=(log.html output.xml report.html)
LOG_ARCHIVE_ARTIFACTS=(log.html output.xml report.html)
JOB_ARCHIVE_DIR="archive"
LOG_ARCHIVE_DIR="$WORKSPACE/archives"
mkdir -p ${JOB_ARCHIVE_DIR}
mkdir -p ${LOG_ARCHIVE_DIR}

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export PYTHONPATH=${SCRIPT_DIR}

# Create tmp dir
mkdir ${SCRIPT_DIR}/tmp

# Use tmp dir to store log files
LOG_PATH="${SCRIPT_DIR}/tmp"

OS_ID=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
OS_VERSION_ID=$(grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')

if [ "$OS_ID" == "centos" ]; then
    DISTRO="CENTOS"
    PACKAGE="rpm"
    sudo yum install -y python-devel python-virtualenv
elif [ "$OS_ID" == "ubuntu" ]; then
    DISTRO="UBUNTU"
    PACKAGE="deb"
    export DEBIAN_FRONTEND=noninteractive
    sudo apt-get -y update
    sudo apt-get -y install libpython2.7-dev python-virtualenv
else
    echo "$OS_ID is not yet supported."
    exit 1
fi

# 1st step: Download and prepare VPP packages

# Temporarily download VPP packages from nexus.fd.io
if [ "${#}" -ne "0" ]; then
    arr=(${@})
    echo ${arr[0]}
else
    # Download the latest VPP build install packages
    CSIT_DIR=${SCRIPT_DIR}
    source "${SCRIPT_DIR}/resources/libraries/bash/function/artifacts.sh"
    download_artifacts
    # Need to revert -euo as the rest of script is not optimized for this.
    set +euo pipefail
fi

VIRL_DIR_LOC="/tmp/"
VPP_PKGS=(*vpp*.$PACKAGE)
VPP_PKGS_FULL=("${VPP_PKGS[@]/#/${VIRL_DIR_LOC}}")
echo ${VPP_PKGS[@]}

VIRL_TOPOLOGY=$(cat ${SCRIPT_DIR}/VIRL_TOPOLOGY_${DISTRO})
VIRL_RELEASE=$(cat ${SCRIPT_DIR}/VIRL_RELEASE_${DISTRO})

VPP_VER="$( expr match $(ls vpp*.${PACKAGE} | head -n 1) 'vpp[-|_]\(.*\)'.${PACKAGE} )"

set +x
echo "****************************************************************************************************************************************"
echo "1st step: Download VPP packages                                                                                                 FINISHED"
echo "VPP version to be tested: ${VPP_VER}"
echo "****************************************************************************************************************************************"
set -x


# 2nd step: Start virtual env and install requirements

echo Starting virtual env...
virtualenv --system-site-packages env
. env/bin/activate

echo Installing requirements...
pip install -r ${SCRIPT_DIR}/requirements.txt

set +x
echo "****************************************************************************************************************************************"
echo "2nd step: Start virtual env and install requirements                                                                            FINISHED"
echo "****************************************************************************************************************************************"
set -x


# 3rd step: Prepare VIRL system
echo Preparing VIRL system...

VIRL_SERVERS=("10.30.51.28" "10.30.51.29" "10.30.51.30")
VIRL_SERVER=""

VIRL_USERNAME=jenkins-in
VIRL_PKEY=priv_key
VIRL_SERVER_STATUS_FILE="status"
VIRL_SERVER_EXPECTED_STATUS="PRODUCTION"
VIRL_SESSION_EXPIRY="620"

SSH_OPTIONS="-i ${VIRL_PKEY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -o LogLevel=error"

function ssh_do() {
    echo
    echo "### "  ssh $@
    ssh ${SSH_OPTIONS} $@
}

rm -f ${VIRL_PKEY}
cat > ${VIRL_PKEY} <<EOF
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA+IHXq87GcqMR1C47rzx6Cbip5Ghq8pKrbqKrP5Nf41HcYrT6
GOXl9nFWKsMOzIlIn+8y7Il27eZh7csQGApbg8QLiHMtcYEmWNzKZpkqg4nuAPxX
VXwlKgnKX902SrET9Gp9TDayiHtCRWVfrlPPPSA0UEXW6BjLN/uHJ+W/Xzrrab+9
asBVa05vT2W6n0KJ66zfCaeDM912mQ6SttscAwFoWDmdHlegiVqrlIG2ABxOvxxz
L3dM3iSmlmQlzv9bThjo+nI4KFYh6m5wrZmAo5r/4q9CIJc21HVnTqkGOWJIZz6J
73lePJVSq5gYqaoGw3swFEA/MDkOx7baWKSoLQIDAQABAoIBAQCNBeolNp+JWJ76
gQ4fwLsknyXSV6sxYyhkDW4PEwwcTU06uqce0AAzXVffxne0fMe48x47+zqBgPbb
4huM+Pu8B9nfojUMr5TaYtl9Zbgpk3F8H7dT7LKOa6XrxvZTZrADSRc30+Z26zPN
e9zTaf42Gvt0/l0Zs1BHwbaOXqO+XuwJ3/F9Sf3PQYWXD3EOWjpHDP/X/1vAs6lV
SLkm6J/9KKE1m6I6LTYjIXuYt4SXybW6N2TSy54hhQtYcDUnIU2hR/PHVWKrGA0J
kELgrtTNTdbML27O5gFWU4PLUEYTZ9fN11D6qUZKxLcPOiPPHXkiILMRCCnG5DYI
ksBAU/YlAoGBAPxZO9VO18TYc8THV1nLKcvT2+1oSs1UcA2wNQMU55t910ZYinRa
MRwUhMOf8Mv5wOeiZaRICQB1PnVWtDVmGECgPpK6jUxqAwn8rgJcnoafLGL5YKMY
RVafTe6N5LXgCaOcJrk21wxs6v7ninEbUxxc575urOvZMBkymDw91dwbAoGBAPwa
YRhKhrzFKZzdK0RadVjnxKvolUllpoqqg3XuvmeAJHAOAnaOgVWq68NAcp5FZJv0
2D2Up7TX8pjf9MofP1SJbcraKBpK4NzfNkA0dSdEi+FhVofAJ9umB2o5LW1n7sab
UIrjsdzSJK/9Zb9yTTHPyibYzNEgaJV1HsbxfEFXAoGAYO2RmvRm0phll18OQVJV
IpKk9kLKAKZ/R/K32hAsikBC8SVPQTPniyaifFWx81diblalff2hX4ipTf7Yx24I
wMIMZuW7Im/R7QMef4+94G3Bad7p7JuE/qnAEHJ2OBnu+eYfxaK35XDsrq6XMazS
NqHE7hOq3giVfgg+C12hCKMCgYEAtu9dbYcG5owbehxzfRI2/OCRsjz/t1bv1seM
xVMND4XI6xb/apBWAZgZpIFrqrWoIBM3ptfsKipZe91ngBPUnL9s0Dolx452RVAj
yctHB8uRxWYgqDkjsxtzXf1HnZBBkBS8CUzYj+hdfuddoeKLaY3invXLCiV+PpXS
U4KAK9kCgYEAtSv0m5+Fg74BbAiFB6kCh11FYkW94YI6B/E2D/uVTD5dJhyEUFgZ
cWsudXjMki8734WSpMBqBp/J8wG3C9ZS6IpQD+U7UXA+roB7Qr+j4TqtWfM+87Rh
maOpG56uAyR0w5Z9BhwzA3VakibVk9KwDgZ29WtKFzuATLFnOtCS46E=
-----END RSA PRIVATE KEY-----
EOF
chmod 600 ${VIRL_PKEY}

#
# Pick a random host from the array of VIRL servers, and attempt
# to reach it and verify it's status.
#
# The server must be reachable, and have a "status" file with
# the content "PRODUCTION", to be selected.
#
# If the server is not reachable, or does not have the correct
# status, remove it from the array and start again.
#
# Abort if there are no more servers left in the array.
#
while [[ ! "$VIRL_SERVER" ]]
do
    num_hosts=${#VIRL_SERVERS[@]}
    if [ $num_hosts == 0 ]
    then
        echo "No more VIRL candidate hosts available, failing."
        exit 127
    fi
    element=$[ $RANDOM % $num_hosts ]
    virl_server_candidate=${VIRL_SERVERS[$element]}
    virl_server_status=$(ssh ${SSH_OPTIONS} ${VIRL_USERNAME}@${virl_server_candidate} cat $VIRL_SERVER_STATUS_FILE 2>&1)
    echo VIRL HOST $virl_server_candidate status is \"$virl_server_status\"
    if [ "$virl_server_status" == "$VIRL_SERVER_EXPECTED_STATUS" ]
    then
        # Candidate is in good status. Select this server.
        VIRL_SERVER="$virl_server_candidate"
    else
        # Candidate is in bad status. Remove from array.
        VIRL_SERVERS=("${VIRL_SERVERS[@]:0:$element}" "${VIRL_SERVERS[@]:$[$element+1]}")
    fi
done

# Copy the files to VIRL host
scp ${SSH_OPTIONS} ${VPP_PKGS[@]} \
    ${VIRL_USERNAME}@${VIRL_SERVER}:${VIRL_DIR_LOC}/

result=$?
if [ "${result}" -ne "0" ]; then
    echo "Failed to copy vpp deb files to virl host"
    echo ${result}
    exit ${result}
fi

# Start a simulation on VIRL server
echo "Starting simulation on VIRL server"

function stop_virl_simulation {
    ssh ${SSH_OPTIONS} ${VIRL_USERNAME}@${VIRL_SERVER}\
        "stop-testcase ${VIRL_SID}"
}

VIRL_SID=$(ssh ${SSH_OPTIONS} \
    ${VIRL_USERNAME}@${VIRL_SERVER} \
    "start-testcase -vv --copy ${VIRL_TOPOLOGY} \
    --expiry ${VIRL_SESSION_EXPIRY} \
    --release ${VIRL_RELEASE} ${VPP_PKGS_FULL[@]}")
retval=$?
if [ ${retval} -ne "0" ]; then
    echo "VIRL simulation start failed"
    exit ${retval}
fi

if [[ ! "${VIRL_SID}" =~ session-[a-zA-Z0-9_]{6} ]]; then
    echo "No VIRL session ID reported."
    exit 127
fi

# Upon script exit, cleanup the VIRL simulation execution
trap stop_virl_simulation EXIT
echo ${VIRL_SID}

ssh_do ${VIRL_USERNAME}@${VIRL_SERVER} cat /scratch/${VIRL_SID}/topology.yaml

# Download the topology file from VIRL session
scp ${SSH_OPTIONS} \
    ${VIRL_USERNAME}@${VIRL_SERVER}:/scratch/${VIRL_SID}/topology.yaml \
    topologies/enabled/topology_VIRL.yaml

retval=$?
if [ ${retval} -ne "0" ]; then
    echo "Failed to copy topology file from VIRL simulation"
    exit ${retval}
fi

set +x
echo "****************************************************************************************************************************************"
echo "3rd step: Start the simulation on the VIRL server                                                                               FINISHED"
echo "****************************************************************************************************************************************"
set -x


# 4th step: Run functional test suites

RC=0
MORE_FAILS=0

echo Running functional tests on the VIRL system...

# There are used three iterations of functional tests there
# to check the stability and reliability of the results.
partial_logs=""
for test_set in 1 2 3
do
    echo
    echo Functional test loop: ${test_set}
    echo

    pybot -L TRACE -W 136\
        -v TOPOLOGY_PATH:${SCRIPT_DIR}/topologies/enabled/topology_VIRL.yaml \
        --suite "tests.vpp.func" \
        --include vm_envAND3_node_single_link_topo \
        --include vm_envAND3_node_double_link_topo \
        --exclude PERFTEST \
        --exclude SOFTWIRE \
        --exclude SKIP_TEST \
        --noncritical EXPECTED_FAILING \
        --output ${LOG_PATH}/output_func_test_set${test_set} \
        tests/
    PARTIAL_RC=$(echo $?)
    partial_logs="${partial_logs} ${LOG_PATH}/output_func_test_set${test_set}.xml"
    if [ ${PARTIAL_RC} -eq 250 ]; then
        MORE_FAILS=1
    fi
    RC=$((RC+PARTIAL_RC))
done

set +x
echo "****************************************************************************************************************************************"
echo "4th step: Run functional tests                                                                                                  FINISHED"
echo "****************************************************************************************************************************************"
set -x

# Set RETURN_STATUS=1 if some critical test failed
if [ ! ${RC} -eq 0 ]; then
        RETURN_STATUS=1
fi

# Log the final result
if [ ${RC} -eq 0 ]; then
    set +x
    echo
    echo "========================================================================================================================================"
    echo "Final result of all test loops:                                                                                                 | PASS |"
    echo "All critical tests have passed."
    echo "========================================================================================================================================"
    echo
    set -x
elif [ ${MORE_FAILS} -eq 0 ]; then
    if [ ${RC} -eq 1 ]; then
        HLP_STR="test has"
    else
        HLP_STR="tests have"
    fi
    set +x
    echo
    echo "========================================================================================================================================"
    echo "Final result of all test loops:                                                                                                 | FAIL |"
    echo "${RC} critical ${HLP_STR} failed."
    echo "========================================================================================================================================"
    echo
    set -x
else
    set +x
    echo
    echo "========================================================================================================================================"
    echo "Final result of all test loops:                                                                                                 | FAIL |"
    echo "More then 250 critical tests have failed in one test loop."
    echo "========================================================================================================================================"
    echo
    set -x
fi

# 7th step: Post-processing test data
echo Post-processing test data...

# Rebot output post-processing
rebot --noncritical EXPECTED_FAILING \
      --output output.xml ${partial_logs}

# Remove unnecessary files
rm -f ${partial_logs}

# Archive JOB artifacts in jenkins
for i in ${JOB_ARCHIVE_ARTIFACTS[@]}; do
    cp $( readlink -f ${i} | tr '\n' ' ' ) ${JOB_ARCHIVE_DIR}/
done
# Archive JOB artifacts to logs.fd.io
for i in ${LOG_ARCHIVE_ARTIFACTS[@]}; do
    cp $( readlink -f ${i} | tr '\n' ' ' ) ${LOG_ARCHIVE_DIR}/
done

echo Post-processing finished.

exit ${RETURN_STATUS}