Commit 605091c5 authored by Magnus Karlsson's avatar Magnus Karlsson Committed by Daniel Borkmann

selftests: xsk: Introduce replacing the default packet stream

Introduce the concept of a default packet stream that is the set of
packets sent by most tests. Then add the ability to replace it for a
test that would like to send or receive something else through the use
of the function pkt_stream_replace() and then restored with
pkt_stream_restore_default(). These are then used to convert the
STAT_TEST_TX_INVALID to use these new APIs.
Signed-off-by: default avatarMagnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://lore.kernel.org/bpf/20210907071928.9750-17-magnus.karlsson@gmail.com
parent 8abf6f72
...@@ -390,6 +390,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, ...@@ -390,6 +390,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
ifobj->umem = &ifobj->umem_arr[0]; ifobj->umem = &ifobj->umem_arr[0];
ifobj->xsk = &ifobj->xsk_arr[0]; ifobj->xsk = &ifobj->xsk_arr[0];
ifobj->use_poll = false; ifobj->use_poll = false;
ifobj->pkt_stream = test->pkt_stream_default;
if (i == 0) { if (i == 0) {
ifobj->rx_on = false; ifobj->rx_on = false;
...@@ -418,9 +419,12 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, ...@@ -418,9 +419,12 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
struct ifobject *ifobj_rx, enum test_mode mode) struct ifobject *ifobj_rx, enum test_mode mode)
{ {
struct pkt_stream *pkt_stream;
u32 i; u32 i;
pkt_stream = test->pkt_stream_default;
memset(test, 0, sizeof(*test)); memset(test, 0, sizeof(*test));
test->pkt_stream_default = pkt_stream;
for (i = 0; i < MAX_INTERFACES; i++) { for (i = 0; i < MAX_INTERFACES; i++) {
struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx; struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx;
...@@ -455,6 +459,19 @@ static struct pkt *pkt_stream_get_pkt(struct pkt_stream *pkt_stream, u32 pkt_nb) ...@@ -455,6 +459,19 @@ static struct pkt *pkt_stream_get_pkt(struct pkt_stream *pkt_stream, u32 pkt_nb)
return &pkt_stream->pkts[pkt_nb]; return &pkt_stream->pkts[pkt_nb];
} }
static void pkt_stream_delete(struct pkt_stream *pkt_stream)
{
free(pkt_stream->pkts);
free(pkt_stream);
}
static void pkt_stream_restore_default(struct test_spec *test)
{
pkt_stream_delete(test->ifobj_tx->pkt_stream);
test->ifobj_tx->pkt_stream = test->pkt_stream_default;
test->ifobj_rx->pkt_stream = test->pkt_stream_default;
}
static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb_pkts, u32 pkt_len) static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb_pkts, u32 pkt_len)
{ {
struct pkt_stream *pkt_stream; struct pkt_stream *pkt_stream;
...@@ -483,6 +500,15 @@ static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb ...@@ -483,6 +500,15 @@ static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb
return pkt_stream; return pkt_stream;
} }
static void pkt_stream_replace(struct test_spec *test, u32 nb_pkts, u32 pkt_len)
{
struct pkt_stream *pkt_stream;
pkt_stream = pkt_stream_generate(test->ifobj_tx->umem, nb_pkts, pkt_len);
test->ifobj_tx->pkt_stream = pkt_stream;
test->ifobj_rx->pkt_stream = pkt_stream;
}
static struct pkt *pkt_generate(struct ifobject *ifobject, u32 pkt_nb) static struct pkt *pkt_generate(struct ifobject *ifobject, u32 pkt_nb)
{ {
struct pkt *pkt = pkt_stream_get_pkt(ifobject->pkt_stream, pkt_nb); struct pkt *pkt = pkt_stream_get_pkt(ifobject->pkt_stream, pkt_nb);
...@@ -557,7 +583,7 @@ static bool is_pkt_valid(struct pkt *pkt, void *buffer, const struct xdp_desc *d ...@@ -557,7 +583,7 @@ static bool is_pkt_valid(struct pkt *pkt, void *buffer, const struct xdp_desc *d
if (iphdr->version == IP_PKT_VER && iphdr->tos == IP_PKT_TOS) { if (iphdr->version == IP_PKT_VER && iphdr->tos == IP_PKT_TOS) {
u32 seqnum = ntohl(*((u32 *)(data + PKT_HDR_SIZE))); u32 seqnum = ntohl(*((u32 *)(data + PKT_HDR_SIZE)));
if (opt_pkt_dump && test_type != TEST_TYPE_STATS) if (opt_pkt_dump)
pkt_dump(data, PKT_SIZE); pkt_dump(data, PKT_SIZE);
if (pkt->len != desc->len) { if (pkt->len != desc->len) {
...@@ -598,9 +624,6 @@ static void complete_pkts(struct xsk_socket_info *xsk, int batch_size) ...@@ -598,9 +624,6 @@ static void complete_pkts(struct xsk_socket_info *xsk, int batch_size)
unsigned int rcvd; unsigned int rcvd;
u32 idx; u32 idx;
if (!xsk->outstanding_tx)
return;
if (xsk_ring_prod__needs_wakeup(&xsk->tx)) if (xsk_ring_prod__needs_wakeup(&xsk->tx))
kick_tx(xsk); kick_tx(xsk);
...@@ -831,6 +854,7 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject) ...@@ -831,6 +854,7 @@ static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
static void testapp_cleanup_xsk_res(struct ifobject *ifobj) static void testapp_cleanup_xsk_res(struct ifobject *ifobj)
{ {
print_verbose("Destroying socket\n");
xsk_socket__delete(ifobj->xsk->xsk); xsk_socket__delete(ifobj->xsk->xsk);
xsk_umem__delete(ifobj->umem->umem); xsk_umem__delete(ifobj->umem->umem);
} }
...@@ -878,9 +902,6 @@ static void *worker_testapp_validate_rx(void *arg) ...@@ -878,9 +902,6 @@ static void *worker_testapp_validate_rx(void *arg)
else else
receive_pkts(ifobject->pkt_stream, ifobject->xsk, &fds); receive_pkts(ifobject->pkt_stream, ifobject->xsk, &fds);
if (test_type == TEST_TYPE_TEARDOWN)
print_verbose("Destroying socket\n");
if (test->total_steps == test->current_step) if (test->total_steps == test->current_step)
testapp_cleanup_xsk_res(ifobject); testapp_cleanup_xsk_res(ifobject);
pthread_exit(NULL); pthread_exit(NULL);
...@@ -890,19 +911,11 @@ static void testapp_validate_traffic(struct test_spec *test) ...@@ -890,19 +911,11 @@ static void testapp_validate_traffic(struct test_spec *test)
{ {
struct ifobject *ifobj_tx = test->ifobj_tx; struct ifobject *ifobj_tx = test->ifobj_tx;
struct ifobject *ifobj_rx = test->ifobj_rx; struct ifobject *ifobj_rx = test->ifobj_rx;
struct pkt_stream *pkt_stream;
pthread_t t0, t1; pthread_t t0, t1;
if (pthread_barrier_init(&barr, NULL, 2)) if (pthread_barrier_init(&barr, NULL, 2))
exit_with_error(errno); exit_with_error(errno);
if (stat_test_type == STAT_TEST_TX_INVALID)
pkt_stream = pkt_stream_generate(test->ifobj_tx->umem, DEFAULT_PKT_CNT,
XSK_UMEM__INVALID_FRAME_SIZE);
else
pkt_stream = pkt_stream_generate(test->ifobj_tx->umem, DEFAULT_PKT_CNT, PKT_SIZE);
ifobj_tx->pkt_stream = pkt_stream;
ifobj_rx->pkt_stream = pkt_stream;
test->current_step++; test->current_step++;
/*Spawn RX thread */ /*Spawn RX thread */
...@@ -982,7 +995,9 @@ static void testapp_bpf_res(struct test_spec *test) ...@@ -982,7 +995,9 @@ static void testapp_bpf_res(struct test_spec *test)
static void testapp_stats(struct test_spec *test) static void testapp_stats(struct test_spec *test)
{ {
for (int i = 0; i < STAT_TEST_TYPE_MAX; i++) { int i;
for (i = 0; i < STAT_TEST_TYPE_MAX; i++) {
test_spec_reset(test); test_spec_reset(test);
stat_test_type = i; stat_test_type = i;
...@@ -991,21 +1006,27 @@ static void testapp_stats(struct test_spec *test) ...@@ -991,21 +1006,27 @@ static void testapp_stats(struct test_spec *test)
test_spec_set_name(test, "STAT_RX_DROPPED"); test_spec_set_name(test, "STAT_RX_DROPPED");
test->ifobj_rx->umem->frame_headroom = test->ifobj_rx->umem->frame_size - test->ifobj_rx->umem->frame_headroom = test->ifobj_rx->umem->frame_size -
XDP_PACKET_HEADROOM - 1; XDP_PACKET_HEADROOM - 1;
testapp_validate_traffic(test);
break; break;
case STAT_TEST_RX_FULL: case STAT_TEST_RX_FULL:
test_spec_set_name(test, "STAT_RX_FULL"); test_spec_set_name(test, "STAT_RX_FULL");
test->ifobj_rx->xsk->rxqsize = RX_FULL_RXQSIZE; test->ifobj_rx->xsk->rxqsize = RX_FULL_RXQSIZE;
testapp_validate_traffic(test);
break; break;
case STAT_TEST_TX_INVALID: case STAT_TEST_TX_INVALID:
test_spec_set_name(test, "STAT_TX_INVALID"); test_spec_set_name(test, "STAT_TX_INVALID");
continue; pkt_stream_replace(test, DEFAULT_PKT_CNT, XSK_UMEM__INVALID_FRAME_SIZE);
testapp_validate_traffic(test);
pkt_stream_restore_default(test);
break;
case STAT_TEST_RX_FILL_EMPTY: case STAT_TEST_RX_FILL_EMPTY:
test_spec_set_name(test, "STAT_RX_FILL_EMPTY"); test_spec_set_name(test, "STAT_RX_FILL_EMPTY");
testapp_validate_traffic(test);
break; break;
default: default:
break; break;
} }
testapp_validate_traffic(test);
} }
/* To only see the whole stat set being completed unless an individual test fails. */ /* To only see the whole stat set being completed unless an individual test fails. */
...@@ -1105,6 +1126,7 @@ static void ifobject_delete(struct ifobject *ifobj) ...@@ -1105,6 +1126,7 @@ static void ifobject_delete(struct ifobject *ifobj)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct rlimit _rlim = { RLIM_INFINITY, RLIM_INFINITY }; struct rlimit _rlim = { RLIM_INFINITY, RLIM_INFINITY };
struct pkt_stream *pkt_stream_default;
struct ifobject *ifobj_tx, *ifobj_rx; struct ifobject *ifobj_tx, *ifobj_rx;
struct test_spec test; struct test_spec test;
u32 i, j; u32 i, j;
...@@ -1133,6 +1155,12 @@ int main(int argc, char **argv) ...@@ -1133,6 +1155,12 @@ int main(int argc, char **argv)
init_iface(ifobj_rx, MAC2, MAC1, IP2, IP1, UDP_PORT2, UDP_PORT1, init_iface(ifobj_rx, MAC2, MAC1, IP2, IP1, UDP_PORT2, UDP_PORT1,
worker_testapp_validate_rx); worker_testapp_validate_rx);
test_spec_init(&test, ifobj_tx, ifobj_rx, 0);
pkt_stream_default = pkt_stream_generate(ifobj_tx->umem, DEFAULT_PKT_CNT, PKT_SIZE);
if (!pkt_stream_default)
exit_with_error(ENOMEM);
test.pkt_stream_default = pkt_stream_default;
ksft_set_plan(TEST_MODE_MAX * TEST_TYPE_MAX); ksft_set_plan(TEST_MODE_MAX * TEST_TYPE_MAX);
for (i = 0; i < TEST_MODE_MAX; i++) for (i = 0; i < TEST_MODE_MAX; i++)
...@@ -1142,6 +1170,7 @@ int main(int argc, char **argv) ...@@ -1142,6 +1170,7 @@ int main(int argc, char **argv)
usleep(USLEEP_MAX); usleep(USLEEP_MAX);
} }
pkt_stream_delete(pkt_stream_default);
ifobject_delete(ifobj_tx); ifobject_delete(ifobj_tx);
ifobject_delete(ifobj_rx); ifobject_delete(ifobj_rx);
......
...@@ -132,6 +132,7 @@ struct ifobject { ...@@ -132,6 +132,7 @@ struct ifobject {
struct test_spec { struct test_spec {
struct ifobject *ifobj_tx; struct ifobject *ifobj_tx;
struct ifobject *ifobj_rx; struct ifobject *ifobj_rx;
struct pkt_stream *pkt_stream_default;
u16 total_steps; u16 total_steps;
u16 current_step; u16 current_step;
u16 nb_sockets; u16 nb_sockets;
......
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