From patchwork Tue Feb 23 16:23:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Loftus, Ciara" X-Patchwork-Id: 387125 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92D3BC43381 for ; Tue, 23 Feb 2021 16:55:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 61CD064ED0 for ; Tue, 23 Feb 2021 16:55:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233606AbhBWQz1 (ORCPT ); Tue, 23 Feb 2021 11:55:27 -0500 Received: from mga11.intel.com ([192.55.52.93]:49578 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232252AbhBWQzS (ORCPT ); Tue, 23 Feb 2021 11:55:18 -0500 IronPort-SDR: gMEPrr0Jc13jW2O6vJKpbKVHbOfB7WVgAEV3z2boP9AkZpDM6GEdy8NGLG+IDLctABRSj3Pb0x V216Wf8R4bBQ== X-IronPort-AV: E=McAfee;i="6000,8403,9904"; a="181435261" X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="181435261" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2021 08:54:35 -0800 IronPort-SDR: RVbQlsE/TZf7SbrSgvOqD91j/aqCBQtYYFZ7QywyHvxzuSkoad906rXlPAVl8a0FonnhdIT/CH gJpcUoiokVcg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="441792263" Received: from silpixa00399839.ir.intel.com (HELO localhost.localdomain) ([10.237.222.142]) by orsmga001.jf.intel.com with ESMTP; 23 Feb 2021 08:53:55 -0800 From: Ciara Loftus To: netdev@vger.kernel.org, bpf@vger.kernel.org, magnus.karlsson@intel.com, bjorn@kernel.org, weqaar.a.janjua@intel.com, maciej.fijalkowski@intel.com Cc: Ciara Loftus Subject: [PATCH bpf-next v3 1/4] selftest/bpf: make xsk tests less verbose Date: Tue, 23 Feb 2021 16:23:01 +0000 Message-Id: <20210223162304.7450-2-ciara.loftus@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210223162304.7450-1-ciara.loftus@intel.com> References: <20210223162304.7450-1-ciara.loftus@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Magnus Karlsson Make the xsk tests less verbose by only printing the essentials. Currently, it is hard to see if the tests passed or not due to all the printouts. Move the extra printouts to a verbose option, if further debugging is needed when a problem arises. To run the xsk tests with verbose output: ./test_xsk.sh -v Signed-off-by: Magnus Karlsson Signed-off-by: Ciara Loftus Acked-by: Maciej Fijalkowski --- tools/testing/selftests/bpf/test_xsk.sh | 27 ++++++++++++++----- tools/testing/selftests/bpf/xdpxceiver.c | 31 +++++++++++++--------- tools/testing/selftests/bpf/xdpxceiver.h | 13 +++++---- tools/testing/selftests/bpf/xsk_prereqs.sh | 9 +++---- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/tools/testing/selftests/bpf/test_xsk.sh b/tools/testing/selftests/bpf/test_xsk.sh index 88a7483eaae4..f4cedf4c2718 100755 --- a/tools/testing/selftests/bpf/test_xsk.sh +++ b/tools/testing/selftests/bpf/test_xsk.sh @@ -71,13 +71,17 @@ # # Run (full output without color-coding): # sudo ./test_xsk.sh +# +# Run with verbose output: +# sudo ./test_xsk.sh -v . xsk_prereqs.sh -while getopts c flag +while getopts "cv" flag do case "${flag}" in c) colorconsole=1;; + v) verbose=1;; esac done @@ -95,13 +99,17 @@ NS1=af_xdp${VETH1_POSTFIX} MTU=1500 setup_vethPairs() { - echo "setting up ${VETH0}: namespace: ${NS0}" + if [[ $verbose -eq 1 ]]; then + echo "setting up ${VETH0}: namespace: ${NS0}" + fi ip netns add ${NS1} ip link add ${VETH0} type veth peer name ${VETH1} if [ -f /proc/net/if_inet6 ]; then echo 1 > /proc/sys/net/ipv6/conf/${VETH0}/disable_ipv6 fi - echo "setting up ${VETH1}: namespace: ${NS1}" + if [[ $verbose -eq 1 ]]; then + echo "setting up ${VETH1}: namespace: ${NS1}" + fi ip link set ${VETH1} netns ${NS1} ip netns exec ${NS1} ip link set ${VETH1} mtu ${MTU} ip link set ${VETH0} mtu ${MTU} @@ -125,7 +133,10 @@ echo "${VETH0}:${VETH1},${NS1}" > ${SPECFILE} validate_veth_spec_file -echo "Spec file created: ${SPECFILE}" +if [[ $verbose -eq 1 ]]; then + echo "Spec file created: ${SPECFILE}" + VERBOSE_ARG="-v" +fi test_status $retval "${TEST_NAME}" @@ -136,12 +147,16 @@ statusList=() ### TEST 1 TEST_NAME="XSK KSELFTEST FRAMEWORK" -echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Generic mode" +if [[ $verbose -eq 1 ]]; then + echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Generic mode" +fi vethXDPgeneric ${VETH0} ${VETH1} ${NS1} retval=$? if [ $retval -eq 0 ]; then - echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Native mode" + if [[ $verbose -eq 1 ]]; then + echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Native mode" + fi vethXDPnative ${VETH0} ${VETH1} ${NS1} fi diff --git a/tools/testing/selftests/bpf/xdpxceiver.c b/tools/testing/selftests/bpf/xdpxceiver.c index f4a96d5ff524..8af746c9a6b6 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.c +++ b/tools/testing/selftests/bpf/xdpxceiver.c @@ -341,6 +341,7 @@ static struct option long_options[] = { {"tear-down", no_argument, 0, 'T'}, {"bidi", optional_argument, 0, 'B'}, {"debug", optional_argument, 0, 'D'}, + {"verbose", no_argument, 0, 'v'}, {"tx-pkt-count", optional_argument, 0, 'C'}, {0, 0, 0, 0} }; @@ -359,6 +360,7 @@ static void usage(const char *prog) " -T, --tear-down Tear down sockets by repeatedly recreating them\n" " -B, --bidi Bi-directional sockets test\n" " -D, --debug Debug mode - dump packets L2 - L5\n" + " -v, --verbose Verbose output\n" " -C, --tx-pkt-count=n Number of packets to send\n"; ksft_print_msg(str, prog); } @@ -392,7 +394,7 @@ static void *nsswitchthread(void *args) ksft_test_result_fail("ERROR: [%s] interface \"%s\" does not exist\n", __func__, ifdict[targs->idx]->ifname); } else { - ksft_print_msg("Interface found: %s\n", ifdict[targs->idx]->ifname); + print_verbose("Interface found: %s\n", ifdict[targs->idx]->ifname); targs->retptr = true; } } @@ -422,7 +424,7 @@ static int validate_interfaces(void) pthread_join(ns_thread, NULL); if (targs->retptr) - ksft_print_msg("NS switched: %s\n", ifdict[i]->nsname); + print_verbose("NS switched: %s\n", ifdict[i]->nsname); free(targs); } else { @@ -432,7 +434,7 @@ static int validate_interfaces(void) ("ERROR: interface \"%s\" does not exist\n", ifdict[i]->ifname); ret = false; } else { - ksft_print_msg("Interface found: %s\n", ifdict[i]->ifname); + print_verbose("Interface found: %s\n", ifdict[i]->ifname); } } } @@ -446,7 +448,7 @@ static void parse_command_line(int argc, char **argv) opterr = 0; for (;;) { - c = getopt_long(argc, argv, "i:q:pSNcTBDC:", long_options, &option_index); + c = getopt_long(argc, argv, "i:q:pSNcTBDC:v", long_options, &option_index); if (c == -1) break; @@ -497,6 +499,9 @@ static void parse_command_line(int argc, char **argv) case 'C': opt_pkt_count = atoi(optarg); break; + case 'v': + opt_verbose = 1; + break; default: usage(basename(argv[0])); ksft_exit_xfail(); @@ -714,7 +719,7 @@ static void worker_pkt_dump(void) int payload = *((uint32_t *)(pkt_buf[iter]->payload + PKT_HDR_SIZE)); if (payload == EOT) { - ksft_print_msg("End-of-transmission frame received\n"); + print_verbose("End-of-transmission frame received\n"); fprintf(stdout, "---------------------------------------\n"); break; } @@ -746,7 +751,7 @@ static void worker_pkt_validate(void) } if (payloadseqnum == EOT) { - ksft_print_msg("End-of-transmission frame received: PASS\n"); + print_verbose("End-of-transmission frame received: PASS\n"); sigvar = 1; break; } @@ -836,7 +841,7 @@ static void *worker_testapp_validate(void *arg) usleep(USLEEP_MAX); } - ksft_print_msg("Interface [%s] vector [Tx]\n", ifobject->ifname); + print_verbose("Interface [%s] vector [Tx]\n", ifobject->ifname); for (int i = 0; i < num_frames; i++) { /*send EOT frame */ if (i == (num_frames - 1)) @@ -850,7 +855,7 @@ static void *worker_testapp_validate(void *arg) gen_eth_frame(ifobject->umem, i * XSK_UMEM__DEFAULT_FRAME_SIZE); } - ksft_print_msg("Sending %d packets on interface %s\n", + print_verbose("Sending %d packets on interface %s\n", (opt_pkt_count - 1), ifobject->ifname); tx_only_all(ifobject); } else if (ifobject->fv.vector == rx) { @@ -860,7 +865,7 @@ static void *worker_testapp_validate(void *arg) if (!bidi_pass) thread_common_ops(ifobject, bufs, &sync_mutex_tx, &spinning_rx); - ksft_print_msg("Interface [%s] vector [Rx]\n", ifobject->ifname); + print_verbose("Interface [%s] vector [Rx]\n", ifobject->ifname); xsk_populate_fill_ring(ifobject->umem); TAILQ_INIT(&head); @@ -890,11 +895,11 @@ static void *worker_testapp_validate(void *arg) break; } - ksft_print_msg("Received %d packets on interface %s\n", + print_verbose("Received %d packets on interface %s\n", pkt_counter, ifobject->ifname); if (opt_teardown) - ksft_print_msg("Destroying socket\n"); + print_verbose("Destroying socket\n"); } if (!opt_bidi || bidi_pass) { @@ -914,7 +919,7 @@ static void testapp_validate(void) if (opt_bidi && bidi_pass) { pthread_init_mutex(); if (!switching_notify) { - ksft_print_msg("Switching Tx/Rx vectors\n"); + print_verbose("Switching Tx/Rx vectors\n"); switching_notify++; } } @@ -974,7 +979,7 @@ static void testapp_sockets(void) pkt_counter = 0; prev_pkt = -1; sigvar = 0; - ksft_print_msg("Creating socket\n"); + print_verbose("Creating socket\n"); testapp_validate(); opt_bidi ? bidi_pass++ : bidi_pass; } diff --git a/tools/testing/selftests/bpf/xdpxceiver.h b/tools/testing/selftests/bpf/xdpxceiver.h index 0e9f9b7e61c2..f66f399dfb2d 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.h +++ b/tools/testing/selftests/bpf/xdpxceiver.h @@ -42,6 +42,8 @@ #define POLL_TMOUT 1000 #define NEED_WAKEUP true +#define print_verbose(x...) do { if (opt_verbose) ksft_print_msg(x); } while (0) + typedef __u32 u32; typedef __u16 u16; typedef __u8 u8; @@ -51,11 +53,11 @@ enum TESTS { ORDER_CONTENT_VALIDATE_XDP_DRV = 1, }; -u8 uut; -u8 debug_pkt_dump; -u32 num_frames; -u8 switching_notify; -u8 bidi_pass; +static u8 uut; +static u8 debug_pkt_dump; +static u32 num_frames; +static u8 switching_notify; +static u8 bidi_pass; static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; static int opt_queue; @@ -64,6 +66,7 @@ static int opt_poll; static int opt_teardown; static int opt_bidi; static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP; +static u8 opt_verbose; static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE]; static u32 pkt_counter; static u32 prev_pkt = -1; diff --git a/tools/testing/selftests/bpf/xsk_prereqs.sh b/tools/testing/selftests/bpf/xsk_prereqs.sh index 9d54c4645127..ef8c5b31f4b6 100755 --- a/tools/testing/selftests/bpf/xsk_prereqs.sh +++ b/tools/testing/selftests/bpf/xsk_prereqs.sh @@ -82,24 +82,21 @@ clear_configs() { if [ $(ip netns show | grep $3 &>/dev/null; echo $?;) == 0 ]; then [ $(ip netns exec $3 ip link show $2 &>/dev/null; echo $?;) == 0 ] && - { echo "removing link $1:$2"; ip netns exec $3 ip link del $2; } - echo "removing ns $3" + { ip netns exec $3 ip link del $2; } ip netns del $3 fi #Once we delete a veth pair node, the entire veth pair is removed, #this is just to be cautious just incase the NS does not exist then #veth node inside NS won't get removed so we explicitly remove it [ $(ip link show $1 &>/dev/null; echo $?;) == 0 ] && - { echo "removing link $1"; ip link del $1; } + { ip link del $1; } if [ -f ${SPECFILE} ]; then - echo "removing spec file:" ${SPECFILE} rm -f ${SPECFILE} fi } cleanup_exit() { - echo "cleaning up..." clear_configs $1 $2 $3 } @@ -131,5 +128,5 @@ execxdpxceiver() copy[$index]=${!current} done - ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${copy[*]} -C ${NUMPKTS} + ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${copy[*]} -C ${NUMPKTS} ${VERBOSE_ARG} } From patchwork Tue Feb 23 16:23:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Loftus, Ciara" X-Patchwork-Id: 386565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B87D1C433DB for ; Tue, 23 Feb 2021 16:56:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8751964E6C for ; Tue, 23 Feb 2021 16:56:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233648AbhBWQ4M (ORCPT ); Tue, 23 Feb 2021 11:56:12 -0500 Received: from mga18.intel.com ([134.134.136.126]:11206 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233585AbhBWQ4B (ORCPT ); Tue, 23 Feb 2021 11:56:01 -0500 IronPort-SDR: V5uNaYmNJCIHJw0oSE4BP23d1fNcZKSVW+ndvuSbqkQxbGxVV2Lf98Swp3mijC2PKPslJFg0K0 Sj9+Q9AOQyeg== X-IronPort-AV: E=McAfee;i="6000,8403,9904"; a="172522720" X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="172522720" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2021 08:55:18 -0800 IronPort-SDR: jM60HyQ6DAyvTsPDltHuzLXx2V/Dho1zU/6qbyHSQIXa+y3WQIKC0DecZE+axMwQ3VS6QbqAmw 6lII/ParM1pA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="441792457" Received: from silpixa00399839.ir.intel.com (HELO localhost.localdomain) ([10.237.222.142]) by orsmga001.jf.intel.com with ESMTP; 23 Feb 2021 08:54:40 -0800 From: Ciara Loftus To: netdev@vger.kernel.org, bpf@vger.kernel.org, magnus.karlsson@intel.com, bjorn@kernel.org, weqaar.a.janjua@intel.com, maciej.fijalkowski@intel.com Cc: Ciara Loftus Subject: [PATCH bpf-next v3 2/4] selftests/bpf: expose and rename debug argument Date: Tue, 23 Feb 2021 16:23:02 +0000 Message-Id: <20210223162304.7450-3-ciara.loftus@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210223162304.7450-1-ciara.loftus@intel.com> References: <20210223162304.7450-1-ciara.loftus@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Launching xdpxceiver with -D enables what was formerly know as 'debug' mode. Rename this mode to 'dump-pkts' as it better describes the behavior enabled by the option. New usage: ./xdpxceiver .. -D or ./xdpxceiver .. --dump-pkts Also make it possible to pass this flag to the app via the test_xsk.sh shell script like so: ./test_xsk.sh -D Signed-off-by: Ciara Loftus --- tools/testing/selftests/bpf/test_xsk.sh | 10 +++++++++- tools/testing/selftests/bpf/xdpxceiver.c | 6 +++--- tools/testing/selftests/bpf/xsk_prereqs.sh | 3 ++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/bpf/test_xsk.sh b/tools/testing/selftests/bpf/test_xsk.sh index f4cedf4c2718..dbb129a36606 100755 --- a/tools/testing/selftests/bpf/test_xsk.sh +++ b/tools/testing/selftests/bpf/test_xsk.sh @@ -74,14 +74,18 @@ # # Run with verbose output: # sudo ./test_xsk.sh -v +# +# Run and dump packet contents: +# sudo ./test_xsk.sh -D . xsk_prereqs.sh -while getopts "cv" flag +while getopts "cvD" flag do case "${flag}" in c) colorconsole=1;; v) verbose=1;; + D) dump_pkts=1;; esac done @@ -138,6 +142,10 @@ if [[ $verbose -eq 1 ]]; then VERBOSE_ARG="-v" fi +if [[ $dump_pkts -eq 1 ]]; then + DUMP_PKTS_ARG="-D" +fi + test_status $retval "${TEST_NAME}" ## START TESTS diff --git a/tools/testing/selftests/bpf/xdpxceiver.c b/tools/testing/selftests/bpf/xdpxceiver.c index 8af746c9a6b6..506423201197 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.c +++ b/tools/testing/selftests/bpf/xdpxceiver.c @@ -58,7 +58,7 @@ * - Rx thread verifies if all 10k packets were received and delivered in-order, * and have the right content * - * Enable/disable debug mode: + * Enable/disable packet dump mode: * -------------------------- * To enable L2 - L4 headers and payload dump of each packet on STDOUT, add * parameter -D to params array in test_xsk.sh, i.e. params=("-S" "-D") @@ -340,7 +340,7 @@ static struct option long_options[] = { {"copy", no_argument, 0, 'c'}, {"tear-down", no_argument, 0, 'T'}, {"bidi", optional_argument, 0, 'B'}, - {"debug", optional_argument, 0, 'D'}, + {"dump-pkts", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"tx-pkt-count", optional_argument, 0, 'C'}, {0, 0, 0, 0} @@ -359,7 +359,7 @@ static void usage(const char *prog) " -c, --copy Force copy mode\n" " -T, --tear-down Tear down sockets by repeatedly recreating them\n" " -B, --bidi Bi-directional sockets test\n" - " -D, --debug Debug mode - dump packets L2 - L5\n" + " -D, --dump-pkts Dump packets L2 - L5\n" " -v, --verbose Verbose output\n" " -C, --tx-pkt-count=n Number of packets to send\n"; ksft_print_msg(str, prog); diff --git a/tools/testing/selftests/bpf/xsk_prereqs.sh b/tools/testing/selftests/bpf/xsk_prereqs.sh index ef8c5b31f4b6..da93575d757a 100755 --- a/tools/testing/selftests/bpf/xsk_prereqs.sh +++ b/tools/testing/selftests/bpf/xsk_prereqs.sh @@ -128,5 +128,6 @@ execxdpxceiver() copy[$index]=${!current} done - ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${copy[*]} -C ${NUMPKTS} ${VERBOSE_ARG} + ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${copy[*]} -C ${NUMPKTS} ${VERBOSE_ARG} \ + ${DUMP_PKTS_ARG} } From patchwork Tue Feb 23 16:23:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Loftus, Ciara" X-Patchwork-Id: 387124 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7BBF6C433E0 for ; Tue, 23 Feb 2021 16:57:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 332D164E2E for ; Tue, 23 Feb 2021 16:57:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233550AbhBWQ4s (ORCPT ); Tue, 23 Feb 2021 11:56:48 -0500 Received: from mga02.intel.com ([134.134.136.20]:25526 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233654AbhBWQ4l (ORCPT ); Tue, 23 Feb 2021 11:56:41 -0500 IronPort-SDR: 7P7xcSWQj72IgW9EcL31C1Svuc7PS9m2fXXjzY0HJsOAgF5tw+nggr49MvwDt8joYuYV6hKUGo Accm5TbzBiHw== X-IronPort-AV: E=McAfee;i="6000,8403,9904"; a="172010043" X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="172010043" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2021 08:56:00 -0800 IronPort-SDR: X7Hn6JrtZ3sqeDXbQeRQBGqHc7dd79g39dH2ivDzxwSvxpjVWaDqw6Sp8FtzJLJyi/8vAI4asW JceGkRpUpldw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="441792693" Received: from silpixa00399839.ir.intel.com (HELO localhost.localdomain) ([10.237.222.142]) by orsmga001.jf.intel.com with ESMTP; 23 Feb 2021 08:55:23 -0800 From: Ciara Loftus To: netdev@vger.kernel.org, bpf@vger.kernel.org, magnus.karlsson@intel.com, bjorn@kernel.org, weqaar.a.janjua@intel.com, maciej.fijalkowski@intel.com Cc: Ciara Loftus Subject: [PATCH bpf-next v3 3/4] selftests/bpf: restructure xsk selftests Date: Tue, 23 Feb 2021 16:23:03 +0000 Message-Id: <20210223162304.7450-4-ciara.loftus@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210223162304.7450-1-ciara.loftus@intel.com> References: <20210223162304.7450-1-ciara.loftus@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prior to this commit individual xsk tests were launched from the shell script 'test_xsk.sh'. When adding a new test type, two new test configurations had to be added to this file - one for each of the supported XDP 'modes' (skb or drv). Should zero copy support be added to the xsk selftest framework in the future, three new test configurations would need to be added for each new test type. Each new test type also typically requires new CLI arguments for the xdpxceiver program. This commit aims to reduce the overhead of adding new tests, by launching the test configurations from within the xdpxceiver program itself, using simple loops. Every test is run every time the C program is executed. Many of the CLI arguments can be removed as a result. Signed-off-by: Ciara Loftus Reviewed-by: Maciej Fijalkowski --- tools/testing/selftests/bpf/test_xsk.sh | 112 +---------- tools/testing/selftests/bpf/xdpxceiver.c | 218 +++++++++++++-------- tools/testing/selftests/bpf/xdpxceiver.h | 33 ++-- tools/testing/selftests/bpf/xsk_prereqs.sh | 24 +-- 4 files changed, 159 insertions(+), 228 deletions(-) diff --git a/tools/testing/selftests/bpf/test_xsk.sh b/tools/testing/selftests/bpf/test_xsk.sh index dbb129a36606..56d4474e2c83 100755 --- a/tools/testing/selftests/bpf/test_xsk.sh +++ b/tools/testing/selftests/bpf/test_xsk.sh @@ -152,117 +152,9 @@ test_status $retval "${TEST_NAME}" statusList=() -### TEST 1 -TEST_NAME="XSK KSELFTEST FRAMEWORK" +TEST_NAME="XSK KSELFTESTS" -if [[ $verbose -eq 1 ]]; then - echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Generic mode" -fi -vethXDPgeneric ${VETH0} ${VETH1} ${NS1} - -retval=$? -if [ $retval -eq 0 ]; then - if [[ $verbose -eq 1 ]]; then - echo "Switching interfaces [${VETH0}, ${VETH1}] to XDP Native mode" - fi - vethXDPnative ${VETH0} ${VETH1} ${NS1} -fi - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 2 -TEST_NAME="SKB NOPOLL" - -vethXDPgeneric ${VETH0} ${VETH1} ${NS1} - -params=("-S") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 3 -TEST_NAME="SKB POLL" - -vethXDPgeneric ${VETH0} ${VETH1} ${NS1} - -params=("-S" "-p") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 4 -TEST_NAME="DRV NOPOLL" - -vethXDPnative ${VETH0} ${VETH1} ${NS1} - -params=("-N") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 5 -TEST_NAME="DRV POLL" - -vethXDPnative ${VETH0} ${VETH1} ${NS1} - -params=("-N" "-p") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 6 -TEST_NAME="SKB SOCKET TEARDOWN" - -vethXDPgeneric ${VETH0} ${VETH1} ${NS1} - -params=("-S" "-T") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 7 -TEST_NAME="DRV SOCKET TEARDOWN" - -vethXDPnative ${VETH0} ${VETH1} ${NS1} - -params=("-N" "-T") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 8 -TEST_NAME="SKB BIDIRECTIONAL SOCKETS" - -vethXDPgeneric ${VETH0} ${VETH1} ${NS1} - -params=("-S" "-B") -execxdpxceiver params - -retval=$? -test_status $retval "${TEST_NAME}" -statusList+=($retval) - -### TEST 9 -TEST_NAME="DRV BIDIRECTIONAL SOCKETS" - -vethXDPnative ${VETH0} ${VETH1} ${NS1} - -params=("-N" "-B") -execxdpxceiver params +execxdpxceiver retval=$? test_status $retval "${TEST_NAME}" diff --git a/tools/testing/selftests/bpf/xdpxceiver.c b/tools/testing/selftests/bpf/xdpxceiver.c index 506423201197..e7913444518d 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.c +++ b/tools/testing/selftests/bpf/xdpxceiver.c @@ -18,12 +18,7 @@ * These selftests test AF_XDP SKB and Native/DRV modes using veth * Virtual Ethernet interfaces. * - * The following tests are run: - * - * 1. AF_XDP SKB mode - * Generic mode XDP is driver independent, used when the driver does - * not have support for XDP. Works on any netdevice using sockets and - * generic XDP path. XDP hook from netif_receive_skb(). + * For each mode, the following tests are run: * a. nopoll - soft-irq processing * b. poll - using poll() syscall * c. Socket Teardown @@ -34,17 +29,6 @@ * completion rings on each socket, tx/rx in both directions. Only nopoll * mode is used * - * 2. AF_XDP DRV/Native mode - * Works on any netdevice with XDP_REDIRECT support, driver dependent. Processes - * packets before SKB allocation. Provides better performance than SKB. Driver - * hook available just after DMA of buffer descriptor. - * a. nopoll - * b. poll - * c. Socket Teardown - * d. Bi-directional sockets - * - Only copy mode is supported because veth does not currently support - * zero-copy mode - * * Total tests: 8 * * Flow: @@ -98,17 +82,23 @@ typedef __u16 __sum16; static void __exit_with_error(int error, const char *file, const char *func, int line) { - ksft_test_result_fail - ("[%s:%s:%i]: ERROR: %d/\"%s\"\n", file, func, line, error, strerror(error)); - ksft_exit_xfail(); + if (configured_mode == TEST_MODE_UNCONFIGURED) { + ksft_exit_fail_msg + ("[%s:%s:%i]: ERROR: %d/\"%s\"\n", file, func, line, error, strerror(error)); + } else { + ksft_test_result_fail + ("[%s:%s:%i]: ERROR: %d/\"%s\"\n", file, func, line, error, strerror(error)); + ksft_exit_xfail(); + } } #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__) #define print_ksft_result(void)\ - (ksft_test_result_pass("PASS: %s %s %s%s\n", uut ? "DRV" : "SKB", opt_poll ? "POLL" :\ - "NOPOLL", opt_teardown ? "Socket Teardown" : "",\ - opt_bidi ? "Bi-directional Sockets" : "")) + (ksft_test_result_pass("PASS: %s %s %s%s\n", configured_mode ? "DRV" : "SKB",\ + test_type == TEST_TYPE_POLL ? "POLL" : "NOPOLL",\ + test_type == TEST_TYPE_TEARDOWN ? "Socket Teardown" : "",\ + test_type == TEST_TYPE_BIDI ? "Bi-directional Sockets" : "")) static void pthread_init_mutex(void) { @@ -311,10 +301,10 @@ static int xsk_configure_socket(struct ifobject *ifobject) cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; cfg.libbpf_flags = 0; - cfg.xdp_flags = opt_xdp_flags; - cfg.bind_flags = opt_xdp_bind_flags; + cfg.xdp_flags = xdp_flags; + cfg.bind_flags = xdp_bind_flags; - if (!opt_bidi) { + if (test_type != TEST_TYPE_BIDI) { rxr = (ifobject->fv.vector == rx) ? &ifobject->xsk->rx : NULL; txr = (ifobject->fv.vector == tx) ? &ifobject->xsk->tx : NULL; } else { @@ -334,12 +324,6 @@ static int xsk_configure_socket(struct ifobject *ifobject) static struct option long_options[] = { {"interface", required_argument, 0, 'i'}, {"queue", optional_argument, 0, 'q'}, - {"poll", no_argument, 0, 'p'}, - {"xdp-skb", no_argument, 0, 'S'}, - {"xdp-native", no_argument, 0, 'N'}, - {"copy", no_argument, 0, 'c'}, - {"tear-down", no_argument, 0, 'T'}, - {"bidi", optional_argument, 0, 'B'}, {"dump-pkts", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"tx-pkt-count", optional_argument, 0, 'C'}, @@ -353,12 +337,6 @@ static void usage(const char *prog) " Options:\n" " -i, --interface Use interface\n" " -q, --queue=n Use queue n (default 0)\n" - " -p, --poll Use poll syscall\n" - " -S, --xdp-skb=n Use XDP SKB mode\n" - " -N, --xdp-native=n Enforce XDP DRV (native) mode\n" - " -c, --copy Force copy mode\n" - " -T, --tear-down Tear down sockets by repeatedly recreating them\n" - " -B, --bidi Bi-directional sockets test\n" " -D, --dump-pkts Dump packets L2 - L5\n" " -v, --verbose Verbose output\n" " -C, --tx-pkt-count=n Number of packets to send\n"; @@ -448,7 +426,7 @@ static void parse_command_line(int argc, char **argv) opterr = 0; for (;;) { - c = getopt_long(argc, argv, "i:q:pSNcTBDC:v", long_options, &option_index); + c = getopt_long(argc, argv, "i:q:DC:v", long_options, &option_index); if (c == -1) break; @@ -471,28 +449,6 @@ static void parse_command_line(int argc, char **argv) case 'q': opt_queue = atoi(optarg); break; - case 'p': - opt_poll = 1; - break; - case 'S': - opt_xdp_flags |= XDP_FLAGS_SKB_MODE; - opt_xdp_bind_flags |= XDP_COPY; - uut = ORDER_CONTENT_VALIDATE_XDP_SKB; - break; - case 'N': - opt_xdp_flags |= XDP_FLAGS_DRV_MODE; - opt_xdp_bind_flags |= XDP_COPY; - uut = ORDER_CONTENT_VALIDATE_XDP_DRV; - break; - case 'c': - opt_xdp_bind_flags |= XDP_COPY; - break; - case 'T': - opt_teardown = 1; - break; - case 'B': - opt_bidi = 1; - break; case 'D': debug_pkt_dump = 1; break; @@ -508,6 +464,11 @@ static void parse_command_line(int argc, char **argv) } } + if (!opt_pkt_count) { + print_verbose("No tx-pkt-count specified, using default %u\n", DEFAULT_PKT_CNT); + opt_pkt_count = DEFAULT_PKT_CNT; + } + if (!validate_interfaces()) { usage(basename(argv[0])); ksft_exit_xfail(); @@ -659,7 +620,7 @@ static void tx_only_all(struct ifobject *ifobject) while ((opt_pkt_count && pkt_cnt < opt_pkt_count) || !opt_pkt_count) { int batch_size = get_batch_size(pkt_cnt); - if (opt_poll) { + if (test_type == TEST_TYPE_POLL) { ret = poll(fds, 1, POLL_TMOUT); if (ret <= 0) continue; @@ -883,7 +844,7 @@ static void *worker_testapp_validate(void *arg) pthread_mutex_unlock(&sync_mutex); while (1) { - if (opt_poll) { + if (test_type == TEST_TYPE_POLL) { ret = poll(fds, 1, POLL_TMOUT); if (ret <= 0) continue; @@ -898,11 +859,11 @@ static void *worker_testapp_validate(void *arg) print_verbose("Received %d packets on interface %s\n", pkt_counter, ifobject->ifname); - if (opt_teardown) + if (test_type == TEST_TYPE_TEARDOWN) print_verbose("Destroying socket\n"); } - if (!opt_bidi || bidi_pass) { + if ((test_type != TEST_TYPE_BIDI) || bidi_pass) { xsk_socket__delete(ifobject->xsk->xsk); (void)xsk_umem__delete(ifobject->umem->umem); } @@ -912,11 +873,12 @@ static void *worker_testapp_validate(void *arg) static void testapp_validate(void) { struct timespec max_wait = { 0, 0 }; + bool bidi = test_type == TEST_TYPE_BIDI; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, THREAD_STACK); - if (opt_bidi && bidi_pass) { + if ((test_type == TEST_TYPE_BIDI) && bidi_pass) { pthread_init_mutex(); if (!switching_notify) { print_verbose("Switching Tx/Rx vectors\n"); @@ -927,10 +889,10 @@ static void testapp_validate(void) pthread_mutex_lock(&sync_mutex); /*Spawn RX thread */ - if (!opt_bidi || !bidi_pass) { + if (!bidi || !bidi_pass) { if (pthread_create(&t0, &attr, worker_testapp_validate, ifdict[1])) exit_with_error(errno); - } else if (opt_bidi && bidi_pass) { + } else if (bidi && bidi_pass) { /*switch Tx/Rx vectors */ ifdict[0]->fv.vector = rx; if (pthread_create(&t0, &attr, worker_testapp_validate, ifdict[0])) @@ -947,10 +909,10 @@ static void testapp_validate(void) pthread_mutex_unlock(&sync_mutex); /*Spawn TX thread */ - if (!opt_bidi || !bidi_pass) { + if (!bidi || !bidi_pass) { if (pthread_create(&t1, &attr, worker_testapp_validate, ifdict[0])) exit_with_error(errno); - } else if (opt_bidi && bidi_pass) { + } else if (bidi && bidi_pass) { /*switch Tx/Rx vectors */ ifdict[1]->fv.vector = tx; if (pthread_create(&t1, &attr, worker_testapp_validate, ifdict[1])) @@ -969,19 +931,20 @@ static void testapp_validate(void) free(pkt_buf); } - if (!opt_teardown && !opt_bidi) + if (!(test_type == TEST_TYPE_TEARDOWN) && !bidi) print_ksft_result(); } static void testapp_sockets(void) { - for (int i = 0; i < (opt_teardown ? MAX_TEARDOWN_ITER : MAX_BIDI_ITER); i++) { + for (int i = 0; i < ((test_type == TEST_TYPE_TEARDOWN) ? MAX_TEARDOWN_ITER : MAX_BIDI_ITER); + i++) { pkt_counter = 0; prev_pkt = -1; sigvar = 0; print_verbose("Creating socket\n"); testapp_validate(); - opt_bidi ? bidi_pass++ : bidi_pass; + test_type == TEST_TYPE_BIDI ? bidi_pass++ : bidi_pass; } print_ksft_result(); @@ -1008,6 +971,98 @@ static void init_iface_config(struct ifaceconfigobj *ifaceconfig) ifdict[1]->src_port = ifaceconfig->dst_port; } +static void *nsdisablemodethread(void *args) +{ + struct targs *targs = args; + + targs->retptr = false; + + if (switch_namespace(targs->idx)) { + targs->retptr = bpf_set_link_xdp_fd(ifdict[targs->idx]->ifindex, -1, targs->flags); + } else { + targs->retptr = errno; + print_verbose("Failed to switch namespace to %s\n", ifdict[targs->idx]->nsname); + } + + pthread_exit(NULL); +} + +static void disable_xdp_mode(int mode) +{ + int err = 0; + __u32 flags = XDP_FLAGS_UPDATE_IF_NOEXIST | mode; + char *mode_str = mode & XDP_FLAGS_SKB_MODE ? "skb" : "drv"; + + for (int i = 0; i < MAX_INTERFACES; i++) { + if (strcmp(ifdict[i]->nsname, "")) { + struct targs *targs; + + targs = malloc(sizeof(*targs)); + memset(targs, 0, sizeof(*targs)); + if (!targs) + exit_with_error(errno); + + targs->idx = i; + targs->flags = flags; + if (pthread_create(&ns_thread, NULL, nsdisablemodethread, targs)) + exit_with_error(errno); + + pthread_join(ns_thread, NULL); + err = targs->retptr; + free(targs); + } else { + err = bpf_set_link_xdp_fd(ifdict[i]->ifindex, -1, flags); + } + + if (err) { + print_verbose("Failed to disable %s mode on interface %s\n", + mode_str, ifdict[i]->ifname); + exit_with_error(err); + } + + print_verbose("Disabled %s mode for interface: %s\n", mode_str, ifdict[i]->ifname); + configured_mode = mode & XDP_FLAGS_SKB_MODE ? TEST_MODE_DRV : TEST_MODE_SKB; + } +} + +static void run_pkt_test(int mode, int type) +{ + test_type = type; + + /* reset defaults after potential previous test */ + xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; + pkt_counter = 0; + switching_notify = 0; + bidi_pass = 0; + prev_pkt = -1; + ifdict[0]->fv.vector = tx; + ifdict[1]->fv.vector = rx; + + switch (mode) { + case (TEST_MODE_SKB): + if (configured_mode == TEST_MODE_DRV) + disable_xdp_mode(XDP_FLAGS_DRV_MODE); + xdp_flags |= XDP_FLAGS_SKB_MODE; + break; + case (TEST_MODE_DRV): + if (configured_mode == TEST_MODE_SKB) + disable_xdp_mode(XDP_FLAGS_SKB_MODE); + xdp_flags |= XDP_FLAGS_DRV_MODE; + break; + default: + break; + } + + pthread_init_mutex(); + + if ((test_type != TEST_TYPE_TEARDOWN) && (test_type != TEST_TYPE_BIDI)) + testapp_validate(); + else + testapp_sockets(); + + pthread_destroy_mutex(); +} + int main(int argc, char **argv) { struct rlimit _rlim = { RLIM_INFINITY, RLIM_INFINITY }; @@ -1021,6 +1076,7 @@ int main(int argc, char **argv) const char *IP2 = "192.168.100.161"; u16 UDP_DST_PORT = 2020; u16 UDP_SRC_PORT = 2121; + int i, j; ifaceconfig = malloc(sizeof(struct ifaceconfigobj)); memcpy(ifaceconfig->dst_mac, MAC1, ETH_ALEN); @@ -1046,24 +1102,18 @@ int main(int argc, char **argv) init_iface_config(ifaceconfig); - pthread_init_mutex(); + disable_xdp_mode(XDP_FLAGS_DRV_MODE); - ksft_set_plan(1); + ksft_set_plan(TEST_MODE_MAX * TEST_TYPE_MAX); - if (!opt_teardown && !opt_bidi) { - testapp_validate(); - } else if (opt_teardown && opt_bidi) { - ksft_test_result_fail("ERROR: parameters -T and -B cannot be used together\n"); - ksft_exit_xfail(); - } else { - testapp_sockets(); + for (i = 0; i < TEST_MODE_MAX; i++) { + for (j = 0; j < TEST_TYPE_MAX; j++) + run_pkt_test(i, j); } for (int i = 0; i < MAX_INTERFACES; i++) free(ifdict[i]); - pthread_destroy_mutex(); - ksft_exit_pass(); return 0; diff --git a/tools/testing/selftests/bpf/xdpxceiver.h b/tools/testing/selftests/bpf/xdpxceiver.h index f66f399dfb2d..e05703f661f8 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.h +++ b/tools/testing/selftests/bpf/xdpxceiver.h @@ -41,6 +41,7 @@ #define BATCH_SIZE 64 #define POLL_TMOUT 1000 #define NEED_WAKEUP true +#define DEFAULT_PKT_CNT 10000 #define print_verbose(x...) do { if (opt_verbose) ksft_print_msg(x); } while (0) @@ -48,28 +49,37 @@ typedef __u32 u32; typedef __u16 u16; typedef __u8 u8; -enum TESTS { - ORDER_CONTENT_VALIDATE_XDP_SKB = 0, - ORDER_CONTENT_VALIDATE_XDP_DRV = 1, +enum TEST_MODES { + TEST_MODE_UNCONFIGURED = -1, + TEST_MODE_SKB, + TEST_MODE_DRV, + TEST_MODE_MAX }; -static u8 uut; +enum TEST_TYPES { + TEST_TYPE_NOPOLL, + TEST_TYPE_POLL, + TEST_TYPE_TEARDOWN, + TEST_TYPE_BIDI, + TEST_TYPE_MAX +}; + +static int configured_mode = TEST_MODE_UNCONFIGURED; static u8 debug_pkt_dump; static u32 num_frames; static u8 switching_notify; static u8 bidi_pass; +static int test_type; -static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; static int opt_queue; static int opt_pkt_count; -static int opt_poll; -static int opt_teardown; -static int opt_bidi; -static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP; static u8 opt_verbose; + +static u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; +static u32 xdp_bind_flags = XDP_USE_NEED_WAKEUP | XDP_COPY; static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE]; static u32 pkt_counter; -static u32 prev_pkt = -1; +static long prev_pkt = -1; static int sigvar; struct xsk_umem_info { @@ -140,8 +150,9 @@ pthread_t t0, t1, ns_thread; pthread_attr_t attr; struct targs { - bool retptr; + u8 retptr; int idx; + u32 flags; }; TAILQ_HEAD(head_s, pkt) head = TAILQ_HEAD_INITIALIZER(head); diff --git a/tools/testing/selftests/bpf/xsk_prereqs.sh b/tools/testing/selftests/bpf/xsk_prereqs.sh index da93575d757a..dac1c5f78752 100755 --- a/tools/testing/selftests/bpf/xsk_prereqs.sh +++ b/tools/testing/selftests/bpf/xsk_prereqs.sh @@ -105,29 +105,7 @@ validate_ip_utility() [ ! $(type -P ip) ] && { echo "'ip' not found. Skipping tests."; test_exit $ksft_skip 1; } } -vethXDPgeneric() -{ - ip link set dev $1 xdpdrv off - ip netns exec $3 ip link set dev $2 xdpdrv off -} - -vethXDPnative() -{ - ip link set dev $1 xdpgeneric off - ip netns exec $3 ip link set dev $2 xdpgeneric off -} - execxdpxceiver() { - local -a 'paramkeys=("${!'"$1"'[@]}")' copy - paramkeysstr=${paramkeys[*]} - - for index in $paramkeysstr; - do - current=$1"[$index]" - copy[$index]=${!current} - done - - ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${copy[*]} -C ${NUMPKTS} ${VERBOSE_ARG} \ - ${DUMP_PKTS_ARG} + ./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} -C ${NUMPKTS} ${VERBOSE_ARG} ${DUMP_PKTS_ARG} } From patchwork Tue Feb 23 16:23:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Loftus, Ciara" X-Patchwork-Id: 386564 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58743C433DB for ; Tue, 23 Feb 2021 16:57:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 216CB64E2E for ; Tue, 23 Feb 2021 16:57:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233660AbhBWQ5b (ORCPT ); Tue, 23 Feb 2021 11:57:31 -0500 Received: from mga03.intel.com ([134.134.136.65]:62263 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233652AbhBWQ5Z (ORCPT ); Tue, 23 Feb 2021 11:57:25 -0500 IronPort-SDR: /7epWHz9s1teRqlGz5KkmQIIqWD4V0beqsq/WnEX/xI6+I3SGlepfj/nbhWPTq1TgsY6nQC7zz TqbiemhFuCLg== X-IronPort-AV: E=McAfee;i="6000,8403,9904"; a="184924339" X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="184924339" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2021 08:56:43 -0800 IronPort-SDR: ybH+PKlQuAdUi04e1RwRn5H3iG2lY4qejtY1zJQOlhU1lwvsuw4JChD23MddqfbWyyj/xbOA3b 8PzeHFw0/s6Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,200,1610438400"; d="scan'208";a="441792894" Received: from silpixa00399839.ir.intel.com (HELO localhost.localdomain) ([10.237.222.142]) by orsmga001.jf.intel.com with ESMTP; 23 Feb 2021 08:56:05 -0800 From: Ciara Loftus To: netdev@vger.kernel.org, bpf@vger.kernel.org, magnus.karlsson@intel.com, bjorn@kernel.org, weqaar.a.janjua@intel.com, maciej.fijalkowski@intel.com Cc: Ciara Loftus Subject: [PATCH bpf-next v3 4/4] selftests/bpf: introduce xsk statistics tests Date: Tue, 23 Feb 2021 16:23:04 +0000 Message-Id: <20210223162304.7450-5-ciara.loftus@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210223162304.7450-1-ciara.loftus@intel.com> References: <20210223162304.7450-1-ciara.loftus@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This commit introduces a range of tests to the xsk testsuite for validating xsk statistics. A new test type called 'stats' is added. Within it there are four sub-tests. Each test configures a scenario which should trigger the given error statistic. The test passes if the statistic is successfully incremented. The four statistics for which tests have been created are: 1. rx dropped Increase the UMEM frame headroom to a value which results in insufficient space in the rx buffer for both the packet and the headroom. 2. tx invalid Set the 'len' field of tx descriptors to an invalid value (umem frame size + 1). 3. rx ring full Reduce the size of the RX ring to a fraction of the fill ring size. 4. fill queue empty Do not populate the fill queue and then try to receive pkts. Signed-off-by: Ciara Loftus Reviewed-by: Maciej Fijalkowski --- tools/testing/selftests/bpf/xdpxceiver.c | 137 ++++++++++++++++++++--- tools/testing/selftests/bpf/xdpxceiver.h | 13 +++ 2 files changed, 136 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/bpf/xdpxceiver.c b/tools/testing/selftests/bpf/xdpxceiver.c index e7913444518d..8b0f7fdd9003 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.c +++ b/tools/testing/selftests/bpf/xdpxceiver.c @@ -28,8 +28,21 @@ * Configure sockets as bi-directional tx/rx sockets, sets up fill and * completion rings on each socket, tx/rx in both directions. Only nopoll * mode is used + * e. Statistics + * Trigger some error conditions and ensure that the appropriate statistics + * are incremented. Within this test, the following statistics are tested: + * i. rx dropped + * Increase the UMEM frame headroom to a value which results in + * insufficient space in the rx buffer for both the packet and the headroom. + * ii. tx invalid + * Set the 'len' field of tx descriptors to an invalid value (umem frame + * size + 1). + * iii. rx ring full + * Reduce the size of the RX ring to a fraction of the fill ring size. + * iv. fill queue empty + * Do not populate the fill queue and then try to receive pkts. * - * Total tests: 8 + * Total tests: 10 * * Flow: * ----- @@ -95,10 +108,11 @@ static void __exit_with_error(int error, const char *file, const char *func, int #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__) #define print_ksft_result(void)\ - (ksft_test_result_pass("PASS: %s %s %s%s\n", configured_mode ? "DRV" : "SKB",\ + (ksft_test_result_pass("PASS: %s %s %s%s%s\n", configured_mode ? "DRV" : "SKB",\ test_type == TEST_TYPE_POLL ? "POLL" : "NOPOLL",\ test_type == TEST_TYPE_TEARDOWN ? "Socket Teardown" : "",\ - test_type == TEST_TYPE_BIDI ? "Bi-directional Sockets" : "")) + test_type == TEST_TYPE_BIDI ? "Bi-directional Sockets" : "",\ + test_type == TEST_TYPE_STATS ? "Stats" : "")) static void pthread_init_mutex(void) { @@ -260,13 +274,20 @@ static void gen_eth_frame(struct xsk_umem_info *umem, u64 addr) static void xsk_configure_umem(struct ifobject *data, void *buffer, u64 size) { int ret; + struct xsk_umem_config cfg = { + .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS, + .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS, + .frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE, + .frame_headroom = frame_headroom, + .flags = XSK_UMEM__DEFAULT_FLAGS + }; data->umem = calloc(1, sizeof(struct xsk_umem_info)); if (!data->umem) exit_with_error(errno); ret = xsk_umem__create(&data->umem->umem, buffer, size, - &data->umem->fq, &data->umem->cq, NULL); + &data->umem->fq, &data->umem->cq, &cfg); if (ret) exit_with_error(ret); @@ -298,7 +319,7 @@ static int xsk_configure_socket(struct ifobject *ifobject) exit_with_error(errno); ifobject->xsk->umem = ifobject->umem; - cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; + cfg.rx_size = rxqsize; cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; cfg.libbpf_flags = 0; cfg.xdp_flags = xdp_flags; @@ -565,6 +586,8 @@ static void tx_only(struct xsk_socket_info *xsk, u32 *frameptr, int batch_size) { u32 idx; unsigned int i; + bool tx_invalid_test = stat_test_type == STAT_TEST_TX_INVALID; + u32 len = tx_invalid_test ? XSK_UMEM__DEFAULT_FRAME_SIZE + 1 : PKT_SIZE; while (xsk_ring_prod__reserve(&xsk->tx, batch_size, &idx) < batch_size) complete_tx_only(xsk, batch_size); @@ -573,11 +596,16 @@ static void tx_only(struct xsk_socket_info *xsk, u32 *frameptr, int batch_size) struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i); tx_desc->addr = (*frameptr + i) << XSK_UMEM__DEFAULT_FRAME_SHIFT; - tx_desc->len = PKT_SIZE; + tx_desc->len = len; } xsk_ring_prod__submit(&xsk->tx, batch_size); - xsk->outstanding_tx += batch_size; + if (!tx_invalid_test) { + xsk->outstanding_tx += batch_size; + } else { + if (!NEED_WAKEUP || xsk_ring_prod__needs_wakeup(&xsk->tx)) + kick_tx(xsk); + } *frameptr += batch_size; *frameptr %= num_frames; complete_tx_only(xsk, batch_size); @@ -689,6 +717,48 @@ static void worker_pkt_dump(void) } } +static void worker_stats_validate(struct ifobject *ifobject) +{ + struct xdp_statistics stats; + socklen_t optlen; + int err; + struct xsk_socket *xsk = stat_test_type == STAT_TEST_TX_INVALID ? + ifdict[!ifobject->ifdict_index]->xsk->xsk : + ifobject->xsk->xsk; + int fd = xsk_socket__fd(xsk); + unsigned long xsk_stat = 0, expected_stat = opt_pkt_count; + + sigvar = 0; + + optlen = sizeof(stats); + err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen); + if (err) + return; + + if (optlen == sizeof(struct xdp_statistics)) { + switch (stat_test_type) { + case STAT_TEST_RX_DROPPED: + xsk_stat = stats.rx_dropped; + break; + case STAT_TEST_TX_INVALID: + xsk_stat = stats.tx_invalid_descs; + break; + case STAT_TEST_RX_FULL: + xsk_stat = stats.rx_ring_full; + expected_stat -= RX_FULL_RXQSIZE; + break; + case STAT_TEST_RX_FILL_EMPTY: + xsk_stat = stats.rx_fill_ring_empty_descs; + break; + default: + break; + } + + if (xsk_stat == expected_stat) + sigvar = 1; + } +} + static void worker_pkt_validate(void) { u32 payloadseqnum = -2; @@ -827,7 +897,8 @@ static void *worker_testapp_validate(void *arg) thread_common_ops(ifobject, bufs, &sync_mutex_tx, &spinning_rx); print_verbose("Interface [%s] vector [Rx]\n", ifobject->ifname); - xsk_populate_fill_ring(ifobject->umem); + if (stat_test_type != STAT_TEST_RX_FILL_EMPTY) + xsk_populate_fill_ring(ifobject->umem); TAILQ_INIT(&head); if (debug_pkt_dump) { @@ -849,15 +920,21 @@ static void *worker_testapp_validate(void *arg) if (ret <= 0) continue; } - rx_pkt(ifobject->xsk, fds); - worker_pkt_validate(); + + if (test_type != TEST_TYPE_STATS) { + rx_pkt(ifobject->xsk, fds); + worker_pkt_validate(); + } else { + worker_stats_validate(ifobject); + } if (sigvar) break; } - print_verbose("Received %d packets on interface %s\n", - pkt_counter, ifobject->ifname); + if (test_type != TEST_TYPE_STATS) + print_verbose("Received %d packets on interface %s\n", + pkt_counter, ifobject->ifname); if (test_type == TEST_TYPE_TEARDOWN) print_verbose("Destroying socket\n"); @@ -931,7 +1008,7 @@ static void testapp_validate(void) free(pkt_buf); } - if (!(test_type == TEST_TYPE_TEARDOWN) && !bidi) + if (!(test_type == TEST_TYPE_TEARDOWN) && !bidi && !(test_type == TEST_TYPE_STATS)) print_ksft_result(); } @@ -950,6 +1027,32 @@ static void testapp_sockets(void) print_ksft_result(); } +static void testapp_stats(void) +{ + for (int i = 0; i < STAT_TEST_TYPE_MAX; i++) { + stat_test_type = i; + + /* reset defaults */ + rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS; + frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM; + + switch (stat_test_type) { + case STAT_TEST_RX_DROPPED: + frame_headroom = XSK_UMEM__DEFAULT_FRAME_SIZE - + XDP_PACKET_HEADROOM - 1; + break; + case STAT_TEST_RX_FULL: + rxqsize = RX_FULL_RXQSIZE; + break; + default: + break; + } + testapp_validate(); + } + + print_ksft_result(); +} + static void init_iface_config(struct ifaceconfigobj *ifaceconfig) { /*Init interface0 */ @@ -1037,6 +1140,10 @@ static void run_pkt_test(int mode, int type) prev_pkt = -1; ifdict[0]->fv.vector = tx; ifdict[1]->fv.vector = rx; + sigvar = 0; + stat_test_type = -1; + rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS; + frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM; switch (mode) { case (TEST_MODE_SKB): @@ -1055,7 +1162,9 @@ static void run_pkt_test(int mode, int type) pthread_init_mutex(); - if ((test_type != TEST_TYPE_TEARDOWN) && (test_type != TEST_TYPE_BIDI)) + if (test_type == TEST_TYPE_STATS) + testapp_stats(); + else if ((test_type != TEST_TYPE_TEARDOWN) && (test_type != TEST_TYPE_BIDI)) testapp_validate(); else testapp_sockets(); diff --git a/tools/testing/selftests/bpf/xdpxceiver.h b/tools/testing/selftests/bpf/xdpxceiver.h index e05703f661f8..30314ef305c2 100644 --- a/tools/testing/selftests/bpf/xdpxceiver.h +++ b/tools/testing/selftests/bpf/xdpxceiver.h @@ -42,6 +42,7 @@ #define POLL_TMOUT 1000 #define NEED_WAKEUP true #define DEFAULT_PKT_CNT 10000 +#define RX_FULL_RXQSIZE 32 #define print_verbose(x...) do { if (opt_verbose) ksft_print_msg(x); } while (0) @@ -61,9 +62,18 @@ enum TEST_TYPES { TEST_TYPE_POLL, TEST_TYPE_TEARDOWN, TEST_TYPE_BIDI, + TEST_TYPE_STATS, TEST_TYPE_MAX }; +enum STAT_TEST_TYPES { + STAT_TEST_RX_DROPPED, + STAT_TEST_TX_INVALID, + STAT_TEST_RX_FULL, + STAT_TEST_RX_FILL_EMPTY, + STAT_TEST_TYPE_MAX +}; + static int configured_mode = TEST_MODE_UNCONFIGURED; static u8 debug_pkt_dump; static u32 num_frames; @@ -81,6 +91,9 @@ static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE]; static u32 pkt_counter; static long prev_pkt = -1; static int sigvar; +static int stat_test_type; +static u32 rxqsize; +static u32 frame_headroom; struct xsk_umem_info { struct xsk_ring_prod fq;