Commit 99f785d5 authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'selftests: xsk: add busy-poll testing plus various fixes'

Magnus Karlsson says:

====================

This patch set adds busy-poll testing to the xsk selftests. It runs
exactly the same tests as with regular softirq processing, but with
busy-poll enabled. I have also included a number of fixes to the
selftests that have been bugging me for a while or was discovered
while implementing the busy-poll support. In summary these are:

* Fix the error reporting of failed tests. Each failed test used to be
  reported as both failed and passed, messing up things.

* Added a summary test printout at the end of the test suite so that
  users do not have to scroll up and look at the result of both the
  softirq run and the busy_poll run.

* Added a timeout to the tests, so that if a test locks up, we report
  a fail and still get to run all the other tests.

* Made the stats test just look and feel like all the other
  tests. Makes the code simpler and the test reporting more
  consistent. These are the 3 last commits.

* Replaced zero length packets with packets of 64 byte length. This so
  that some of the tests will pass after commit 726e2c59 ("veth:
  Ensure eth header is in skb's linear part").

* Added clean-up of the veth pair when terminating the test run.

* Some smaller clean-ups of unused stuff.

Note, to pass the busy-poll tests commit 8de8b71b ("xsk: Fix
l2fwd for copy mode + busy poll combo") need to be present. It is
present in bpf but not yet in bpf-next.

Thanks: Magnus
====================
Acked-by: default avatarBjörn Töpel <bjorn@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents b63b3c49 27e934be
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
# ** veth<xxxx> in root namespace # ** veth<xxxx> in root namespace
# ** veth<yyyy> in af_xdp<xxxx> namespace # ** veth<yyyy> in af_xdp<xxxx> namespace
# ** namespace af_xdp<xxxx> # ** namespace af_xdp<xxxx>
# * create a spec file veth.spec that includes this run-time configuration
# *** xxxx and yyyy are randomly generated 4 digit numbers used to avoid # *** xxxx and yyyy are randomly generated 4 digit numbers used to avoid
# conflict with any existing interface # conflict with any existing interface
# * tests the veth and xsk layers of the topology # * tests the veth and xsk layers of the topology
...@@ -77,7 +76,7 @@ ...@@ -77,7 +76,7 @@
. xsk_prereqs.sh . xsk_prereqs.sh
while getopts "cvD" flag while getopts "vD" flag
do do
case "${flag}" in case "${flag}" in
v) verbose=1;; v) verbose=1;;
...@@ -88,7 +87,7 @@ done ...@@ -88,7 +87,7 @@ done
TEST_NAME="PREREQUISITES" TEST_NAME="PREREQUISITES"
URANDOM=/dev/urandom URANDOM=/dev/urandom
[ ! -e "${URANDOM}" ] && { echo "${URANDOM} not found. Skipping tests."; test_exit 1 1; } [ ! -e "${URANDOM}" ] && { echo "${URANDOM} not found. Skipping tests."; test_exit $ksft_fail; }
VETH0_POSTFIX=$(cat ${URANDOM} | tr -dc '0-9' | fold -w 256 | head -n 1 | head --bytes 4) VETH0_POSTFIX=$(cat ${URANDOM} | tr -dc '0-9' | fold -w 256 | head -n 1 | head --bytes 4)
VETH0=ve${VETH0_POSTFIX} VETH0=ve${VETH0_POSTFIX}
...@@ -98,6 +97,13 @@ NS0=root ...@@ -98,6 +97,13 @@ NS0=root
NS1=af_xdp${VETH1_POSTFIX} NS1=af_xdp${VETH1_POSTFIX}
MTU=1500 MTU=1500
trap ctrl_c INT
function ctrl_c() {
cleanup_exit ${VETH0} ${VETH1} ${NS1}
exit 1
}
setup_vethPairs() { setup_vethPairs() {
if [[ $verbose -eq 1 ]]; then if [[ $verbose -eq 1 ]]; then
echo "setting up ${VETH0}: namespace: ${NS0}" echo "setting up ${VETH0}: namespace: ${NS0}"
...@@ -110,6 +116,14 @@ setup_vethPairs() { ...@@ -110,6 +116,14 @@ setup_vethPairs() {
if [[ $verbose -eq 1 ]]; then if [[ $verbose -eq 1 ]]; then
echo "setting up ${VETH1}: namespace: ${NS1}" echo "setting up ${VETH1}: namespace: ${NS1}"
fi fi
if [[ $busy_poll -eq 1 ]]; then
echo 2 > /sys/class/net/${VETH0}/napi_defer_hard_irqs
echo 200000 > /sys/class/net/${VETH0}/gro_flush_timeout
echo 2 > /sys/class/net/${VETH1}/napi_defer_hard_irqs
echo 200000 > /sys/class/net/${VETH1}/gro_flush_timeout
fi
ip link set ${VETH1} netns ${NS1} ip link set ${VETH1} netns ${NS1}
ip netns exec ${NS1} ip link set ${VETH1} mtu ${MTU} ip netns exec ${NS1} ip link set ${VETH1} mtu ${MTU}
ip link set ${VETH0} mtu ${MTU} ip link set ${VETH0} mtu ${MTU}
...@@ -130,17 +144,12 @@ if [ $retval -ne 0 ]; then ...@@ -130,17 +144,12 @@ if [ $retval -ne 0 ]; then
exit $retval exit $retval
fi fi
echo "${VETH0}:${VETH1},${NS1}" > ${SPECFILE}
validate_veth_spec_file
if [[ $verbose -eq 1 ]]; then if [[ $verbose -eq 1 ]]; then
echo "Spec file created: ${SPECFILE}" ARGS+="-v "
VERBOSE_ARG="-v"
fi fi
if [[ $dump_pkts -eq 1 ]]; then if [[ $dump_pkts -eq 1 ]]; then
DUMP_PKTS_ARG="-D" ARGS="-D "
fi fi
test_status $retval "${TEST_NAME}" test_status $retval "${TEST_NAME}"
...@@ -149,23 +158,31 @@ test_status $retval "${TEST_NAME}" ...@@ -149,23 +158,31 @@ test_status $retval "${TEST_NAME}"
statusList=() statusList=()
TEST_NAME="XSK KSELFTESTS" TEST_NAME="XSK_SELFTESTS_SOFTIRQ"
execxdpxceiver execxdpxceiver
retval=$? cleanup_exit ${VETH0} ${VETH1} ${NS1}
test_status $retval "${TEST_NAME}" TEST_NAME="XSK_SELFTESTS_BUSY_POLL"
statusList+=($retval) busy_poll=1
setup_vethPairs
execxdpxceiver
## END TESTS ## END TESTS
cleanup_exit ${VETH0} ${VETH1} ${NS1} cleanup_exit ${VETH0} ${VETH1} ${NS1}
for _status in "${statusList[@]}" failures=0
echo -e "\nSummary:"
for i in "${!statusList[@]}"
do do
if [ $_status -ne 0 ]; then if [ ${statusList[$i]} -ne 0 ]; then
test_exit $ksft_fail 0 test_status ${statusList[$i]} ${nameList[$i]}
failures=1
fi fi
done done
test_exit $ksft_pass 0 if [ $failures -eq 0 ]; then
echo "All tests successful!"
fi
This diff is collapsed.
...@@ -17,6 +17,16 @@ ...@@ -17,6 +17,16 @@
#define PF_XDP AF_XDP #define PF_XDP AF_XDP
#endif #endif
#ifndef SO_BUSY_POLL_BUDGET
#define SO_BUSY_POLL_BUDGET 70
#endif
#ifndef SO_PREFER_BUSY_POLL
#define SO_PREFER_BUSY_POLL 69
#endif
#define TEST_PASS 0
#define TEST_FAILURE -1
#define MAX_INTERFACES 2 #define MAX_INTERFACES 2
#define MAX_INTERFACE_NAME_CHARS 7 #define MAX_INTERFACE_NAME_CHARS 7
#define MAX_INTERFACES_NAMESPACE_CHARS 10 #define MAX_INTERFACES_NAMESPACE_CHARS 10
...@@ -25,9 +35,10 @@ ...@@ -25,9 +35,10 @@
#define MAX_TEARDOWN_ITER 10 #define MAX_TEARDOWN_ITER 10
#define PKT_HDR_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \ #define PKT_HDR_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
sizeof(struct udphdr)) sizeof(struct udphdr))
#define MIN_PKT_SIZE 64 #define MIN_ETH_PKT_SIZE 64
#define ETH_FCS_SIZE 4 #define ETH_FCS_SIZE 4
#define PKT_SIZE (MIN_PKT_SIZE - ETH_FCS_SIZE) #define MIN_PKT_SIZE (MIN_ETH_PKT_SIZE - ETH_FCS_SIZE)
#define PKT_SIZE (MIN_PKT_SIZE)
#define IP_PKT_SIZE (PKT_SIZE - sizeof(struct ethhdr)) #define IP_PKT_SIZE (PKT_SIZE - sizeof(struct ethhdr))
#define IP_PKT_VER 0x4 #define IP_PKT_VER 0x4
#define IP_PKT_TOS 0x9 #define IP_PKT_TOS 0x9
...@@ -37,6 +48,7 @@ ...@@ -37,6 +48,7 @@
#define SOCK_RECONF_CTR 10 #define SOCK_RECONF_CTR 10
#define BATCH_SIZE 64 #define BATCH_SIZE 64
#define POLL_TMOUT 1000 #define POLL_TMOUT 1000
#define RECV_TMOUT 3
#define DEFAULT_PKT_CNT (4 * 1024) #define DEFAULT_PKT_CNT (4 * 1024)
#define DEFAULT_UMEM_BUFFERS (DEFAULT_PKT_CNT / 4) #define DEFAULT_UMEM_BUFFERS (DEFAULT_PKT_CNT / 4)
#define UMEM_SIZE (DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE) #define UMEM_SIZE (DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE)
...@@ -64,24 +76,16 @@ enum test_type { ...@@ -64,24 +76,16 @@ enum test_type {
TEST_TYPE_HEADROOM, TEST_TYPE_HEADROOM,
TEST_TYPE_TEARDOWN, TEST_TYPE_TEARDOWN,
TEST_TYPE_BIDI, TEST_TYPE_BIDI,
TEST_TYPE_STATS, TEST_TYPE_STATS_RX_DROPPED,
TEST_TYPE_STATS_TX_INVALID_DESCS,
TEST_TYPE_STATS_RX_FULL,
TEST_TYPE_STATS_FILL_EMPTY,
TEST_TYPE_BPF_RES, TEST_TYPE_BPF_RES,
TEST_TYPE_MAX TEST_TYPE_MAX
}; };
enum stat_test_type {
STAT_TEST_RX_DROPPED,
STAT_TEST_TX_INVALID,
STAT_TEST_RX_FULL,
STAT_TEST_RX_FILL_EMPTY,
STAT_TEST_TYPE_MAX
};
static bool opt_pkt_dump; static bool opt_pkt_dump;
static int test_type;
static bool opt_verbose; static bool opt_verbose;
static int stat_test_type;
struct xsk_umem_info { struct xsk_umem_info {
struct xsk_ring_prod fq; struct xsk_ring_prod fq;
...@@ -117,6 +121,8 @@ struct pkt_stream { ...@@ -117,6 +121,8 @@ struct pkt_stream {
bool use_addr_for_fill; bool use_addr_for_fill;
}; };
struct ifobject;
typedef int (*validation_func_t)(struct ifobject *ifobj);
typedef void *(*thread_func_t)(void *arg); typedef void *(*thread_func_t)(void *arg);
struct ifobject { struct ifobject {
...@@ -126,6 +132,7 @@ struct ifobject { ...@@ -126,6 +132,7 @@ struct ifobject {
struct xsk_socket_info *xsk_arr; struct xsk_socket_info *xsk_arr;
struct xsk_umem_info *umem; struct xsk_umem_info *umem;
thread_func_t func_ptr; thread_func_t func_ptr;
validation_func_t validation_func;
struct pkt_stream *pkt_stream; struct pkt_stream *pkt_stream;
int ns_fd; int ns_fd;
int xsk_map_fd; int xsk_map_fd;
...@@ -138,7 +145,9 @@ struct ifobject { ...@@ -138,7 +145,9 @@ struct ifobject {
bool tx_on; bool tx_on;
bool rx_on; bool rx_on;
bool use_poll; bool use_poll;
bool pacing_on; bool busy_poll;
bool use_fill_ring;
bool release_rx;
u8 dst_mac[ETH_ALEN]; u8 dst_mac[ETH_ALEN];
u8 src_mac[ETH_ALEN]; u8 src_mac[ETH_ALEN];
}; };
...@@ -150,6 +159,7 @@ struct test_spec { ...@@ -150,6 +159,7 @@ struct test_spec {
u16 total_steps; u16 total_steps;
u16 current_step; u16 current_step;
u16 nb_sockets; u16 nb_sockets;
bool fail;
char name[MAX_TEST_NAME_SIZE]; char name[MAX_TEST_NAME_SIZE];
}; };
...@@ -157,6 +167,6 @@ pthread_barrier_t barr; ...@@ -157,6 +167,6 @@ pthread_barrier_t barr;
pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t pacing_cond = PTHREAD_COND_INITIALIZER; pthread_cond_t pacing_cond = PTHREAD_COND_INITIALIZER;
u32 pkts_in_flight; int pkts_in_flight;
#endif /* XDPXCEIVER_H */ #endif /* XDPXCEIVER_H */
...@@ -8,7 +8,6 @@ ksft_xfail=2 ...@@ -8,7 +8,6 @@ ksft_xfail=2
ksft_xpass=3 ksft_xpass=3
ksft_skip=4 ksft_skip=4
SPECFILE=veth.spec
XSKOBJ=xdpxceiver XSKOBJ=xdpxceiver
validate_root_exec() validate_root_exec()
...@@ -16,7 +15,7 @@ validate_root_exec() ...@@ -16,7 +15,7 @@ validate_root_exec()
msg="skip all tests:" msg="skip all tests:"
if [ $UID != 0 ]; then if [ $UID != 0 ]; then
echo $msg must be run as root >&2 echo $msg must be run as root >&2
test_exit $ksft_fail 2 test_exit $ksft_fail
else else
return $ksft_pass return $ksft_pass
fi fi
...@@ -27,39 +26,31 @@ validate_veth_support() ...@@ -27,39 +26,31 @@ validate_veth_support()
msg="skip all tests:" msg="skip all tests:"
if [ $(ip link add $1 type veth 2>/dev/null; echo $?;) != 0 ]; then if [ $(ip link add $1 type veth 2>/dev/null; echo $?;) != 0 ]; then
echo $msg veth kernel support not available >&2 echo $msg veth kernel support not available >&2
test_exit $ksft_skip 1 test_exit $ksft_skip
else else
ip link del $1 ip link del $1
return $ksft_pass return $ksft_pass
fi fi
} }
validate_veth_spec_file()
{
if [ ! -f ${SPECFILE} ]; then
test_exit $ksft_skip 1
fi
}
test_status() test_status()
{ {
statusval=$1 statusval=$1
if [ $statusval -eq 2 ]; then if [ $statusval -eq $ksft_fail ]; then
echo -e "$2: [ FAIL ]" echo "$2: [ FAIL ]"
elif [ $statusval -eq 1 ]; then elif [ $statusval -eq $ksft_skip ]; then
echo -e "$2: [ SKIPPED ]" echo "$2: [ SKIPPED ]"
elif [ $statusval -eq 0 ]; then elif [ $statusval -eq $ksft_pass ]; then
echo -e "$2: [ PASS ]" echo "$2: [ PASS ]"
fi fi
} }
test_exit() test_exit()
{ {
retval=$1 if [ $1 -ne 0 ]; then
if [ $2 -ne 0 ]; then test_status $1 $(basename $0)
test_status $2 $(basename $0)
fi fi
exit $retval exit 1
} }
clear_configs() clear_configs()
...@@ -74,9 +65,6 @@ clear_configs() ...@@ -74,9 +65,6 @@ clear_configs()
#veth node inside NS won't get removed so we explicitly remove it #veth node inside NS won't get removed so we explicitly remove it
[ $(ip link show $1 &>/dev/null; echo $?;) == 0 ] && [ $(ip link show $1 &>/dev/null; echo $?;) == 0 ] &&
{ ip link del $1; } { ip link del $1; }
if [ -f ${SPECFILE} ]; then
rm -f ${SPECFILE}
fi
} }
cleanup_exit() cleanup_exit()
...@@ -86,10 +74,19 @@ cleanup_exit() ...@@ -86,10 +74,19 @@ cleanup_exit()
validate_ip_utility() validate_ip_utility()
{ {
[ ! $(type -P ip) ] && { echo "'ip' not found. Skipping tests."; test_exit $ksft_skip 1; } [ ! $(type -P ip) ] && { echo "'ip' not found. Skipping tests."; test_exit $ksft_skip; }
} }
execxdpxceiver() execxdpxceiver()
{ {
./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${VERBOSE_ARG} ${DUMP_PKTS_ARG} if [[ $busy_poll -eq 1 ]]; then
ARGS+="-b "
fi
./${XSKOBJ} -i ${VETH0} -i ${VETH1},${NS1} ${ARGS}
retval=$?
test_status $retval "${TEST_NAME}"
statusList+=($retval)
nameList+=(${TEST_NAME})
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment