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 @@
# ** veth<xxxx> in root namespace
# ** veth<yyyy> in af_xdp<xxxx> namespace
# ** 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
# conflict with any existing interface
# * tests the veth and xsk layers of the topology
......@@ -77,7 +76,7 @@
. xsk_prereqs.sh
while getopts "cvD" flag
while getopts "vD" flag
do
case "${flag}" in
v) verbose=1;;
......@@ -88,7 +87,7 @@ done
TEST_NAME="PREREQUISITES"
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=ve${VETH0_POSTFIX}
......@@ -98,6 +97,13 @@ NS0=root
NS1=af_xdp${VETH1_POSTFIX}
MTU=1500
trap ctrl_c INT
function ctrl_c() {
cleanup_exit ${VETH0} ${VETH1} ${NS1}
exit 1
}
setup_vethPairs() {
if [[ $verbose -eq 1 ]]; then
echo "setting up ${VETH0}: namespace: ${NS0}"
......@@ -110,6 +116,14 @@ setup_vethPairs() {
if [[ $verbose -eq 1 ]]; then
echo "setting up ${VETH1}: namespace: ${NS1}"
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 netns exec ${NS1} ip link set ${VETH1} mtu ${MTU}
ip link set ${VETH0} mtu ${MTU}
......@@ -130,17 +144,12 @@ if [ $retval -ne 0 ]; then
exit $retval
fi
echo "${VETH0}:${VETH1},${NS1}" > ${SPECFILE}
validate_veth_spec_file
if [[ $verbose -eq 1 ]]; then
echo "Spec file created: ${SPECFILE}"
VERBOSE_ARG="-v"
ARGS+="-v "
fi
if [[ $dump_pkts -eq 1 ]]; then
DUMP_PKTS_ARG="-D"
ARGS="-D "
fi
test_status $retval "${TEST_NAME}"
......@@ -149,23 +158,31 @@ test_status $retval "${TEST_NAME}"
statusList=()
TEST_NAME="XSK KSELFTESTS"
TEST_NAME="XSK_SELFTESTS_SOFTIRQ"
execxdpxceiver
retval=$?
test_status $retval "${TEST_NAME}"
statusList+=($retval)
cleanup_exit ${VETH0} ${VETH1} ${NS1}
TEST_NAME="XSK_SELFTESTS_BUSY_POLL"
busy_poll=1
setup_vethPairs
execxdpxceiver
## END TESTS
cleanup_exit ${VETH0} ${VETH1} ${NS1}
for _status in "${statusList[@]}"
failures=0
echo -e "\nSummary:"
for i in "${!statusList[@]}"
do
if [ $_status -ne 0 ]; then
test_exit $ksft_fail 0
if [ ${statusList[$i]} -ne 0 ]; then
test_status ${statusList[$i]} ${nameList[$i]}
failures=1
fi
done
test_exit $ksft_pass 0
if [ $failures -eq 0 ]; then
echo "All tests successful!"
fi
This diff is collapsed.
......@@ -17,6 +17,16 @@
#define PF_XDP AF_XDP
#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_INTERFACE_NAME_CHARS 7
#define MAX_INTERFACES_NAMESPACE_CHARS 10
......@@ -25,9 +35,10 @@
#define MAX_TEARDOWN_ITER 10
#define PKT_HDR_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
sizeof(struct udphdr))
#define MIN_PKT_SIZE 64
#define MIN_ETH_PKT_SIZE 64
#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_VER 0x4
#define IP_PKT_TOS 0x9
......@@ -37,6 +48,7 @@
#define SOCK_RECONF_CTR 10
#define BATCH_SIZE 64
#define POLL_TMOUT 1000
#define RECV_TMOUT 3
#define DEFAULT_PKT_CNT (4 * 1024)
#define DEFAULT_UMEM_BUFFERS (DEFAULT_PKT_CNT / 4)
#define UMEM_SIZE (DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE)
......@@ -64,24 +76,16 @@ enum test_type {
TEST_TYPE_HEADROOM,
TEST_TYPE_TEARDOWN,
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_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 int test_type;
static bool opt_verbose;
static int stat_test_type;
struct xsk_umem_info {
struct xsk_ring_prod fq;
......@@ -117,6 +121,8 @@ struct pkt_stream {
bool use_addr_for_fill;
};
struct ifobject;
typedef int (*validation_func_t)(struct ifobject *ifobj);
typedef void *(*thread_func_t)(void *arg);
struct ifobject {
......@@ -126,6 +132,7 @@ struct ifobject {
struct xsk_socket_info *xsk_arr;
struct xsk_umem_info *umem;
thread_func_t func_ptr;
validation_func_t validation_func;
struct pkt_stream *pkt_stream;
int ns_fd;
int xsk_map_fd;
......@@ -138,7 +145,9 @@ struct ifobject {
bool tx_on;
bool rx_on;
bool use_poll;
bool pacing_on;
bool busy_poll;
bool use_fill_ring;
bool release_rx;
u8 dst_mac[ETH_ALEN];
u8 src_mac[ETH_ALEN];
};
......@@ -150,6 +159,7 @@ struct test_spec {
u16 total_steps;
u16 current_step;
u16 nb_sockets;
bool fail;
char name[MAX_TEST_NAME_SIZE];
};
......@@ -157,6 +167,6 @@ pthread_barrier_t barr;
pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t pacing_cond = PTHREAD_COND_INITIALIZER;
u32 pkts_in_flight;
int pkts_in_flight;
#endif /* XDPXCEIVER_H */
......@@ -8,7 +8,6 @@ ksft_xfail=2
ksft_xpass=3
ksft_skip=4
SPECFILE=veth.spec
XSKOBJ=xdpxceiver
validate_root_exec()
......@@ -16,7 +15,7 @@ validate_root_exec()
msg="skip all tests:"
if [ $UID != 0 ]; then
echo $msg must be run as root >&2
test_exit $ksft_fail 2
test_exit $ksft_fail
else
return $ksft_pass
fi
......@@ -27,39 +26,31 @@ validate_veth_support()
msg="skip all tests:"
if [ $(ip link add $1 type veth 2>/dev/null; echo $?;) != 0 ]; then
echo $msg veth kernel support not available >&2
test_exit $ksft_skip 1
test_exit $ksft_skip
else
ip link del $1
return $ksft_pass
fi
}
validate_veth_spec_file()
{
if [ ! -f ${SPECFILE} ]; then
test_exit $ksft_skip 1
fi
}
test_status()
{
statusval=$1
if [ $statusval -eq 2 ]; then
echo -e "$2: [ FAIL ]"
elif [ $statusval -eq 1 ]; then
echo -e "$2: [ SKIPPED ]"
elif [ $statusval -eq 0 ]; then
echo -e "$2: [ PASS ]"
if [ $statusval -eq $ksft_fail ]; then
echo "$2: [ FAIL ]"
elif [ $statusval -eq $ksft_skip ]; then
echo "$2: [ SKIPPED ]"
elif [ $statusval -eq $ksft_pass ]; then
echo "$2: [ PASS ]"
fi
}
test_exit()
{
retval=$1
if [ $2 -ne 0 ]; then
test_status $2 $(basename $0)
if [ $1 -ne 0 ]; then
test_status $1 $(basename $0)
fi
exit $retval
exit 1
}
clear_configs()
......@@ -74,9 +65,6 @@ clear_configs()
#veth node inside NS won't get removed so we explicitly remove it
[ $(ip link show $1 &>/dev/null; echo $?;) == 0 ] &&
{ ip link del $1; }
if [ -f ${SPECFILE} ]; then
rm -f ${SPECFILE}
fi
}
cleanup_exit()
......@@ -86,10 +74,19 @@ cleanup_exit()
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()
{
./${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