Skip to content

Commit

Permalink
selftests/bpf: Add mptcpify test
Browse files Browse the repository at this point in the history
Implement a new test program mptcpify: if the family is AF_INET or
AF_INET6, the type is SOCK_STREAM, and the protocol ID is 0 or
IPPROTO_TCP, set it to IPPROTO_MPTCP. It will be hooked in
update_socket_protocol().

Extend the MPTCP test base, add a selftest test_mptcpify() for the
mptcpify case. Open and load the mptcpify test prog to mptcpify the
TCP sockets dynamically, then use start_server() and connect_to_fd()
to create a TCP socket, but actually what's created is an MPTCP
socket, which can be verified through 'getsockopt(SOL_PROTOCOL)'
and 'nstat' commands.

Acked-by: Yonghong Song <[email protected]>
Reviewed-by: Matthieu Baerts <[email protected]>
Signed-off-by: Geliang Tang <[email protected]>
  • Loading branch information
geliangtang authored and intel-lab-lkp committed Aug 7, 2023
1 parent d490b53 commit 04b42ba
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
102 changes: 102 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/mptcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
/* Copyright (c) 2020, Tessares SA. */
/* Copyright (c) 2022, SUSE. */

#include <netinet/in.h>
#include <test_progs.h>
#include "cgroup_helpers.h"
#include "network_helpers.h"
#include "mptcp_sock.skel.h"
#include "mptcpify.skel.h"

char NS_TEST[32];

#ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262
#endif

#ifndef TCP_CA_NAME_MAX
#define TCP_CA_NAME_MAX 16
#endif
Expand Down Expand Up @@ -186,8 +192,104 @@ static void test_base(void)
close(cgroup_fd);
}

static void send_byte(int fd)
{
char b = 0x55;

ASSERT_EQ(write(fd, &b, sizeof(b)), 1, "send single byte");
}

static int verify_mptcpify(int server_fd)
{
socklen_t optlen;
char cmd[256];
int protocol;
int err = 0;

optlen = sizeof(protocol);
if (!ASSERT_OK(getsockopt(server_fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen),
"getsockopt(SOL_PROTOCOL)"))
return -1;

if (!ASSERT_EQ(protocol, IPPROTO_MPTCP, "protocol isn't MPTCP"))
err++;

/* Output of nstat:
*
* #kernel
* MPTcpExtMPCapableSYNACKRX 1 0.0
*/
snprintf(cmd, sizeof(cmd),
"ip netns exec %s nstat -asz %s | awk '%s' | grep -q '%s'",
NS_TEST, "MPTcpExtMPCapableSYNACKRX",
"NR==1 {next} {print $2}", "1");
if (!ASSERT_OK(system(cmd), "No MPTcpExtMPCapableSYNACKRX found!"))
err++;

return err;
}

static int run_mptcpify(int cgroup_fd)
{
int server_fd, client_fd, err = 0;
struct mptcpify *mptcpify_skel;

mptcpify_skel = mptcpify__open_and_load();
if (!ASSERT_OK_PTR(mptcpify_skel, "skel_open_load"))
return libbpf_get_error(mptcpify_skel);

err = mptcpify__attach(mptcpify_skel);
if (!ASSERT_OK(err, "skel_attach"))
goto out;

/* without MPTCP */
server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0);
if (!ASSERT_GE(server_fd, 0, "start_server")) {
err = -EIO;
goto out;
}

client_fd = connect_to_fd(server_fd, 0);
if (!ASSERT_GE(client_fd, 0, "connect to fd")) {
err = -EIO;
goto close_server;
}

send_byte(client_fd);
err = verify_mptcpify(server_fd);

close(client_fd);
close_server:
close(server_fd);
out:
mptcpify__destroy(mptcpify_skel);
return err;
}

static void test_mptcpify(void)
{
struct nstoken *nstoken = NULL;
int cgroup_fd;

cgroup_fd = test__join_cgroup("/mptcpify");
if (!ASSERT_GE(cgroup_fd, 0, "test__join_cgroup"))
return;

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

ASSERT_OK(run_mptcpify(cgroup_fd), "run_mptcpify");

fail:
cleanup_netns(nstoken);
close(cgroup_fd);
}

void test_mptcp(void)
{
if (test__start_subtest("base"))
test_base();
if (test__start_subtest("mptcpify"))
test_mptcpify();
}
20 changes: 20 additions & 0 deletions tools/testing/selftests/bpf/progs/mptcpify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023, SUSE. */

#include "vmlinux.h"
#include <bpf/bpf_tracing.h>
#include "bpf_tracing_net.h"

char _license[] SEC("license") = "GPL";

SEC("fmod_ret/update_socket_protocol")
int BPF_PROG(mptcpify, int family, int type, int protocol)
{
if ((family == AF_INET || family == AF_INET6) &&
type == SOCK_STREAM &&
(!protocol || protocol == IPPROTO_TCP)) {
return IPPROTO_MPTCP;
}

return protocol;
}

0 comments on commit 04b42ba

Please sign in to comment.