Skip to content

Commit

Permalink
Squash to "selftests/bpf: Add bpf_first test"
Browse files Browse the repository at this point in the history
'''
This patch extends the MPTCP test base to support MPTCP packet scheduler
tests. Add a new test to use the default in-kernel scheduler.

In the new helper sched_init(), invoke create_netns() to create a net
namespace, and invoke endpoint_init() to add two veth net devices to
simulate the multiple addresses case and add the new endpoint ADDR_2 to
PM netlink. Use sysctl to set net.mptcp.scheduler to use the given sched.

Invoke start_mptcp_server() to start the server on ADDR_1, and invoke
connect_to_fd() to connect with the server from the client. Then invoke
send_data() to send data.

Some code in send_data() is from prog_tests/bpf_tcp_ca.c.

Add time metrics for BPF tests to compare the performance of each
schedulers. Run prog_tests with '-v' option can print out the running
time of each test.

Use the new helper has_bytes_sent() to check the bytes_sent filed of 'ss'
output after send_data() to make sure no data has been sent on ADDR_2.
All data has been sent on the first subflow.

Invoke the new helper sched_cleanup() to set back net.mptcp.scheduler to
default, flush all mptcp endpoints, and delete the veth net devices.

Then this patch adds the bpf_first scheduler test: test_first(). Use sysctl
to set net.mptcp.scheduler to use this sched. Add two veth net devices to
simulate the multiple addresses case. Use 'ip mptcp endpoint' command to
add the new endpoint ADDR_2 to PM netlink. Send data and check bytes_sent
of 'ss' output after it to make sure the data has been only sent on the
first subflow ADDR_1.
'''

Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
  • Loading branch information
Geliang Tang committed Mar 22, 2024
1 parent 8aad33c commit ce98d0f
Showing 1 changed file with 120 additions and 0 deletions.
120 changes: 120 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/mptcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/const.h>
#include <netinet/in.h>
#include <test_progs.h>
#include <time.h>
#include "cgroup_helpers.h"
#include "network_helpers.h"
#include "mptcp_sock.skel.h"
Expand Down Expand Up @@ -415,6 +416,125 @@ void test_subflow(void)
close(cgroup_fd);
}

static const unsigned int total_bytes = 10 * 1024 * 1024;
static int stop;

static void *server(void *arg)
{
int lfd = (int)(long)arg, err = 0, fd;
ssize_t nr_sent = 0, bytes = 0;
char batch[1500];

fd = accept(lfd, NULL, NULL);
while (fd == -1) {
if (errno == EINTR)
continue;
err = -errno;
goto done;
}

if (settimeo(fd, 0)) {
err = -errno;
goto done;
}

while (bytes < total_bytes && !READ_ONCE(stop)) {
nr_sent = send(fd, &batch,
MIN(total_bytes - bytes, sizeof(batch)), 0);
if (nr_sent == -1 && errno == EINTR)
continue;
if (nr_sent == -1) {
err = -errno;
break;
}
bytes += nr_sent;
}

ASSERT_EQ(bytes, total_bytes, "send");

done:
if (fd >= 0)
close(fd);
if (err) {
WRITE_ONCE(stop, 1);
return ERR_PTR(err);
}
return NULL;
}

static void send_data(int lfd, int fd, char *msg)
{
ssize_t nr_recv = 0, bytes = 0;
struct timespec start, end;
unsigned int delta_ms;
pthread_t srv_thread;
void *thread_ret;
char batch[1500];
int err;

WRITE_ONCE(stop, 0);

if (clock_gettime(CLOCK_MONOTONIC, &start) < 0)
return;

err = pthread_create(&srv_thread, NULL, server, (void *)(long)lfd);
if (!ASSERT_OK(err, "pthread_create"))
return;

/* recv total_bytes */
while (bytes < total_bytes && !READ_ONCE(stop)) {
nr_recv = recv(fd, &batch,
MIN(total_bytes - bytes, sizeof(batch)), 0);
if (nr_recv == -1 && errno == EINTR)
continue;
if (nr_recv == -1)
break;
bytes += nr_recv;
}

if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
return;

delta_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000;

ASSERT_EQ(bytes, total_bytes, "recv");

printf("%s: %u ms\n", msg, delta_ms);

WRITE_ONCE(stop, 1);

pthread_join(srv_thread, &thread_ret);
ASSERT_OK(IS_ERR(thread_ret), "thread_ret");
}

static struct nstoken *sched_init(char *flags, char *sched)
{
struct nstoken *nstoken;

nstoken = create_netns();
if (!ASSERT_OK_PTR(nstoken, "create_netns"))
goto fail;

if (!ASSERT_OK(endpoint_init("subflow"), "endpoint_init"))
goto fail;

SYS(fail, "ip netns exec %s sysctl -qw net.mptcp.scheduler=%s", NS_TEST, sched);

return nstoken;
fail:
return NULL;
}

static int has_bytes_sent(char *dst)
{
char cmd[128];

snprintf(cmd, sizeof(cmd),
"ip netns exec %s ss -it src %s sport %d dst %s | %s",
NS_TEST, ADDR_1, PORT_1, dst, "grep -q bytes_sent:");
return system(cmd);
}

static void test_first(void)
{
struct mptcp_bpf_first *first_skel;
Expand Down

0 comments on commit ce98d0f

Please sign in to comment.