@@ -13780,6 +13780,7 @@ F: include/net/mptcp.h
F: include/trace/events/mptcp.h
F: include/uapi/linux/mptcp.h
F: net/mptcp/
+F: tools/testing/selftests/bpf/bpf_mptcp_helpers.h
F: tools/testing/selftests/bpf/*/*mptcp*.c
F: tools/testing/selftests/net/mptcp/
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2022, SUSE. */
+
+#ifndef __BPF_MPTCP_HELPERS_H
+#define __BPF_MPTCP_HELPERS_H
+
+#include "bpf_tcp_helpers.h"
+
+struct mptcp_sock {
+ struct inet_connection_sock sk;
+
+} __attribute__((preserve_access_index));
+
+#endif
@@ -10,14 +10,12 @@ struct mptcp_storage {
__u32 is_mptcp;
};
-static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 is_mptcp)
+static int verify_tsk(int map_fd, int client_fd)
{
+ char *msg = "plain TCP socket";
int err = 0, cfd = client_fd;
struct mptcp_storage val;
- if (is_mptcp == 1)
- return 0;
-
if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &cfd, &val) < 0)) {
perror("Failed to read socket storage");
return -1;
@@ -38,6 +36,32 @@ static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 is_mptcp)
return err;
}
+static int verify_msk(int map_fd, int client_fd)
+{
+ char *msg = "MPTCP subflow socket";
+ int err = 0, cfd = client_fd;
+ struct mptcp_storage val;
+
+ if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &cfd, &val) < 0)) {
+ perror("Failed to read socket storage");
+ return -1;
+ }
+
+ if (val.invoked != 1) {
+ log_err("%s: unexpected invoked count %d != 1",
+ msg, val.invoked);
+ err++;
+ }
+
+ if (val.is_mptcp != 1) {
+ log_err("%s: unexpected bpf_tcp_sock.is_mptcp %d != 1",
+ msg, val.is_mptcp);
+ err++;
+ }
+
+ return err;
+}
+
static int run_test(int cgroup_fd, int server_fd, bool is_mptcp)
{
int client_fd, prog_fd, map_fd, err;
@@ -88,8 +112,8 @@ static int run_test(int cgroup_fd, int server_fd, bool is_mptcp)
goto out;
}
- err += is_mptcp ? verify_sk(map_fd, client_fd, "MPTCP subflow socket", 1) :
- verify_sk(map_fd, client_fd, "plain TCP socket", 0);
+ err += is_mptcp ? verify_msk(map_fd, client_fd) :
+ verify_tsk(map_fd, client_fd);
close(client_fd);
@@ -3,9 +3,11 @@
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
+#include "bpf_mptcp_helpers.h"
char _license[] SEC("license") = "GPL";
__u32 _version SEC("version") = 1;
+extern bool CONFIG_MPTCP __kconfig;
struct mptcp_storage {
__u32 invoked;
@@ -24,6 +26,7 @@ int _sockops(struct bpf_sock_ops *ctx)
{
struct mptcp_storage *storage;
struct bpf_tcp_sock *tcp_sk;
+ struct mptcp_sock *msk;
int op = (int)ctx->op;
struct bpf_sock *sk;
@@ -38,11 +41,24 @@ int _sockops(struct bpf_sock_ops *ctx)
if (!tcp_sk)
return 1;
- storage = bpf_sk_storage_get(&socket_storage_map, sk, 0,
- BPF_SK_STORAGE_GET_F_CREATE);
- if (!storage)
- return 1;
+ if (!tcp_sk->is_mptcp) {
+ storage = bpf_sk_storage_get(&socket_storage_map, sk, 0,
+ BPF_SK_STORAGE_GET_F_CREATE);
+ if (!storage)
+ return 1;
+ } else {
+ if (!CONFIG_MPTCP)
+ return 1;
+
+ msk = bpf_skc_to_mptcp_sock(sk);
+ if (!msk)
+ return 1;
+ storage = bpf_sk_storage_get(&socket_storage_map, msk, 0,
+ BPF_SK_STORAGE_GET_F_CREATE);
+ if (!storage)
+ return 1;
+ }
storage->invoked++;
storage->is_mptcp = tcp_sk->is_mptcp;