@@ -83,6 +83,7 @@ done
TEST_NAME="PREREQUISITES"
DEFAULTPKTS=10000
+TRACEPKTS=64
URANDOM=/dev/urandom
[ ! -e "${URANDOM}" ] && { echo "${URANDOM} not found. Skipping tests."; test_exit 1 1; }
@@ -246,6 +247,30 @@ retval=$?
test_status $retval "${TEST_NAME}"
statusList+=($retval)
+### TEST 10
+TEST_NAME="SKB TRACE DROP PKT_TOO_BIG"
+
+vethXDPgeneric ${VETH0} ${VETH1} ${NS1}
+
+params=("-S" "-t" "0" "-C" "${TRACEPKTS}")
+execxdpxceiver params
+
+retval=$?
+test_status $retval "${TEST_NAME}"
+statusList+=($retval)
+
+### TEST 11
+TEST_NAME="DRV TRACE DROP PKT_TOO_BIG"
+
+vethXDPnative ${VETH0} ${VETH1} ${NS1}
+
+params=("-N" "-t" "0" "-C" "${TRACEPKTS}")
+execxdpxceiver params
+
+retval=$?
+test_status $retval "${TEST_NAME}"
+statusList+=($retval)
+
## END TESTS
cleanup_exit ${VETH0} ${VETH1} ${NS1}
@@ -33,6 +33,8 @@
* 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. Tracing - XSK_TRACE_DROP_PKT_TOO_BIG
+ * Increase the headroom size and send packets. Validate traces.
*
* 2. AF_XDP DRV/Native mode
* Works on any netdevice with XDP_REDIRECT support, driver dependent. Processes
@@ -44,8 +46,9 @@
* d. Bi-directional sockets
* - Only copy mode is supported because veth does not currently support
* zero-copy mode
+ * e. Tracing - XSK_TRACE_DROP_PKT_TOO_BIG
*
- * Total tests: 8
+ * Total tests: 10
*
* Flow:
* -----
@@ -272,13 +275,23 @@ 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 = XSK_UMEM__DEFAULT_FRAME_HEADROOM,
+ .flags = XSK_UMEM__DEFAULT_FLAGS
+ };
+
+ if (opt_trace_code == XSK_TRACE_DROP_PKT_TOO_BIG)
+ cfg.frame_headroom = XSK_UMEM__DEFAULT_FRAME_SIZE - XDP_PACKET_HEADROOM - 1;
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);
@@ -363,7 +376,7 @@ static void usage(const char *prog)
" -B, --bidi Bi-directional sockets test\n"
" -D, --debug Debug mode - dump packets L2 - L5\n"
" -C, --tx-pkt-count=n Number of packets to send\n"
- " -t, --trace-enable Enable trace\n";
+ " -t, --trace-enable=n Enable trace and execute test 'n'\n";
ksft_print_msg(str, prog);
}
@@ -450,7 +463,7 @@ static void parse_command_line(int argc, char **argv)
opterr = 0;
for (;;) {
- c = getopt_long(argc, argv, "i:q:pSNcTBDC:t", long_options, &option_index);
+ c = getopt_long(argc, argv, "i:q:pSNcTBDC:t:", long_options, &option_index);
if (c == -1)
break;
@@ -503,6 +516,7 @@ static void parse_command_line(int argc, char **argv)
break;
case 't':
opt_trace_enable = 1;
+ opt_trace_code = atoi(optarg);
break;
default:
usage(basename(argv[0]));
@@ -730,6 +744,28 @@ static void worker_pkt_dump(void)
}
}
+static void worker_trace_validate(FILE *fp, char *ifname)
+{
+ char trace_str[128];
+ char *line = NULL;
+ size_t len = 0;
+ int ret = 0;
+
+ snprintf(trace_str, sizeof(trace_str), "netdev: %s qid 0 reason: %s",
+ ifname, reason_str);
+
+ while (trace_counter != expected_traces) {
+ while ((ret = getline(&line, &len, fp)) == EOF)
+ continue;
+ if (strstr(line, trace_str) != NULL)
+ trace_counter++;
+ }
+
+ sigvar = 1;
+
+ fclose(fp);
+}
+
static void worker_pkt_validate(void)
{
u32 payloadseqnum = -2;
@@ -851,6 +887,25 @@ static int enable_disable_trace(bool enable)
return ret;
}
+static FILE *get_eof_trace(void)
+{
+ FILE *ret_fp;
+ char *line = NULL;
+ size_t len = 0;
+ int ret = 0;
+
+ ret_fp = fopen(TRACE_FILE, "r");
+ if (ret_fp == NULL) {
+ ksft_print_msg("Error opening %s\n", TRACE_FILE);
+ return NULL;
+ }
+
+ /* Go to end of file and record the file pointer */
+ while ((ret = getline(&line, &len, ret_fp)) != EOF)
+ ;
+
+ return ret_fp;
+}
static void *worker_testapp_validate(void *arg)
{
@@ -900,12 +955,22 @@ static void *worker_testapp_validate(void *arg)
}
ksft_print_msg("Sending %d packets on interface %s\n",
- (opt_pkt_count - 1), ifobject->ifname);
+ (opt_trace_enable ? opt_pkt_count : opt_pkt_count - 1),
+ ifobject->ifname);
tx_only_all(ifobject);
} else if (ifobject->fv.vector == rx) {
struct pollfd fds[MAX_SOCKS] = { };
+ FILE *tr_fp = NULL;
int ret;
+ if (opt_trace_enable) {
+ tr_fp = get_eof_trace();
+ if (tr_fp == NULL) {
+ ksft_print_msg("Error getting EOF of trace\n");
+ exit_with_error(-1);
+ }
+ }
+
if (!bidi_pass)
thread_common_ops(ifobject, bufs, &sync_mutex_tx, &spinning_rx);
@@ -932,15 +997,22 @@ static void *worker_testapp_validate(void *arg)
if (ret <= 0)
continue;
}
- rx_pkt(ifobject->xsk, fds);
- worker_pkt_validate();
+
+ if (!opt_trace_enable) {
+ rx_pkt(ifobject->xsk, fds);
+ worker_pkt_validate();
+ } else {
+ worker_trace_validate(tr_fp, ifobject->ifname);
+ }
if (sigvar)
break;
}
- ksft_print_msg("Received %d packets on interface %s\n",
- pkt_counter, ifobject->ifname);
+ ksft_print_msg("%s %d packets on interface %s\n",
+ opt_trace_enable ? "Traced" : "Received",
+ opt_trace_enable ? trace_counter : pkt_counter,
+ ifobject->ifname);
if (opt_teardown)
ksft_print_msg("Destroying socket\n");
@@ -1086,15 +1158,25 @@ int main(int argc, char **argv)
parse_command_line(argc, argv);
- num_frames = ++opt_pkt_count;
+ num_frames = opt_trace_enable ? opt_pkt_count : ++opt_pkt_count;
init_iface_config(ifaceconfig);
if (opt_trace_enable) {
+ expected_traces = opt_pkt_count;
if (enable_disable_trace(1)) {
ksft_test_result_fail("ERROR: failed to enable tracing for trace test\n");
ksft_exit_xfail();
}
+ switch (opt_trace_code) {
+ case XSK_TRACE_DROP_PKT_TOO_BIG:
+ reason_str = "packet too big";
+ break;
+ default:
+ ksft_test_result_fail("ERROR: unsupported trace %i\n",
+ opt_trace_code);
+ ksft_exit_xfail();
+ }
}
pthread_init_mutex();
@@ -42,6 +42,8 @@
#define POLL_TMOUT 1000
#define NEED_WAKEUP true
#define TRACE_ENABLE_FILE "/sys/kernel/debug/tracing/events/xsk/xsk_packet_drop/enable"
+#define TRACE_FILE "/sys/kernel/debug/tracing/trace"
+#define TRACE_MAX_PKTS 100 /* limit size to avoid filling trace buffer */
typedef __u32 u32;
typedef __u16 u16;
@@ -66,11 +68,15 @@ static int opt_teardown;
static int opt_bidi;
static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
static int opt_trace_enable;
+static int opt_trace_code = -1;
static int reset_trace;
static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE];
static u32 pkt_counter;
+static u32 trace_counter;
static u32 prev_pkt = -1;
static int sigvar;
+static int expected_traces;
+static const char *reason_str;
struct xsk_umem_info {
struct xsk_ring_prod fq;
This test increases the UMEM headroom to a size that will cause packets to be dropped. Traces which report these drops are expected which look like so: xsk_packet_drop: netdev: ve3213 qid 0 reason: packet too big: \ len 60 max 1 not_used 0 The test validates that these traces were successfully generated. Signed-off-by: Ciara Loftus <ciara.loftus@intel.com> --- tools/testing/selftests/bpf/test_xsk.sh | 25 ++++++ tools/testing/selftests/bpf/xdpxceiver.c | 102 ++++++++++++++++++++--- tools/testing/selftests/bpf/xdpxceiver.h | 6 ++ 3 files changed, 123 insertions(+), 10 deletions(-)