/* * Copyright (c) 2018 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. */ #include #include static int test_memset_s (vlib_main_t * vm, unformat_input_t * input) { u8 dst[64]; int i; errno_t err; vlib_cli_output (vm, "Test memset_s..."); err = memset_s (dst, ARRAY_LEN (dst), 0xfe, ARRAY_LEN (dst)); if (err != EOK) return -1; for (i = 0; i < ARRAY_LEN (dst); i++) if (dst[i] != 0xFE) return -1; err = memset_s (dst, ARRAY_LEN (dst), 0xfa, ARRAY_LEN (dst) + 1); if (err == EOK) return -1; return 0; } static int test_clib_memset (vlib_main_t * vm, unformat_input_t * input) { u8 dst[64]; int i; errno_t err; vlib_cli_output (vm, "Test clib_memset..."); err = clib_memset (dst, 0xfe, ARRAY_LEN (dst)); if (err != EOK) return -1; for (i = 0; i < ARRAY_LEN (dst); i++) if (dst[i] != 0xFE) return -1; return 0; } static int test_memcpy_s (vlib_main_t * vm, unformat_input_t * input) { char src[64], dst[64]; int i; errno_t err; vlib_cli_output (vm, "Test memcpy_s..."); for (i = 0; i < ARRAY_LEN (src); i++) src[i] = i + 1; /* Typical case */ err = memcpy_s (dst, sizeof (dst), src, sizeof (src)); if (err != EOK) return -1; /* This better not fail but check anyhow */ for (i = 0; i < ARRAY_LEN (dst); i++) if (src[i] != dst[i]) return -1; /* Size fail */ err = memcpy_s (dst + 1, sizeof (dst) - 1, src, sizeof (src)); if (err == EOK) return -1; /* overlap fail */ err = memcpy_s (dst, sizeof (dst), dst + 1, sizeof (dst) - 1); if (err == EOK) return -1; /* Zero length copy */ err = memcpy_s (0, sizeof (dst), src, 0); if (err != EOK) return -1; /* OK, seems to work */ return 0; } static int test_clib_memcpy (vlib_main_t * vm, unformat_input_t * input) { char src[64], dst[64]; int i; errno_t err; vlib_cli_output (vm, "Test clib_memcpy..."); for (i = 0; i < ARRAY_LEN (src); i++) src[i] = i + 1; /* Typical case */ err = clib_memcpy (dst, src, sizeof (src)); if (err != EOK) return -1; /* This better not fail but check anyhow */ for (i = 0; i < ARRAY_LEN (dst); i++) if (src[i] != dst[i]) return -1; /* verify it against memcpy */ memcpy (dst, src, sizeof (src)); /* This better not fail but check anyhow */ for (i = 0; i < ARRAY_LEN (dst); i++) if (src[i] != dst[i]) return -1; /* Zero length copy */ err = clib_memcpy (0, src, 0); if (err != EOK) return -1; /* OK, seems to work */ return 0; } static int test_memcmp_s (vlib_main_t * vm, unformat_input_t * input) { char src[64], dst[64]; errno_t err; int diff = 0; vlib_cli_output (vm, "Test memcmp_s..."); /* Fill array with different values */ err = clib_memset (src, 0x1, ARRAY_LEN (src)); if (err != EOK) return -1; err = clib_memset (dst, 0x3, ARRAY_LEN (dst)); if (err != EOK) return -1; /* s1 > s2, > 0 is expected in diff */ err = memcmp_s (dst, ARRAY_LEN (dst), src, ARRAY_LEN (src), &diff); if (err != EOK) return -1; if (!(diff > 0)) return -1; /* s1 < s2, < 0 is expected in diff */ err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff); if (err != EOK) return -1; if (!(diff < 0)) return -1; err = clib_memset (dst, 0x1, ARRAY_LEN (dst)); if (err != EOK) return -1; /* s1 == s2, 0 is expected in diff */ err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff); if (err != EOK) return -1; if (diff != 0) return -1; /* Try negative tests */ err = memcmp_s (0, 0, 0, 0, 0); if (err != EINVAL) return -1; /* Try s2max > s1max */ err = memcmp_s (src, ARRAY_LEN (src) - 1, dst, ARRAY_LEN (dst), &diff); if (err != EINVAL) return -1; /* OK, seems to work */ return 0; } static int test_clib_memcmp (vlib_main_t * vm, unformat_input_t * input) { char src[64], dst[64]; errno_t err; char *s; vlib_cli_output (vm, "Test clib_memcmp..."); /* Fill array with different values */ err = clib_memset (src, 0x1, ARRAY_LEN (src)); if (err != EOK) return -1; err = clib_memset (dst, 0x3, ARRAY_LEN (dst)); if (err != EOK) return -1; /* s1 > s2, > 0 is expected in diff */ if (!(clib_memcmp (dst, src, ARRAY_LEN (src)) > 0)) return -1; /* verify it against memcmp */ if (!(memcmp (dst, src, ARRAY_LEN (src)) > 0)) return -1; /* s1 < s2, < 0 is expected in diff */ if (!(clib_memcmp (src, dst, ARRAY_LEN (dst)) < 0)) return -1; /* verify it against memcmp */ if (!(memcmp (src, dst, ARRAY_LEN (dst)) < 0)) return -1; err = clib_memset (dst, 0x1, ARRAY_LEN (dst)); if (err != EOK) return -1; /* s1 == s2, 0 is expected in diff */ if (clib_memcmp (src, dst, ARRAY_LEN (dst)) != 0) return -1; /* verify it against memcmp */ if (memcmp (src, dst, ARRAY_LEN (dst)) != 0) return -1; /* Try negative tests */ s = 0; if (clib_memcmp (s, s, 0) != 0) return -1; /* verify it against memcmp */ if (memcmp (s, s, 0) != 0) return -1; /* OK, seems to work */ return 0; } static int test_strcmp_s (vlib_main_t * vm, unformat_input_t * input) { char s1[] = "Simplicity is the ultimate sophistication"; uword s1len = sizeof (s1) - 1; // excluding null errno_t err; int indicator = 0; vlib_cli_output (vm, "Test strcmp_s..."); /* s1 == s2, 0 is expected */ err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication", &indicator); if (err != EOK) return -1; if (indicator != 0) return -1; /* s1 > s2, > 0 is expected */ err = strcmp_s (s1, s1len, "Simplicity is the ultimate", &indicator); if (err != EOK) return -1; if (!(indicator > 0)) return -1; /* s1 < s2, < 0 is expected */ err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication!", &indicator); if (err != EOK) return -1; if (!(indicator < 0)) return -1; /* Try some negative tests */ /* Null pointers test */ err = strcmp_s (0, 0, 0, 0); if (err != EINVAL) return -1; /* non-null terminated s1 */ s1[s1len] = 0x1; err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication", &indicator); if (err != EINVAL) return -1; /* OK, seems to work */ return 0; } static int test_clib_strcmp (vlib_main_t * vm, unformat_input_t * input) { char s1[] = "Simplicity is the ultimate sophistication"; int indicator; char *s; vlib_cli_output (vm, "Test clib_strcmp..."); /* s1 == s2, 0 is expected */ indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication"); if (indicator != 0) return -1; /* verify it against strcmp */ indicator = strcmp (s1, "Simplicity is the ultimate sophistication"); if (indicator != 0) return -1; /* s1 > s2, > 0 is expected */ indicator = clib_strcmp (s1, "Simplicity is the ultimate"); if (!(indicator > 0)) return -1; /* verify it against strcmp */ indicator = strcmp (s1, "Simplicity is the ultimate"); if (!(indicator > 0)) return -1; /* s1 < s2, < 0 is expected */ indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication!"); if (!(indicator < 0)) return -1; /* verify it against strcmp */ indicator = strcmp (s1, "Simplicity is the ultimate sophistication!"); if (!(indicator < 0)) return -1; /* Try some negative tests */ /* Null pointers comparison */ s = 0; indicator = clib_strcmp (s, s); if (indicator != 0) return -1; /* OK, seems to work */ return 0; } static int test_strncmp_s (vlib_main_t * vm, unformat_input_t * input) { char s1[] = "Every moment is a fresh beginning"; uword s1len = sizeof (s1) - 1; // excluding null errno_t err; int indicator = 0; vlib_cli_output (vm, "Test strncmp_s..."); /* s1 == s2, 0 is expected */ err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len, &indicator); if (err != EOK) return -1; if (indicator != 0) return -1; /* s1 > s2, 0 is expected since comparison is no more than n character */ err = strncmp_s (s1, s1len, "Every moment is a fresh begin", sizeof ("Every moment is a fresh begin") - 1, &indicator); if (err != EOK) return -1; if (indicator != 0) return -1; /* s1 < s2, < 0 is expected */ err = strncmp_s (s1, s1len, "Every moment is fresh beginning", sizeof ("Every moment is fresh beginning") - 1, &indicator); if (err != EOK) return -1; if (!(indicator < 0)) return -1; /* s1 > s2, > 0 is expected */ err = strncmp_s ("Every moment is fresh beginning. ", sizeof ("Every moment is fresh beginning. ") - 1, s1, s1len, &indicator); if (err != EOK) return -1; if (!(indicator > 0)) return -1; /* Try some negative tests */ /* Null pointers */ err = strncmp_s (0, 0, 0, 0, 0); if (err != EINVAL) return -1; /* n > s1max */ err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len + 1, &indicator); if (err != EINVAL) return -1; /* unterminated s1 */ s1[s1len] = 0x1; err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", sizeof ("Every moment is a fresh beginning") - 1, &indicator); if (err != EINVAL) return -1; /* OK, seems to work */ return 0; } static int test_clib_strncmp (vlib_main_t * vm, unformat_input_t * input) { char s1[] = "Every moment is a fresh beginning"; uword s1len = sizeof (s1) - 1; // excluding null int indicator, v_indicator; vlib_cli_output (vm, "Test clib_strncmp..."); /* s1 == s2, 0 is expected */ indicator = clib_strncmp (s1, "Every moment is a fresh beginning", s1len); if (indicator != 0) return -1; /* verify it against strncmp */ v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len); if (v_indicator != 0) return -1; /* s1 > s2, 0 is expected since comparison is no more than n character */ indicator = clib_strncmp (s1, "Every moment is a fresh begin", sizeof ("Every moment is a fresh begin") - 1); if (indicator != 0) return -1; /* verify it against strncmp */ v_indicator = strncmp (s1, "Every moment is a fresh begin", sizeof ("Every moment is a fresh begin") - 1); if (v_indicator != 0) return -1; /* s1 < s2, < 0 is expected */ indicator = clib_strncmp (s1, "Every moment is fresh beginning", sizeof ("Every moment is fresh beginning") - 1); if (!(indicator < 0)) return -1; /* verify it against strncmp */ v_indicator = strncmp (s1, "Every moment is fresh beginning", sizeof ("Every moment is fresh beginning") - 1); if (!(v_indicator < 0)) return -1; if (v_indicator != indicator) return -1; /* s1 > s2, > 0 is expected */ indicator = clib_strncmp ("Every moment is fresh beginning. ", s1, s1len); if (!(indicator > 0)) return -1; /* verify it against strncmp */ v_indicator = strncmp ("Every moment is fresh beginning. ", s1, s1len); if (!(v_indicator > 0)) return -1; if (v_indicator != indicator) return -1; /* Try some negative tests */ /* Null pointers */ /* make sure we don't crash */ indicator = clib_strncmp (0, 0, 0); if (indicator != EOK) return -1; /* n > s1 len */ indicator = clib_strncmp (s1, "Every moment is a fresh beginning", s1len + 1); if (indicator != 0) return -1; /* verify it against strncmp */ v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len + 1); if (v_indicator != 0) return -1; /* unterminated s1 */ s1[s1len] = 0x1; indicator = clib_strncmp (s1, "Every moment is a fresh beginning", sizeof ("every moment is a fresh beginning") - 1); if (indicator != 0) return -1; /* verify it against strncmp */ v_indicator = strncmp (s1, "Every moment is a fresh beginning", sizeof ("Every moment is a fresh beginning") - 1); if (v_indicator != 0) return -1; /* OK, seems to work */ return 0; } static int test_strcpy_s (vlib_main_t * vm, unformat_input_t * input) { char src[] = "To err is human."; char dst[64]; int indicator; size_t s1size = sizeof (dst); // including null errno_t err; vlib_cli_output (vm, "Test strcpy_s..."); err = strcpy_s (dst, s1size, src); if (err != EOK) return -1; /* This better not fail but check anyhow */ if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) != EOK) return -1; if (indicator != 0) return -1; /* Negative tests */ err = strcpy_s (0, 0, 0); if (err == EOK) return -1; /* Size fail */ err = strcpy_s (dst, 10, src); if (err == EOK) return -1; /* overlap fail */ #if __GNUC__ < 8 /* GCC 8 flunks this one at compile time... */ err = strcpy_s (dst, s1size, dst); if (err == EOK) return -1; #endif /* overlap fail */ err = strcpy_s (dst, s1size, dst + 1); if (err == EOK) return -1; /* OK, seems to work */ return 0; } static int test_clib_strcpy (vlib_main_t * vm, unformat_input_t * input) { char src[] = "The journey of a one thousand miles begins with one step."; char dst[100]; int indicator; errno_t err; vlib_cli_output (vm, "Test clib_strcpy..."); err = clib_strcpy (dst, src); if (err != EOK) return -1; /* This better not fail but check anyhow */ if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) != EOK) return -1; if (indicator != 0) return -1; /* verify it against strcpy */ strcpy (dst, src); /* This better not fail but check anyhow */ if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) != EOK) return -1; if (indicator != 0) return -1; /* Negative tests */ err = clib_strcpy (0, 0); if (err == EOK) return -1; /* overlap fail */ #if __GNUC__ < 8 /* GCC 8 flunks this one at compile time... */ err = clib_strcpy (dst, dst); if (err == EOK) return -1; #endif /* overlap fail */ err = clib_strcpy (dst, dst + 1); if (err == EOK) return -1; /* OK, seems to work */ return 0; } static int test_strncpy_s (vlib_main_t * vm, unformat_input_t * input) { char src[] = "Those who dare to fail miserably can achieve greatly."; char dst[100], old_dst[100]; int indicator, i; size_t s1size = sizeof (dst); // including null errno_t err; vlib_cli_output (vm, "Test strncpy_s..."); /* dmax includes null, n excludes null */ /* n == string len of src */ err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src))); if (err != EOK) return -1; if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) != EOK) return -1; if (indicator != 0) return -1; /* limited copy -- strlen src > n, copy up to n */ err = strncpy_s (dst, s1size, "The price of greatness is responsibility.", 10); if (err != EOK) return -1; if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ", &indicator) != EOK) return -1; if (indicator != 0) return -1; /* n > string len of src */ err = clib_memset (dst, 1, sizeof (dst)); if (err != EOK) return -1; err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src)) + 10); if (err != EOK) return -1; if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) != EOK) return -1; if (indicator != 0) return -1; /* Make sure bytes after strlen(dst) is untouched */ for (i = 1 + clib_strnlen (dst, sizeof (dst)); i < sizeof (dst); i++) if (dst[i] != 1) return -1; /* truncation, n >= dmax */ err = strncpy_s (dst, clib_strnlen (src, sizeof (src)), src, clib_strnlen (src, sizeof (src))); if (err != EOVERFLOW) return -1; /* Check dst content
# Copyright (c) 2019 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.

*** Settings ***
| Resource | resources/libraries/robot/performance/performance_setup.robot
| ...
| Force Tags | 2_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | NDRPDR
| ... | NIC_Intel-X710 | ETH | L2BDMACLRN | BASE | VHOST | VM
| ... | VHOST_1024 | NF_DENSITY | NF_L3FWDIP4 | CHAIN | 1R10C
| ...
| Suite Setup | Set up 2-node performance topology with DUT's NIC model
| ... | L3 | ${nic_name}
| Suite Teardown | Tear down 2-node performance topology
| ...
| Test Setup | Set up performance test
| Test Teardown | Tear down performance test with vhost
| ...
| Test Template | Local Template
| ...
| Documentation | *RFC2544: Pkt throughput L2BD test cases with 20 vhost 1 chain
| ... | 10 VMs*
| ...
| ... | *[Top] Network Topologies:* TG-DUT1-TG 2-node circular topology
| ... | with single links between nodes.
| ... | *[Enc] Packet Encapsulations:* Eth-IPv4 for L2 switching of IPv4.
| ... | *[Cfg] DUT configuration:* DUT1 is configured with L2 bridge-
| ... | domain and MAC learning enabled. Qemu VNFs are connected to VPP via
| ... | vhost-user interfaces. Guest is running DPDK l3fwd IPv4
| ... | interconnecting vhost-user interfaces, forwarding mode is
| ... | set to io, rxd/txd=1024. DUT1 is tested with ${nic_name}.\
| ... | *[Ver] TG verification:* TG finds and reports throughput NDR (Non Drop\
| ... | Rate) with zero packet loss tolerance and throughput PDR (Partial Drop\
| ... | Rate) with non-zero packet loss tolerance (LT) expressed in percentage\
| ... | of packets transmitted. NDR and PDR are discovered for different\
| ... | Ethernet L2 frame sizes using MLRsearch library.\
| ... | Test packets are generated by TG on links to DUTs. TG traffic profile
| ... | contains two L3 flow-groups (flow-group per direction, 254 flows per
| ... | flow-group) with all packets containing Ethernet header, IPv4 header
| ... | with IP protocol=61 and static payload. MAC addresses are matching MAC
| ... | addresses of the TG node interfaces.
| ... | *[Ref] Applicable standard specifications:* RFC2544.

*** Variables ***
| ${nic_name}= | Intel-X710
| ${overhead}= | ${0}
# Traffic profile:
| ${traffic_profile}= | trex-sl-2n3n-ethip4-ip4src254-1c10n

*** Keywords ***
| Local Template
| | [Documentation]
| | ... | [Cfg] DUT runs L2BD switching config.
| | ... | Each DUT uses ${phy_cores} physical core(s) for worker threads.
| | ... | [Ver] Measure NDR and PDR values using MLRsearch algorithm.\
| | ...
| | ... | *Arguments:*
| | ... | - frame_size - Framesize in Bytes in integer or string (IMIX_v4_1).
| | ... | Type: integer, string
| | ... | - phy_cores - Number of physical cores. Type: integer
| | ... | - rxq - Number of RX queues, default value: ${None}. Type: integer
| | ...
| | [Arguments] | ${frame_size} | ${phy_cores} | ${rxq}=${None}
| | ...
| | Set Test Variable | \${frame_size}
| | ...
| | Given Add worker threads and rxqueues to all DUTs | ${phy_cores} | ${rxq}
| | And Add PCI devices to all DUTs
| | Set Max Rate And Jumbo And Handle Multi Seg
| | And Apply startup configuration on all VPP DUTs
| | When Initialize L2 bridge domains for multiple chains with Vhost-User
| | ... | nf_chains=${1} | nf_nodes=${10}
| | And Configure chains of NFs connected via vhost-user
| | ... | nf_chains=${1} | nf_nodes=${10} | jumbo=${jumbo}
| | ... | use_tuned_cfs=${False} | auto_scale=${False} | vnf=testpmd_mac
| | Then Find NDR and PDR intervals using optimized search

*** Test Cases ***
| tc01-64B-1c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 64B | 1C
| | frame_size=${64} | phy_cores=${1}

| tc02-64B-2c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 64B | 2C
| | frame_size=${64} | phy_cores=${2}

| tc03-64B-4c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 64B | 4C
| | frame_size=${64} | phy_cores=${4}

| tc04-1518B-1c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 1518B | 1C
| | frame_size=${1518} | phy_cores=${1}

| tc05-1518B-2c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 1518B | 2C
| | frame_size=${1518} | phy_cores=${2}

| tc06-1518B-4c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 1518B | 4C
| | frame_size=${1518} | phy_cores=${4}

| tc07-9000B-1c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 9000B | 1C
| | frame_size=${9000} | phy_cores=${1}

| tc08-9000B-2c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 9000B | 2C
| | frame_size=${9000} | phy_cores=${2}

| tc09-9000B-4c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | 9000B | 4C
| | frame_size=${9000} | phy_cores=${4}

| tc10-IMIX-1c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | IMIX | 1C
| | frame_size=IMIX_v4_1 | phy_cores=${1}

| tc11-IMIX-2c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | IMIX | 2C
| | frame_size=IMIX_v4_1 | phy_cores=${2}

| tc12-IMIX-4c-eth-l2bd-20vhost-1chain-10vm-l3fwdip4-ndrpdr
| | [Tags] | IMIX | 4C
| | frame_size=IMIX_v4_1 | phy_cores=${4}
d_fn, }; /* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */