1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
Implement address_announced/address_removed/subflow_established/
4
subflow_closed interfaces.
5
3
Depends on:
6
Depends on:
7
- BPF path manager, part 4, v5
8
Based-on: <cover.1740019794.git.tanggeliang@kylinos.cn>
4
9
5
- BPF path manager, part 4, v4
10
Geliang Tang (9):
6
Based-on: <cover.1738919954.git.tanggeliang@kylinos.cn>
11
mptcp: pm: in-kernel: add address_removed/subflow_closed
12
mptcp: pm: in-kernel: address_announced interface
13
mptcp: pm: in-kernel: address_removed interface
14
mptcp: pm: in-kernel: subflow_established interface
15
mptcp: pm: in-kernel: subflow_closed interface
16
mptcp: pm: userspace: address_announced interface
17
mptcp: pm: userspace: address_removed interface
18
mptcp: pm: userspace: subflow_established interface
19
mptcp: pm: userspace: subflow_closed interface
7
20
8
- add mptcp_address bpf_iter, v5
21
net/mptcp/pm_netlink.c | 115 ++++++++++++++------
9
Based-on: <cover.1738924354.git.tanggeliang@kylinos.cn>
22
net/mptcp/pm_userspace.c | 220 +++++++++++++++++++++++----------------
10
23
2 files changed, 215 insertions(+), 120 deletions(-)
11
Geliang Tang (5):
12
bpf: Add mptcp path manager struct_ops
13
bpf: Register mptcp struct_ops kfunc set
14
selftests/bpf: Add mptcp userspace pm subtest
15
selftests/bpf: Implement mptcp pm helpers in BPF
16
selftests/bpf: Add mptcp bpf path manager subtest
17
18
net/mptcp/bpf.c | 372 +++++++++++++++++-
19
.../testing/selftests/bpf/prog_tests/mptcp.c | 211 ++++++++++
20
tools/testing/selftests/bpf/progs/mptcp_bpf.h | 185 +++++++++
21
.../bpf/progs/mptcp_bpf_userspace_pm.c | 275 +++++++++++++
22
4 files changed, 1042 insertions(+), 1 deletion(-)
23
create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c
24
24
25
--
25
--
26
2.43.0
26
2.43.0
diff view generated by jsdifflib
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
To verify that the behavior of BPF path manager is the same as that of
3
This patch defines the code in the loop of traversing all msks in
4
userspace pm in the kernel, a userspace pm self-test has been added.
4
mptcp_nl_remove_subflow_and_signal_addr() as two new helpers,
5
BPF path manager in the next commit will also use this test.
5
mptcp_pm_nl_address_removed() and mptcp_pm_nl_subflow_closed(),
6
used for signaling a RM_ADDR and closing a subflow respectively.
6
7
7
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
8
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
8
---
9
---
9
.../testing/selftests/bpf/prog_tests/mptcp.c | 160 ++++++++++++++++++
10
net/mptcp/pm_netlink.c | 60 +++++++++++++++++++++++++++---------------
10
1 file changed, 160 insertions(+)
11
1 file changed, 39 insertions(+), 21 deletions(-)
11
12
12
diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c
13
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/tools/testing/selftests/bpf/prog_tests/mptcp.c
15
--- a/net/mptcp/pm_netlink.c
15
+++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c
16
+++ b/net/mptcp/pm_netlink.c
16
@@ -XXX,XX +XXX,XX @@ enum mptcp_pm_type {
17
@@ -XXX,XX +XXX,XX @@ static void __mark_subflow_endp_available(struct mptcp_sock *msk, u8 id)
17
    __MPTCP_PM_TYPE_MAX = __MPTCP_PM_TYPE_NR - 1,
18
        msk->pm.local_addr_used--;
18
};
19
}
19
20
20
+enum mptcp_pm_family {
21
+static int mptcp_pm_nl_address_removed(struct mptcp_sock *msk,
21
+    IPV4 = 0,
22
+                 const struct mptcp_pm_addr_entry *local)
22
+    IPV4MAPPED,
23
+{
23
+    IPV6,
24
+    bool remove_subflow;
24
+};
25
+
25
+
26
static const unsigned int total_bytes = 10 * 1024 * 1024;
26
+    remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, &local->addr);
27
static int duration;
27
+    mptcp_pm_remove_anno_addr(msk, &local->addr, remove_subflow &&
28
28
+                 !(local->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
29
@@ -XXX,XX +XXX,XX @@ static void test_iters_address(void)
29
+    return 0;
30
    close(cgroup_fd);
31
}
32
33
+static int userspace_pm_add_addr(__u32 token, char *addr, __u8 id)
34
+{
35
+    return SYS_NOFAIL("ip netns exec %s %s ann %s id %u token %u",
36
+             NS_TEST, PM_CTL, addr, id, token);
37
+}
30
+}
38
+
31
+
39
+static int userspace_pm_rm_addr(__u32 token, __u8 id)
32
+static int mptcp_pm_nl_subflow_closed(struct mptcp_sock *msk,
33
+                 const struct mptcp_pm_addr_entry *local)
40
+{
34
+{
41
+    return SYS_NOFAIL("ip netns exec %s %s rem id %u token %u",
35
+    struct mptcp_rm_list list = { .nr = 1 };
42
+             NS_TEST, PM_CTL, id, token);
36
+    bool remove_subflow;
37
+
38
+    list.ids[0] = mptcp_endp_get_local_id(msk, &local->addr);
39
+    remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, &local->addr);
40
+    if (remove_subflow) {
41
+        spin_lock_bh(&msk->pm.lock);
42
+        mptcp_pm_nl_rm_subflow_received(msk, &list);
43
+        spin_unlock_bh(&msk->pm.lock);
44
+    }
45
+
46
+    if (local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
47
+        spin_lock_bh(&msk->pm.lock);
48
+        __mark_subflow_endp_available(msk, list.ids[0]);
49
+        spin_unlock_bh(&msk->pm.lock);
50
+    }
51
+
52
+    if (msk->mpc_endpoint_id == local->addr.id)
53
+        msk->mpc_endpoint_id = 0;
54
+
55
+    return 0;
43
+}
56
+}
44
+
57
+
45
+static int userspace_pm_rm_subflow(__u32 token, char *addr, __u8 id)
58
static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
46
+{
59
                         const struct mptcp_pm_addr_entry *entry)
47
+    bool ipv6 = strstr(addr, ":");
48
+    char line[1024], *str;
49
+    __u32 sport, dport;
50
+
51
+    if (userspace_pm_get_events_line("type:10", line))
52
+        return -1;
53
+
54
+    str = strstr(line, "sport");
55
+    if (!str || sscanf(str, "sport:%u,dport:%u,", &sport, &dport) != 2) {
56
+        log_err("rm_subflow error, str=%s\n", str);
57
+        return -1;
58
+    }
59
+
60
+    str = ipv6 ? (strstr(addr, ".") ? "::ffff:"ADDR_1 : ADDR6_1) : ADDR_1;
61
+    return SYS_NOFAIL("ip netns exec %s %s dsf lip %s lport %u rip %s rport %u token %u",
62
+             NS_TEST, PM_CTL, addr, sport, str, dport, token);
63
+}
64
+
65
+static int userspace_pm_set_flags(__u32 token, char *addr, char *flags)
66
+{
67
+    bool ipv6 = strstr(addr, ":");
68
+    char line[1024], *str;
69
+    __u32 sport, dport;
70
+
71
+    if (userspace_pm_get_events_line("type:10", line))
72
+        return -1;
73
+
74
+    str = strstr(line, "sport");
75
+    if (!str || sscanf(str, "sport:%u,dport:%u,", &sport, &dport) != 2) {
76
+        log_err("set_flags error, str=%s\n", str);
77
+        return -1;
78
+    }
79
+
80
+    str = ipv6 ? (strstr(addr, ".") ? "::ffff:"ADDR_1 : ADDR6_1) : ADDR_1;
81
+    return SYS_NOFAIL("ip netns exec %s %s set %s port %u rip %s rport %u flags %s token %u",
82
+             NS_TEST, PM_CTL, addr, sport, str, dport, flags, token);
83
+}
84
+
85
+static void run_userspace_pm(enum mptcp_pm_family family)
86
+{
87
+    bool ipv4mapped = (family == IPV4MAPPED);
88
+    bool ipv6 = (family == IPV6 || ipv4mapped);
89
+    int server_fd, client_fd, accept_fd;
90
+    __u32 token;
91
+    char *addr;
92
+    int err;
93
+
94
+    addr = ipv6 ? (ipv4mapped ? "::ffff:"ADDR_1 : ADDR6_1) : ADDR_1;
95
+    server_fd = start_mptcp_server(ipv6 ? AF_INET6 : AF_INET, addr, PORT_1, 0);
96
+    if (!ASSERT_OK_FD(server_fd, "start_mptcp_server"))
97
+        return;
98
+
99
+    client_fd = connect_to_fd(server_fd, 0);
100
+    if (!ASSERT_OK_FD(client_fd, "connect_to_fd"))
101
+        goto close_server;
102
+
103
+    accept_fd = accept(server_fd, NULL, NULL);
104
+    if (!ASSERT_OK_FD(accept_fd, "accept"))
105
+        goto close_client;
106
+
107
+    token = userspace_pm_get_token(client_fd);
108
+    if (!token)
109
+        goto close_client;
110
+    recv_byte(accept_fd);
111
+    usleep(200000); /* 0.2s */
112
+
113
+    addr = ipv6 ? (ipv4mapped ? "::ffff:"ADDR_2 : ADDR6_2) : ADDR_2;
114
+    err = userspace_pm_add_subflow(token, addr, 100);
115
+    if (!ASSERT_OK(err, "userspace_pm_add_subflow 100"))
116
+        goto close_accept;
117
+
118
+    send_byte(accept_fd);
119
+    recv_byte(client_fd);
120
+
121
+    err = userspace_pm_set_flags(token, addr, "backup");
122
+    if (!ASSERT_OK(err, "userspace_pm_set_flags backup"))
123
+        goto close_accept;
124
+
125
+    send_byte(client_fd);
126
+    recv_byte(accept_fd);
127
+
128
+    err = userspace_pm_set_flags(token, addr, "nobackup");
129
+    if (!ASSERT_OK(err, "userspace_pm_set_flags nobackup"))
130
+        goto close_accept;
131
+
132
+    send_byte(accept_fd);
133
+    recv_byte(client_fd);
134
+
135
+    err = userspace_pm_rm_subflow(token, addr, 100);
136
+    if (!ASSERT_OK(err, "userspace_pm_rm_subflow 100"))
137
+        goto close_accept;
138
+
139
+    send_byte(client_fd);
140
+    recv_byte(accept_fd);
141
+
142
+    addr = ipv6 ? (ipv4mapped ? "::ffff:"ADDR_3 : ADDR6_3) : ADDR_3;
143
+    err = userspace_pm_add_addr(token, addr, 200);
144
+    if (!ASSERT_OK(err, "userspace_pm_add_addr 200"))
145
+        goto close_accept;
146
+
147
+    send_byte(accept_fd);
148
+    recv_byte(client_fd);
149
+
150
+    err = userspace_pm_rm_addr(token, 200);
151
+    if (!ASSERT_OK(err, "userspace_pm_rm_addr 200"))
152
+        goto close_accept;
153
+
154
+    send_byte(client_fd);
155
+    recv_byte(accept_fd);
156
+
157
+close_accept:
158
+    close(accept_fd);
159
+close_client:
160
+    close(client_fd);
161
+close_server:
162
+    close(server_fd);
163
+}
164
+
165
+static void test_userspace_pm(void)
166
+{
167
+    struct netns_obj *netns;
168
+    int err;
169
+
170
+    netns = netns_new(NS_TEST, true);
171
+    if (!ASSERT_OK_PTR(netns, "netns_new"))
172
+        return;
173
+
174
+    err = userspace_pm_init(MPTCP_PM_TYPE_USERSPACE);
175
+    if (!ASSERT_OK(err, "userspace_pm_init: userspace pm"))
176
+        goto fail;
177
+
178
+    run_userspace_pm(IPV4MAPPED);
179
+
180
+    userspace_pm_cleanup();
181
+fail:
182
+    netns_free(netns);
183
+}
184
+
185
static struct netns_obj *sched_init(char *flags, char *sched)
186
{
60
{
187
    struct netns_obj *netns;
61
    const struct mptcp_addr_info *addr = &entry->addr;
188
@@ -XXX,XX +XXX,XX @@ void test_mptcp(void)
62
-    struct mptcp_rm_list list = { .nr = 1 };
189
        test_iters_subflow();
63
    long s_slot = 0, s_num = 0;
190
    if (test__start_subtest("iters_address"))
64
    struct mptcp_sock *msk;
191
        test_iters_address();
65
192
+    if (test__start_subtest("userspace_pm"))
66
@@ -XXX,XX +XXX,XX @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
193
+        test_userspace_pm();
67
194
    if (test__start_subtest("default"))
68
    while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
195
        test_default();
69
        struct sock *sk = (struct sock *)msk;
196
    if (test__start_subtest("first"))
70
-        bool remove_subflow;
71
72
        if (mptcp_pm_is_userspace(msk))
73
            goto next;
74
75
        lock_sock(sk);
76
-        remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, addr);
77
-        mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
78
-                     !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
79
-
80
-        list.ids[0] = mptcp_endp_get_local_id(msk, addr);
81
-        if (remove_subflow) {
82
-            spin_lock_bh(&msk->pm.lock);
83
-            mptcp_pm_nl_rm_subflow_received(msk, &list);
84
-            spin_unlock_bh(&msk->pm.lock);
85
-        }
86
-
87
-        if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
88
-            spin_lock_bh(&msk->pm.lock);
89
-            __mark_subflow_endp_available(msk, list.ids[0]);
90
-            spin_unlock_bh(&msk->pm.lock);
91
-        }
92
-
93
-        if (msk->mpc_endpoint_id == entry->addr.id)
94
-            msk->mpc_endpoint_id = 0;
95
+        mptcp_pm_nl_address_removed(msk, entry);
96
+        mptcp_pm_nl_subflow_closed(msk, entry);
97
        release_sock(sk);
98
99
next:
197
--
100
--
198
2.43.0
101
2.43.0
diff view generated by jsdifflib
New patch
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
2
3
Extract address_announced() interface of the in-kernel netlink PM from
4
the helper mptcp_nl_add_subflow_or_signal_addr(), only leave the code
5
for traversing all msk in the helper.
6
7
This interface is invoked under holding the msk socket lock.
8
9
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
10
---
11
net/mptcp/pm_netlink.c | 34 +++++++++++++++++++++++++---------
12
1 file changed, 25 insertions(+), 9 deletions(-)
13
14
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/mptcp/pm_netlink.c
17
+++ b/net/mptcp/pm_netlink.c
18
@@ -XXX,XX +XXX,XX @@ static struct pm_nl_pernet *genl_info_pm_nl(struct genl_info *info)
19
    return pm_nl_get_pernet(genl_info_net(info));
20
}
21
22
+static int mptcp_pm_nl_address_announced(struct mptcp_sock *msk,
23
+                     struct mptcp_pm_param *param)
24
+{
25
+    struct mptcp_addr_info *addr = &param->addr;
26
+    struct mptcp_addr_info mpc_addr;
27
+
28
+    /* if the endp linked to the init sf is re-added with a != ID */
29
+    mptcp_local_address((struct sock_common *)msk, &mpc_addr);
30
+
31
+    spin_lock_bh(&msk->pm.lock);
32
+    if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
33
+        msk->mpc_endpoint_id = addr->id;
34
+
35
+    mptcp_pm_create_subflow_or_signal_addr(msk);
36
+    spin_unlock_bh(&msk->pm.lock);
37
+
38
+    return 0;
39
+}
40
+
41
static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
42
                     struct mptcp_addr_info *addr)
43
{
44
@@ -XXX,XX +XXX,XX @@ static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
45
46
    while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
47
        struct sock *sk = (struct sock *)msk;
48
-        struct mptcp_addr_info mpc_addr;
49
+        struct mptcp_pm_param param;
50
51
        if (!READ_ONCE(msk->fully_established) ||
52
         mptcp_pm_is_userspace(msk))
53
            goto next;
54
55
-        /* if the endp linked to the init sf is re-added with a != ID */
56
-        mptcp_local_address((struct sock_common *)msk, &mpc_addr);
57
-
58
        lock_sock(sk);
59
-        spin_lock_bh(&msk->pm.lock);
60
-        if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
61
-            msk->mpc_endpoint_id = addr->id;
62
-        mptcp_pm_create_subflow_or_signal_addr(msk);
63
-        spin_unlock_bh(&msk->pm.lock);
64
+        mptcp_pm_param_set_contexts(&param, NULL, addr);
65
+        msk->pm.ops && msk->pm.ops->address_announced ?
66
+            msk->pm.ops->address_announced(msk, &param) :
67
+            mptcp_pm_nl_address_announced(msk, &param);
68
        release_sock(sk);
69
70
next:
71
@@ -XXX,XX +XXX,XX @@ static struct pernet_operations mptcp_pm_pernet_ops = {
72
};
73
74
static struct mptcp_pm_ops mptcp_netlink_pm = {
75
+    .address_announced    = mptcp_pm_nl_address_announced,
76
    .get_local_id        = mptcp_pm_nl_get_local_id,
77
    .get_priority        = mptcp_pm_nl_get_priority,
78
    .type            = MPTCP_PM_TYPE_KERNEL,
79
--
80
2.43.0
diff view generated by jsdifflib
New patch
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
2
3
Update the 2nd parameter of mptcp_pm_nl_address_removed(), and define it
4
as the address_removed() interface of the in-kernel netlink PM.
5
6
This interface is invoked under holding the msk socket lock.
7
8
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
9
---
10
net/mptcp/pm_netlink.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/net/mptcp/pm_netlink.c
16
+++ b/net/mptcp/pm_netlink.c
17
@@ -XXX,XX +XXX,XX @@ static void __mark_subflow_endp_available(struct mptcp_sock *msk, u8 id)
18
}
19
20
static int mptcp_pm_nl_address_removed(struct mptcp_sock *msk,
21
-                 const struct mptcp_pm_addr_entry *local)
22
+                 struct mptcp_pm_param *param)
23
{
24
+    struct mptcp_pm_addr_entry *local = &param->entry;
25
    bool remove_subflow;
26
27
    remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, &local->addr);
28
@@ -XXX,XX +XXX,XX @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
29
30
    while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
31
        struct sock *sk = (struct sock *)msk;
32
+        struct mptcp_pm_param param;
33
34
        if (mptcp_pm_is_userspace(msk))
35
            goto next;
36
37
        lock_sock(sk);
38
-        mptcp_pm_nl_address_removed(msk, entry);
39
+        mptcp_pm_param_set_contexts(&param, entry, NULL);
40
+        msk->pm.ops && msk->pm.ops->address_removed ?
41
+            msk->pm.ops->address_removed(msk, &param) :
42
+            mptcp_pm_nl_address_removed(msk, &param);
43
        mptcp_pm_nl_subflow_closed(msk, entry);
44
        release_sock(sk);
45
46
@@ -XXX,XX +XXX,XX @@ static struct pernet_operations mptcp_pm_pernet_ops = {
47
48
static struct mptcp_pm_ops mptcp_netlink_pm = {
49
    .address_announced    = mptcp_pm_nl_address_announced,
50
+    .address_removed    = mptcp_pm_nl_address_removed,
51
    .get_local_id        = mptcp_pm_nl_get_local_id,
52
    .get_priority        = mptcp_pm_nl_get_priority,
53
    .type            = MPTCP_PM_TYPE_KERNEL,
54
--
55
2.43.0
diff view generated by jsdifflib
New patch
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
2
3
Update mptcp_pm_nl_subflow_established() to match the parameters and
4
return value of subflow_established() interface and define it as the
5
interface of the in-kernel netlink PM.
6
7
This interface is invoked under holding the msk socket lock.
8
9
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
10
---
11
net/mptcp/pm_netlink.c | 11 +++++++++--
12
1 file changed, 9 insertions(+), 2 deletions(-)
13
14
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/mptcp/pm_netlink.c
17
+++ b/net/mptcp/pm_netlink.c
18
@@ -XXX,XX +XXX,XX @@ static void mptcp_pm_nl_fully_established(struct mptcp_sock *msk)
19
    mptcp_pm_create_subflow_or_signal_addr(msk);
20
}
21
22
-static void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk)
23
+static int mptcp_pm_nl_subflow_established(struct mptcp_sock *msk,
24
+                     struct mptcp_pm_param *param)
25
{
26
    mptcp_pm_create_subflow_or_signal_addr(msk);
27
+
28
+    return 0;
29
}
30
31
/* Fill all the local addresses into the array addrs[],
32
@@ -XXX,XX +XXX,XX @@ static void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
33
void mptcp_pm_nl_work(struct mptcp_sock *msk)
34
{
35
    struct mptcp_pm_data *pm = &msk->pm;
36
+    struct mptcp_pm_param param;
37
38
    msk_owned_by_me(msk);
39
40
@@ -XXX,XX +XXX,XX @@ void mptcp_pm_nl_work(struct mptcp_sock *msk)
41
    }
42
    if (pm->status & BIT(MPTCP_PM_SUBFLOW_ESTABLISHED)) {
43
        pm->status &= ~BIT(MPTCP_PM_SUBFLOW_ESTABLISHED);
44
-        mptcp_pm_nl_subflow_established(msk);
45
+        msk->pm.ops && msk->pm.ops->subflow_established ?
46
+            msk->pm.ops->subflow_established(msk, &param) :
47
+            mptcp_pm_nl_subflow_established(msk, &param);
48
    }
49
50
    spin_unlock_bh(&msk->pm.lock);
51
@@ -XXX,XX +XXX,XX @@ static struct pernet_operations mptcp_pm_pernet_ops = {
52
static struct mptcp_pm_ops mptcp_netlink_pm = {
53
    .address_announced    = mptcp_pm_nl_address_announced,
54
    .address_removed    = mptcp_pm_nl_address_removed,
55
+    .subflow_established    = mptcp_pm_nl_subflow_established,
56
    .get_local_id        = mptcp_pm_nl_get_local_id,
57
    .get_priority        = mptcp_pm_nl_get_priority,
58
    .type            = MPTCP_PM_TYPE_KERNEL,
59
--
60
2.43.0
diff view generated by jsdifflib
New patch
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
2
3
Update the 2nd parameter of mptcp_pm_nl_subflow_closed(), and define it
4
as the subflow_closed() interface of the in-kernel netlink PM.
5
6
This interface is invoked under holding the msk socket lock.
7
8
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
9
---
10
net/mptcp/pm_netlink.c | 8 ++++++--
11
1 file changed, 6 insertions(+), 2 deletions(-)
12
13
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/net/mptcp/pm_netlink.c
16
+++ b/net/mptcp/pm_netlink.c
17
@@ -XXX,XX +XXX,XX @@ static int mptcp_pm_nl_address_removed(struct mptcp_sock *msk,
18
}
19
20
static int mptcp_pm_nl_subflow_closed(struct mptcp_sock *msk,
21
-                 const struct mptcp_pm_addr_entry *local)
22
+                 struct mptcp_pm_param *param)
23
{
24
+    struct mptcp_pm_addr_entry *local = &param->entry;
25
    struct mptcp_rm_list list = { .nr = 1 };
26
    bool remove_subflow;
27
28
@@ -XXX,XX +XXX,XX @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
29
        msk->pm.ops && msk->pm.ops->address_removed ?
30
            msk->pm.ops->address_removed(msk, &param) :
31
            mptcp_pm_nl_address_removed(msk, &param);
32
-        mptcp_pm_nl_subflow_closed(msk, entry);
33
+        msk->pm.ops && msk->pm.ops->subflow_closed ?
34
+            msk->pm.ops->subflow_closed(msk, &param) :
35
+            mptcp_pm_nl_subflow_closed(msk, &param);
36
        release_sock(sk);
37
38
next:
39
@@ -XXX,XX +XXX,XX @@ static struct mptcp_pm_ops mptcp_netlink_pm = {
40
    .address_announced    = mptcp_pm_nl_address_announced,
41
    .address_removed    = mptcp_pm_nl_address_removed,
42
    .subflow_established    = mptcp_pm_nl_subflow_established,
43
+    .subflow_closed        = mptcp_pm_nl_subflow_closed,
44
    .get_local_id        = mptcp_pm_nl_get_local_id,
45
    .get_priority        = mptcp_pm_nl_get_priority,
46
    .type            = MPTCP_PM_TYPE_KERNEL,
47
--
48
2.43.0
diff view generated by jsdifflib
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
This patch adds an mptcp bpf userspace pm example program, implements
3
Extract address_announced() interface of the userspace PM from the handler
4
address_announce, address_remove, subflow_create, subflow_destroy,
4
of netlink command MPTCP_PM_CMD_ANNOUNCE mptcp_pm_nl_announce_doit(), only
5
get_local_id, is_backup, and set_flags interfaces using almost the
5
leave the code for obtaining msk through "info" and parsing address entry
6
same logic as the userspace pm in kernel.
6
in the handler.
7
8
This interface is invoked under holding the msk socket lock.
7
9
8
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
10
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
9
---
11
---
10
.../testing/selftests/bpf/prog_tests/mptcp.c | 51 ++++
12
net/mptcp/pm_userspace.c | 49 ++++++++++++++++++++++++++--------------
11
tools/testing/selftests/bpf/progs/mptcp_bpf.h | 75 +++++
13
1 file changed, 32 insertions(+), 17 deletions(-)
12
.../bpf/progs/mptcp_bpf_userspace_pm.c | 275 ++++++++++++++++++
13
3 files changed, 401 insertions(+)
14
create mode 100644 tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c
15
14
16
diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing/selftests/bpf/prog_tests/mptcp.c
15
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/tools/testing/selftests/bpf/prog_tests/mptcp.c
17
--- a/net/mptcp/pm_userspace.c
19
+++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c
18
+++ b/net/mptcp/pm_userspace.c
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static struct mptcp_sock *mptcp_userspace_pm_get_sock(const struct genl_info *in
21
#include "mptcpify.skel.h"
20
    return msk;
22
#include "mptcp_subflow.skel.h"
23
#include "mptcp_bpf_iters.skel.h"
24
+#include "mptcp_bpf_userspace_pm.skel.h"
25
#include "mptcp_bpf_first.skel.h"
26
#include "mptcp_bpf_bkup.skel.h"
27
#include "mptcp_bpf_rr.skel.h"
28
@@ -XXX,XX +XXX,XX @@
29
enum mptcp_pm_type {
30
    MPTCP_PM_TYPE_KERNEL = 0,
31
    MPTCP_PM_TYPE_USERSPACE,
32
+    MPTCP_PM_TYPE_BPF_USERSPACE,
33
34
    __MPTCP_PM_TYPE_NR,
35
    __MPTCP_PM_TYPE_MAX = __MPTCP_PM_TYPE_NR - 1,
36
@@ -XXX,XX +XXX,XX @@ static void test_userspace_pm(void)
37
    netns_free(netns);
38
}
21
}
39
22
40
+static void test_bpf_path_manager(void)
23
+static int mptcp_userspace_pm_address_announced(struct mptcp_sock *msk,
24
+                        struct mptcp_pm_param *param)
41
+{
25
+{
42
+    struct mptcp_bpf_userspace_pm *skel;
26
+    struct mptcp_pm_addr_entry *local = &param->entry;
43
+    struct netns_obj *netns;
44
+    int err;
45
+
46
+    skel = mptcp_bpf_userspace_pm__open();
47
+    if (!ASSERT_OK_PTR(skel, "open: userspace_pm"))
48
+        return;
49
+
50
+    err = bpf_program__set_flags(skel->progs.mptcp_userspace_pm_address_announced,
51
+                 BPF_F_SLEEPABLE);
52
+    err = err ?: bpf_program__set_flags(skel->progs.mptcp_userspace_pm_address_removed,
53
+                     BPF_F_SLEEPABLE);
54
+    err = err ?: bpf_program__set_flags(skel->progs.mptcp_userspace_pm_subflow_established,
55
+                     BPF_F_SLEEPABLE);
56
+    err = err ?: bpf_program__set_flags(skel->progs.mptcp_userspace_pm_subflow_closed,
57
+                     BPF_F_SLEEPABLE);
58
+    err = err ?: bpf_program__set_flags(skel->progs.mptcp_userspace_pm_set_priority,
59
+                     BPF_F_SLEEPABLE);
60
+    if (!ASSERT_OK(err, "set sleepable flags"))
61
+        goto skel_destroy;
62
+
63
+    if (!ASSERT_OK(mptcp_bpf_userspace_pm__load(skel), "load: userspace_pm"))
64
+        goto skel_destroy;
65
+
66
+    err = mptcp_bpf_userspace_pm__attach(skel);
67
+    if (!ASSERT_OK(err, "attach: userspace_pm"))
68
+        goto skel_destroy;
69
+
70
+    netns = netns_new(NS_TEST, true);
71
+    if (!ASSERT_OK_PTR(netns, "netns_new"))
72
+        goto skel_destroy;
73
+
74
+    err = userspace_pm_init(MPTCP_PM_TYPE_BPF_USERSPACE);
75
+    if (!ASSERT_OK(err, "userspace_pm_init: bpf pm"))
76
+        goto close_netns;
77
+
78
+    run_userspace_pm(skel->kconfig->CONFIG_MPTCP_IPV6 ? IPV6 : IPV4);
79
+
80
+    userspace_pm_cleanup();
81
+close_netns:
82
+    netns_free(netns);
83
+skel_destroy:
84
+    mptcp_bpf_userspace_pm__destroy(skel);
85
+}
86
+
87
static struct netns_obj *sched_init(char *flags, char *sched)
88
{
89
    struct netns_obj *netns;
90
@@ -XXX,XX +XXX,XX @@ void test_mptcp(void)
91
        test_iters_address();
92
    if (test__start_subtest("userspace_pm"))
93
        test_userspace_pm();
94
+    if (test__start_subtest("bpf_path_manager"))
95
+        test_bpf_path_manager();
96
    if (test__start_subtest("default"))
97
        test_default();
98
    if (test__start_subtest("first"))
99
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h
102
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
103
@@ -XXX,XX +XXX,XX @@ static inline int list_is_head(const struct list_head *list,
104
#define    ENOMEM        12    /* Out of Memory */
105
#define    EINVAL        22    /* Invalid argument */
106
107
+/* mptcp helpers from include/net/mptcp.h */
108
+#define U8_MAX        ((u8)~0U)
109
+
110
+/* max value of mptcp_addr_info.id */
111
+#define MPTCP_PM_MAX_ADDR_ID        U8_MAX
112
+
113
+/* mptcp macros from include/uapi/linux/mptcp.h */
114
+#define MPTCP_PM_ADDR_FLAG_SIGNAL            (1 << 0)
115
+#define MPTCP_PM_ADDR_FLAG_SUBFLOW            (1 << 1)
116
+#define MPTCP_PM_ADDR_FLAG_BACKUP            (1 << 2)
117
+#define MPTCP_PM_ADDR_FLAG_FULLMESH            (1 << 3)
118
+#define MPTCP_PM_ADDR_FLAG_IMPLICIT            (1 << 4)
119
+
120
+/* address families macros from include/linux/socket.h */
121
+#define AF_UNSPEC    0
122
+#define AF_INET        2
123
+#define AF_INET6    10
124
+
125
+/* shutdown macros from include/net/sock.h */
126
+#define RCV_SHUTDOWN    1
127
+#define SEND_SHUTDOWN    2
128
+
129
+/* GFP macros from include/linux/gfp_types.h */
130
+#define __AC(X,Y)    (X##Y)
131
+#define _AC(X,Y)    __AC(X,Y)
132
+#define _UL(x)        (_AC(x, UL))
133
+#define UL(x)        (_UL(x))
134
+#define BIT(nr)        (UL(1) << (nr))
135
+
136
+#define ___GFP_HIGH        BIT(___GFP_HIGH_BIT)
137
+#define __GFP_HIGH        ((gfp_t)___GFP_HIGH)
138
+#define ___GFP_KSWAPD_RECLAIM    BIT(___GFP_KSWAPD_RECLAIM_BIT)
139
+#define __GFP_KSWAPD_RECLAIM    ((gfp_t)___GFP_KSWAPD_RECLAIM) /* kswapd can wake */
140
+#define GFP_ATOMIC        (__GFP_HIGH|__GFP_KSWAPD_RECLAIM)
141
+
142
static __always_inline struct sock *
143
mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow)
144
{
145
@@ -XXX,XX +XXX,XX @@ extern void bpf_spin_unlock_bh(spinlock_t *lock) __ksym;
146
147
extern bool bpf_ipv4_is_private_10(__be32 addr) __ksym;
148
149
+extern struct mptcp_pm_addr_entry *
150
+bpf_sock_kmalloc_entry(struct sock *sk, int size, gfp_t priority) __ksym;
151
+extern void
152
+bpf_sock_kfree_entry(struct sock *sk, struct mptcp_pm_addr_entry *entry,
153
+         int size) __ksym;
154
+
155
+extern bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
156
+                 const struct mptcp_addr_info *addr) __ksym;
157
+extern int mptcp_pm_announce_addr(struct mptcp_sock *msk,
158
+                 const struct mptcp_addr_info *addr,
159
+                 bool echo) __ksym;
160
+extern void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) __ksym;
161
+
162
+extern void bpf_bitmap_zero(unsigned long *dst, unsigned int nbits) __ksym;
163
+extern void bpf_set_bit(unsigned long nr, unsigned long *addr) __ksym;
164
+extern u8 bpf_find_next_zero_bit(const unsigned long *addr,
165
+                 unsigned long size, unsigned long offset) __ksym;
166
+
167
+extern int mptcp_pm_remove_addr(struct mptcp_sock *msk,
168
+                const struct mptcp_rm_list *rm_list) __ksym;
169
+extern void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
170
+                 struct mptcp_pm_addr_entry *entry) __ksym;
171
+
172
+extern int bpf_mptcp_subflow_connect(struct sock *sk,
173
+                 const struct mptcp_pm_addr_entry *entry,
174
+                 const struct mptcp_addr_info *remote) __ksym;
175
+
176
+extern void
177
+mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how) __ksym;
178
+extern void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
179
+             struct mptcp_subflow_context *subflow) __ksym;
180
+extern struct net *bpf_sock_net(const struct sock *sk) __ksym;
181
+extern void BPF_MPTCP_INC_STATS(struct net *net,
182
+                enum linux_mptcp_mib_field field) __ksym;
183
+
184
+extern int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
185
+                    struct mptcp_addr_info *addr,
186
+                    struct mptcp_addr_info *rem,
187
+                    u8 bkup) __ksym;
188
+
189
extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
190
                    bool scheduled) __ksym;
191
192
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c b/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c
193
new file mode 100644
194
index XXXXXXX..XXXXXXX
195
--- /dev/null
196
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_userspace_pm.c
197
@@ -XXX,XX +XXX,XX @@
198
+// SPDX-License-Identifier: GPL-2.0
199
+/* Copyright (c) 2025, Kylin Software */
200
+
201
+#include "mptcp_bpf.h"
202
+
203
+char _license[] SEC("license") = "GPL";
204
+
205
+extern bool CONFIG_MPTCP_IPV6 __kconfig __weak;
206
+
207
+extern void bpf_list_add_tail_rcu(struct list_head *new,
208
+                 struct list_head *head) __ksym;
209
+extern void bpf_list_del_rcu(struct list_head *entry) __ksym;
210
+
211
+SEC("struct_ops")
212
+void BPF_PROG(mptcp_userspace_pm_init, struct mptcp_sock *msk)
213
+{
214
+    bpf_printk("BPF userspace PM (%s)",
215
+         CONFIG_MPTCP_IPV6 ? "IPv6" : "IPv4");
216
+}
217
+
218
+SEC("struct_ops")
219
+void BPF_PROG(mptcp_userspace_pm_release, struct mptcp_sock *msk)
220
+{
221
+}
222
+
223
+static struct mptcp_pm_addr_entry *
224
+mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk,
225
+             const struct mptcp_addr_info *addr)
226
+{
227
+    struct mptcp_pm_addr_entry *entry;
228
+
229
+    bpf_for_each(mptcp_userspace_pm_addr, entry, (struct sock *)msk) {
230
+        if (mptcp_addresses_equal(&entry->addr, addr, false))
231
+            return entry;
232
+    }
233
+    return NULL;
234
+}
235
+
236
+static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
237
+                         struct mptcp_pm_addr_entry *entry,
238
+                         bool needs_id)
239
+{
240
+    struct sock *sk = (struct sock *)msk;
241
+    unsigned long id_bitmap[4] = { 0 };
242
+    struct mptcp_pm_addr_entry *e;
243
+    bool addr_match = false;
244
+    bool id_match = false;
245
+    int ret = -EINVAL;
246
+
247
+    bpf_bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
248
+
249
+    bpf_spin_lock_bh(&msk->pm.lock);
250
+    bpf_for_each(mptcp_userspace_pm_addr, e, sk) {
251
+        addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true);
252
+        if (addr_match && entry->addr.id == 0 && needs_id)
253
+            entry->addr.id = e->addr.id;
254
+        id_match = (e->addr.id == entry->addr.id);
255
+        if (addr_match || id_match)
256
+            break;
257
+        bpf_set_bit(e->addr.id, id_bitmap);
258
+    }
259
+
260
+    if (!addr_match && !id_match) {
261
+        /* Memory for the entry is allocated from the
262
+         * sock option buffer.
263
+         */
264
+        e = bpf_sock_kmalloc_entry(sk, sizeof(*e), GFP_ATOMIC);
265
+        if (!e) {
266
+            ret = -ENOMEM;
267
+            goto append_err;
268
+        }
269
+
270
+        mptcp_pm_copy_entry(e, entry);
271
+        if (!e->addr.id && needs_id)
272
+            e->addr.id = bpf_find_next_zero_bit(id_bitmap,
273
+                             MPTCP_PM_MAX_ADDR_ID + 1,
274
+                             1);
275
+        bpf_list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
276
+        msk->pm.local_addr_used++;
277
+        ret = e->addr.id;
278
+    } else if (addr_match && id_match) {
279
+        ret = entry->addr.id;
280
+    }
281
+
282
+append_err:
283
+    bpf_spin_unlock_bh(&msk->pm.lock);
284
+    return ret;
285
+}
286
+
287
+SEC("struct_ops")
288
+int BPF_PROG(mptcp_userspace_pm_address_announced, struct mptcp_sock *msk,
289
+     struct mptcp_pm_addr_entry *local)
290
+{
291
+    int err;
27
+    int err;
292
+
28
+
293
+    err = mptcp_userspace_pm_append_new_local_addr(msk, local, false);
29
+    err = mptcp_userspace_pm_append_new_local_addr(msk, local, false);
294
+    if (err < 0)
30
+    if (err < 0)
295
+        return err;
31
+        return err;
296
+
32
+
297
+    bpf_spin_lock_bh(&msk->pm.lock);
33
+    spin_lock_bh(&msk->pm.lock);
298
+
34
+
299
+    if (mptcp_pm_alloc_anno_list(msk, &local->addr)) {
35
+    if (mptcp_pm_alloc_anno_list(msk, &local->addr)) {
300
+        msk->pm.add_addr_signaled++;
36
+        msk->pm.add_addr_signaled++;
301
+        mptcp_pm_announce_addr(msk, &local->addr, false);
37
+        mptcp_pm_announce_addr(msk, &local->addr, false);
302
+        mptcp_pm_nl_addr_send_ack(msk);
38
+        mptcp_pm_nl_addr_send_ack(msk);
303
+    }
39
+    }
304
+
40
+
305
+    bpf_spin_unlock_bh(&msk->pm.lock);
41
+    spin_unlock_bh(&msk->pm.lock);
306
+
42
+
307
+    return 0;
43
+    return 0;
308
+}
44
+}
309
+
45
+
310
+static struct mptcp_pm_addr_entry *
46
int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
311
+mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
47
{
312
+{
48
    struct mptcp_pm_addr_entry addr_val;
313
+    struct mptcp_pm_addr_entry *entry;
49
+    struct mptcp_pm_param param;
314
+
50
    struct mptcp_sock *msk;
315
+    bpf_for_each(mptcp_userspace_pm_addr, entry, (struct sock *)msk) {
51
    struct nlattr *addr;
316
+        if (entry->addr.id == id)
52
    int err = -EINVAL;
317
+            return entry;
53
@@ -XXX,XX +XXX,XX @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
318
+    }
54
        goto announce_err;
319
+    return NULL;
55
    }
320
+}
56
321
+
57
-    err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val, false);
322
+SEC("struct_ops")
58
-    if (err < 0) {
323
+int BPF_PROG(mptcp_userspace_pm_address_removed, struct mptcp_sock *msk, u8 id)
59
-        NL_SET_ERR_MSG_ATTR(info->extack, addr,
324
+{
60
-                 "did not match address and id");
325
+    struct mptcp_pm_addr_entry *entry;
61
-        goto announce_err;
326
+
62
-    }
327
+    bpf_spin_lock_bh(&msk->pm.lock);
63
-
328
+    entry = mptcp_userspace_pm_lookup_addr_by_id(msk, id);
64
    lock_sock(sk);
329
+    if (!entry) {
65
-    spin_lock_bh(&msk->pm.lock);
330
+        bpf_spin_unlock_bh(&msk->pm.lock);
66
-
331
+        return -EINVAL;
67
-    if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) {
332
+    }
68
-        msk->pm.add_addr_signaled++;
333
+
69
-        mptcp_pm_announce_addr(msk, &addr_val.addr, false);
334
+    bpf_list_del_rcu(&entry->list);
70
-        mptcp_pm_nl_addr_send_ack(msk);
335
+    bpf_spin_unlock_bh(&msk->pm.lock);
71
-    }
336
+
72
-
337
+    mptcp_pm_remove_addr_entry(msk, entry);
73
-    spin_unlock_bh(&msk->pm.lock);
338
+
74
+    mptcp_pm_param_set_contexts(&param, &addr_val, NULL);
339
+    bpf_sock_kfree_entry((struct sock *)msk, entry, sizeof(*entry));
75
+    err = msk->pm.ops && msk->pm.ops->address_announced ?
340
+
76
+     msk->pm.ops->address_announced(msk, &param) :
341
+    return 0;
77
+     mptcp_userspace_pm_address_announced(msk, &param);
342
+}
78
    release_sock(sk);
343
+
344
+static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
345
+                        struct mptcp_pm_addr_entry *addr)
346
+{
347
+    struct sock *sk = (struct sock *)msk;
348
+    struct mptcp_pm_addr_entry *entry;
349
+
350
+    entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr);
351
+    if (!entry)
352
+        return -EINVAL;
353
+
354
+    bpf_list_del_rcu(&entry->list);
355
+    bpf_sock_kfree_entry(sk, entry, sizeof(*entry));
356
+    msk->pm.local_addr_used--;
357
+    return 0;
358
+}
359
+
360
+SEC("struct_ops")
361
+int BPF_PROG(mptcp_userspace_pm_subflow_established, struct mptcp_sock *msk,
362
+     struct mptcp_pm_addr_entry *local, struct mptcp_addr_info *remote)
363
+{
364
+    struct sock *sk = (struct sock *)msk;
365
+    int err;
366
+
367
+    err = mptcp_userspace_pm_append_new_local_addr(msk, local, false);
368
+    if (err < 0)
369
+        return err;
370
+
371
+    err = bpf_mptcp_subflow_connect(sk, local, remote);
372
+    bpf_spin_lock_bh(&msk->pm.lock);
373
+    if (err)
79
+    if (err)
374
+        mptcp_userspace_pm_delete_local_addr(msk, local);
80
+        NL_SET_ERR_MSG_ATTR(info->extack, addr,
375
+    else
81
+                 "did not match address and id");
376
+        msk->pm.subflows++;
82
377
+    bpf_spin_unlock_bh(&msk->pm.lock);
83
-    err = 0;
378
+
84
announce_err:
379
+    return err;
85
    sock_put(sk);
380
+}
86
    return err;
381
+
87
@@ -XXX,XX +XXX,XX @@ int mptcp_userspace_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
382
+SEC("struct_ops")
88
}
383
+int BPF_PROG(mptcp_userspace_pm_subflow_closed, struct mptcp_sock *msk,
89
384
+     struct mptcp_pm_addr_entry *local, struct mptcp_addr_info *remote)
90
static struct mptcp_pm_ops mptcp_userspace_pm = {
385
+{
91
+    .address_announced    = mptcp_userspace_pm_address_announced,
386
+    struct sock *ssk, *sk = (struct sock *)msk;
92
    .get_local_id        = mptcp_userspace_pm_get_local_id,
387
+    struct mptcp_subflow_context *subflow;
93
    .get_priority        = mptcp_userspace_pm_get_priority,
388
+
94
    .type            = MPTCP_PM_TYPE_USERSPACE,
389
+    ssk = mptcp_pm_find_ssk(msk, &local->addr, remote);
390
+    if (!ssk)
391
+        return -ESRCH;
392
+
393
+    subflow = bpf_mptcp_subflow_ctx(ssk);
394
+    if (!subflow)
395
+        return -EINVAL;
396
+
397
+    bpf_spin_lock_bh(&msk->pm.lock);
398
+    mptcp_userspace_pm_delete_local_addr(msk, local);
399
+    bpf_spin_unlock_bh(&msk->pm.lock);
400
+    mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
401
+    mptcp_close_ssk(sk, ssk, subflow);
402
+    BPF_MPTCP_INC_STATS(bpf_sock_net(sk), MPTCP_MIB_RMSUBFLOW);
403
+
404
+    return 0;
405
+}
406
+
407
+SEC("struct_ops")
408
+int BPF_PROG(mptcp_userspace_pm_get_local_id, struct mptcp_sock *msk,
409
+     struct mptcp_pm_addr_entry *skc)
410
+{
411
+    struct mptcp_pm_addr_entry *entry;
412
+
413
+    bpf_spin_lock_bh(&msk->pm.lock);
414
+    entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
415
+    bpf_spin_unlock_bh(&msk->pm.lock);
416
+    if (entry)
417
+        return entry->addr.id;
418
+
419
+    return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
420
+}
421
+
422
+SEC("struct_ops")
423
+bool BPF_PROG(mptcp_userspace_pm_get_priority, struct mptcp_sock *msk,
424
+     struct mptcp_addr_info *skc)
425
+{
426
+    struct mptcp_pm_addr_entry *entry;
427
+    bool backup;
428
+
429
+    bpf_spin_lock_bh(&msk->pm.lock);
430
+    entry = mptcp_userspace_pm_lookup_addr(msk, skc);
431
+    backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
432
+    bpf_spin_unlock_bh(&msk->pm.lock);
433
+
434
+    return backup;
435
+}
436
+
437
+SEC("struct_ops")
438
+int BPF_PROG(mptcp_userspace_pm_set_priority, struct mptcp_sock *msk,
439
+     struct mptcp_pm_addr_entry *local, struct mptcp_addr_info *remote)
440
+{
441
+    struct mptcp_pm_addr_entry *entry;
442
+    u8 bkup = 0;
443
+
444
+    if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
445
+        bkup = 1;
446
+
447
+    bpf_spin_lock_bh(&msk->pm.lock);
448
+    entry = mptcp_userspace_pm_lookup_addr(msk, &local->addr);
449
+    if (entry) {
450
+        if (bkup)
451
+            entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
452
+        else
453
+            entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
454
+    }
455
+    bpf_spin_unlock_bh(&msk->pm.lock);
456
+
457
+    return mptcp_pm_nl_mp_prio_send_ack(msk, &local->addr, remote, bkup);
458
+}
459
+
460
+SEC(".struct_ops.link")
461
+struct mptcp_pm_ops userspace_pm = {
462
+    .address_announced    = (void *)mptcp_userspace_pm_address_announced,
463
+    .address_removed    = (void *)mptcp_userspace_pm_address_removed,
464
+    .subflow_established    = (void *)mptcp_userspace_pm_subflow_established,
465
+    .subflow_closed        = (void *)mptcp_userspace_pm_subflow_closed,
466
+    .get_local_id        = (void *)mptcp_userspace_pm_get_local_id,
467
+    .get_priority        = (void *)mptcp_userspace_pm_get_priority,
468
+    .set_priority        = (void *)mptcp_userspace_pm_set_priority,
469
+    .init            = (void *)mptcp_userspace_pm_init,
470
+    .release        = (void *)mptcp_userspace_pm_release,
471
+    .type            = MPTCP_PM_TYPE_BPF_USERSPACE,
472
+};
473
--
95
--
474
2.43.0
96
2.43.0
diff view generated by jsdifflib
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
This patch implements a new struct bpf_struct_ops for MPTCP BPF path
3
Extract address_removed() interface of the userspace PM from the handler
4
manager: bpf_mptcp_pm_ops. Register and unregister the bpf path manager
4
of netlink command MPTCP_PM_CMD_REMOVE mptcp_pm_nl_remove_doit(), only
5
in .reg and .unreg.
5
leave the code for parsing address id and obtaining msk through "info"
6
in the handler.
6
7
7
Add write access for some fields of struct mptcp_addr_info, struct
8
This interface is invoked under holding the msk socket lock.
8
mptcp_pm_addr_entry and struct mptcp_sock in .btf_struct_access.
9
10
This MPTCP BPF path manager implementation is similar to BPF TCP CC. And
11
net/ipv4/bpf_tcp_ca.c is a frame of reference for this patch.
12
9
13
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
10
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
14
---
11
---
15
net/mptcp/bpf.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++-
12
net/mptcp/pm_userspace.c | 74 ++++++++++++++++++++--------------------
16
1 file changed, 275 insertions(+), 1 deletion(-)
13
1 file changed, 37 insertions(+), 37 deletions(-)
17
14
18
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
15
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/net/mptcp/bpf.c
17
--- a/net/mptcp/pm_userspace.c
21
+++ b/net/mptcp/bpf.c
18
+++ b/net/mptcp/pm_userspace.c
22
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
23
#include "protocol.h"
20
{
24
21
    struct mptcp_rm_list list = { .nr = 0 };
25
#ifdef CONFIG_BPF_JIT
22
    struct mptcp_subflow_context *subflow;
26
+static struct bpf_struct_ops bpf_mptcp_pm_ops;
23
-    struct sock *sk = (struct sock *)msk;
27
+static u32 mptcp_sock_id,
24
    bool has_id_0 = false;
28
+     mptcp_entry_id;
25
-    int err = -EINVAL;
26
27
-    lock_sock(sk);
28
    mptcp_for_each_subflow(msk, subflow) {
29
        if (READ_ONCE(subflow->local_id) == 0) {
30
            has_id_0 = true;
31
@@ -XXX,XX +XXX,XX @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
32
        }
33
    }
34
    if (!has_id_0)
35
-        goto remove_err;
36
+        return -EINVAL;
37
38
    list.ids[list.nr++] = 0;
39
40
@@ -XXX,XX +XXX,XX @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk)
41
    mptcp_pm_remove_addr(msk, &list);
42
    spin_unlock_bh(&msk->pm.lock);
43
44
-    err = 0;
45
-
46
-remove_err:
47
-    release_sock(sk);
48
-    return err;
49
+    return 0;
50
}
51
52
void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
53
@@ -XXX,XX +XXX,XX @@ void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
54
    spin_unlock_bh(&msk->pm.lock);
55
}
56
57
+static int mptcp_userspace_pm_address_removed(struct mptcp_sock *msk,
58
+                     struct mptcp_pm_param *param)
59
+{
60
+    struct mptcp_pm_addr_entry *entry;
61
+    u8 id = param->addr.id;
29
+
62
+
30
+/* MPTCP BPF path manager */
63
+    if (id == 0)
64
+        return mptcp_userspace_pm_remove_id_zero_address(msk);
31
+
65
+
32
+static const struct bpf_func_proto *
66
+    spin_lock_bh(&msk->pm.lock);
33
+bpf_mptcp_pm_get_func_proto(enum bpf_func_id func_id,
67
+    entry = mptcp_userspace_pm_lookup_addr_by_id(msk, id);
34
+             const struct bpf_prog *prog)
68
+    if (!entry) {
35
+{
69
+        spin_unlock_bh(&msk->pm.lock);
36
+    switch (func_id) {
70
+        return -EINVAL;
37
+    case BPF_FUNC_sk_storage_get:
38
+        return &bpf_sk_storage_get_proto;
39
+    case BPF_FUNC_sk_storage_delete:
40
+        return &bpf_sk_storage_delete_proto;
41
+    default:
42
+        return bpf_base_func_proto(func_id, prog);
43
+    }
44
+}
45
+
46
+static int bpf_mptcp_pm_btf_struct_access(struct bpf_verifier_log *log,
47
+                     const struct bpf_reg_state *reg,
48
+                     int off, int size)
49
+{
50
+    u32 id = reg->btf_id;
51
+    size_t end;
52
+
53
+    if (id == mptcp_sock_id) {
54
+        switch (off) {
55
+        case offsetof(struct mptcp_sock, pm.add_addr_signaled):
56
+            end = offsetofend(struct mptcp_sock, pm.add_addr_signaled);
57
+            break;
58
+        case offsetof(struct mptcp_sock, pm.local_addr_used):
59
+            end = offsetofend(struct mptcp_sock, pm.local_addr_used);
60
+            break;
61
+        case offsetof(struct mptcp_sock, pm.subflows):
62
+            end = offsetofend(struct mptcp_sock, pm.subflows);
63
+            break;
64
+        default:
65
+            bpf_log(log, "no write support to mptcp_sock at off %d\n",
66
+                off);
67
+            return -EACCES;
68
+        }
69
+    } else if (id == mptcp_entry_id) {
70
+        switch (off) {
71
+        case offsetof(struct mptcp_pm_addr_entry, addr.id):
72
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.id);
73
+            break;
74
+        case offsetof(struct mptcp_pm_addr_entry, addr.family):
75
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.family);
76
+            break;
77
+        case offsetof(struct mptcp_pm_addr_entry, addr.port):
78
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.port);
79
+            break;
80
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
81
+        case offsetof(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[0]):
82
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[0]);
83
+            break;
84
+        case offsetof(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[1]):
85
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[1]);
86
+            break;
87
+        case offsetof(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[2]):
88
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[2]);
89
+            break;
90
+        case offsetof(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[3]):
91
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.addr6.s6_addr32[3]);
92
+            break;
93
+#else
94
+        case offsetof(struct mptcp_pm_addr_entry, addr.addr.s_addr):
95
+            end = offsetofend(struct mptcp_pm_addr_entry, addr.addr.s_addr);
96
+            break;
97
+#endif
98
+        case offsetof(struct mptcp_pm_addr_entry, flags):
99
+            end = offsetofend(struct mptcp_pm_addr_entry, flags);
100
+            break;
101
+        case offsetof(struct mptcp_pm_addr_entry, ifindex):
102
+            end = offsetofend(struct mptcp_pm_addr_entry, ifindex);
103
+            break;
104
+        default:
105
+            bpf_log(log, "no write support to mptcp_pm_addr_entry at off %d\n",
106
+                off);
107
+            return -EACCES;
108
+        }
109
+    } else {
110
+        bpf_log(log, "only access to mptcp sock or addr or entry is supported\n");
111
+        return -EACCES;
112
+    }
71
+    }
113
+
72
+
114
+    if (off + size > end) {
73
+    list_del_rcu(&entry->list);
115
+        bpf_log(log, "access beyond %s at off %u size %u ended at %zu",
74
+    spin_unlock_bh(&msk->pm.lock);
116
+            id == mptcp_sock_id ? "mptcp_sock" :
117
+            (id == mptcp_entry_id ? "mptcp_pm_addr_entry" : "mptcp_addr_info"),
118
+            off, size, end);
119
+        return -EACCES;
120
+    }
121
+
75
+
122
+    return NOT_INIT;
76
+    mptcp_pm_remove_addr_entry(msk, entry);
123
+}
124
+
77
+
125
+static const struct bpf_verifier_ops bpf_mptcp_pm_verifier_ops = {
78
+    sock_kfree_s((struct sock *)msk, entry, sizeof(*entry));
126
+    .get_func_proto        = bpf_mptcp_pm_get_func_proto,
127
+    .is_valid_access    = bpf_tracing_btf_ctx_access,
128
+    .btf_struct_access    = bpf_mptcp_pm_btf_struct_access,
129
+};
130
+
131
+static int bpf_mptcp_pm_reg(void *kdata, struct bpf_link *link)
132
+{
133
+    return mptcp_pm_register(kdata);
134
+}
135
+
136
+static void bpf_mptcp_pm_unreg(void *kdata, struct bpf_link *link)
137
+{
138
+    mptcp_pm_unregister(kdata);
139
+}
140
+
141
+static int bpf_mptcp_pm_check_member(const struct btf_type *t,
142
+                 const struct btf_member *member,
143
+                 const struct bpf_prog *prog)
144
+{
145
+    return 0;
146
+}
147
+
148
+static int bpf_mptcp_pm_init_member(const struct btf_type *t,
149
+                 const struct btf_member *member,
150
+                 void *kdata, const void *udata)
151
+{
152
+    const struct mptcp_pm_ops *upm;
153
+    struct mptcp_pm_ops *pm;
154
+    u32 moff;
155
+
156
+    upm = (const struct mptcp_pm_ops *)udata;
157
+    pm = (struct mptcp_pm_ops *)kdata;
158
+
159
+    moff = __btf_member_bit_offset(t, member) / 8;
160
+    switch (moff) {
161
+    case offsetof(struct mptcp_pm_ops, type):
162
+        pm->type = upm->type;
163
+        return 1;
164
+    }
165
+
79
+
166
+    return 0;
80
+    return 0;
167
+}
81
+}
168
+
82
+
169
+static int bpf_mptcp_pm_init(struct btf *btf)
83
int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
170
+{
84
{
171
+    s32 type_id;
85
-    struct mptcp_pm_addr_entry *match;
172
+
86
+    struct mptcp_addr_info addr;
173
+    type_id = btf_find_by_name_kind(btf, "mptcp_sock",
87
+    struct mptcp_pm_param param;
174
+                    BTF_KIND_STRUCT);
88
    struct mptcp_sock *msk;
175
+    if (type_id < 0)
89
    struct nlattr *id;
176
+        return -EINVAL;
90
    int err = -EINVAL;
177
+    mptcp_sock_id = type_id;
91
    struct sock *sk;
178
+
92
-    u8 id_val;
179
+    type_id = btf_find_by_name_kind(btf, "mptcp_pm_addr_entry",
93
180
+                    BTF_KIND_STRUCT);
94
    if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_LOC_ID))
181
+    if (type_id < 0)
95
        return err;
182
+        return -EINVAL;
96
183
+    mptcp_entry_id = type_id;
97
    id = info->attrs[MPTCP_PM_ATTR_LOC_ID];
184
+
98
-    id_val = nla_get_u8(id);
185
+    return 0;
99
+    addr.id = nla_get_u8(id);
186
+}
100
187
+
101
    msk = mptcp_userspace_pm_get_sock(info);
188
+static int bpf_mptcp_pm_validate(void *kdata)
102
    if (!msk)
189
+{
103
@@ -XXX,XX +XXX,XX @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
190
+    return mptcp_pm_validate(kdata);
104
191
+}
105
    sk = (struct sock *)msk;
192
+
106
193
+static int __bpf_mptcp_pm_address_created(struct mptcp_sock *msk)
107
-    if (id_val == 0) {
194
+{
108
-        err = mptcp_userspace_pm_remove_id_zero_address(msk);
195
+    return 0;
109
-        goto out;
196
+}
110
-    }
197
+
111
-
198
+static int __bpf_mptcp_pm_address_established(struct mptcp_sock *msk)
112
    lock_sock(sk);
199
+{
113
-
200
+    return 0;
114
-    spin_lock_bh(&msk->pm.lock);
201
+}
115
-    match = mptcp_userspace_pm_lookup_addr_by_id(msk, id_val);
202
+
116
-    if (!match) {
203
+static int __bpf_mptcp_pm_address_closed(struct mptcp_sock *msk)
117
-        spin_unlock_bh(&msk->pm.lock);
204
+{
118
-        release_sock(sk);
205
+    return 0;
119
-        goto out;
206
+}
120
-    }
207
+
121
-
208
+static int __bpf_mptcp_pm_address_announced(struct mptcp_sock *msk,
122
-    list_del_rcu(&match->list);
209
+                     struct mptcp_pm_addr_entry *addr)
123
-    spin_unlock_bh(&msk->pm.lock);
210
+{
124
-
211
+    return 0;
125
-    mptcp_pm_remove_addr_entry(msk, match);
212
+}
126
-
213
+
127
+    mptcp_pm_param_set_contexts(&param, NULL, &addr);
214
+static int __bpf_mptcp_pm_address_removed(struct mptcp_sock *msk, u8 id)
128
+    err = msk->pm.ops && msk->pm.ops->address_removed ?
215
+{
129
+     msk->pm.ops->address_removed(msk, &param) :
216
+    return 0;
130
+     mptcp_userspace_pm_address_removed(msk, &param);
217
+}
131
    release_sock(sk);
218
+
132
-
219
+static int __bpf_mptcp_pm_subflow_established(struct mptcp_sock *msk,
133
-    sock_kfree_s(sk, match, sizeof(*match));
220
+                     struct mptcp_pm_addr_entry *local,
134
-
221
+                     struct mptcp_addr_info *remote)
135
-    err = 0;
222
+{
136
-out:
223
+    return 0;
137
    if (err)
224
+}
138
        NL_SET_ERR_MSG_ATTR_FMT(info->extack, id,
225
+
139
                    "address with id %u not found",
226
+static int __bpf_mptcp_pm_subflow_closed(struct mptcp_sock *msk,
140
-                    id_val);
227
+                     struct mptcp_pm_addr_entry *local,
141
+                    addr.id);
228
+                     struct mptcp_addr_info *remote)
142
229
+{
143
    sock_put(sk);
230
+    return 0;
144
    return err;
231
+}
145
@@ -XXX,XX +XXX,XX @@ int mptcp_userspace_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
232
+
146
233
+static int __bpf_mptcp_pm_get_local_id(struct mptcp_sock *msk,
147
static struct mptcp_pm_ops mptcp_userspace_pm = {
234
+                 struct mptcp_pm_addr_entry *skc)
148
    .address_announced    = mptcp_userspace_pm_address_announced,
235
+{
149
+    .address_removed    = mptcp_userspace_pm_address_removed,
236
+    return 0;
150
    .get_local_id        = mptcp_userspace_pm_get_local_id,
237
+}
151
    .get_priority        = mptcp_userspace_pm_get_priority,
238
+
152
    .type            = MPTCP_PM_TYPE_USERSPACE,
239
+static bool __bpf_mptcp_pm_get_priority(struct mptcp_sock *msk,
240
+                    struct mptcp_addr_info *skc)
241
+{
242
+    return 0;
243
+}
244
+
245
+static int __bpf_mptcp_pm_set_priority(struct mptcp_sock *msk,
246
+                 struct mptcp_pm_addr_entry *local,
247
+                 struct mptcp_addr_info *remote)
248
+{
249
+    return 0;
250
+}
251
+
252
+static int __bpf_mptcp_pm_address_listener_created(struct mptcp_sock *msk)
253
+{
254
+    return 0;
255
+}
256
+
257
+static int __bpf_mptcp_pm_address_listener_closed(struct mptcp_sock *msk)
258
+{
259
+    return 0;
260
+}
261
+
262
+static void __bpf_mptcp_pm_init(struct mptcp_sock *msk)
263
+{
264
+}
265
+
266
+static void __bpf_mptcp_pm_release(struct mptcp_sock *msk)
267
+{
268
+}
269
+
270
+static struct mptcp_pm_ops __bpf_mptcp_pm_ops = {
271
+    .created        = __bpf_mptcp_pm_address_created,
272
+    .established        = __bpf_mptcp_pm_address_established,
273
+    .closed            = __bpf_mptcp_pm_address_closed,
274
+    .address_announced    = __bpf_mptcp_pm_address_announced,
275
+    .address_removed    = __bpf_mptcp_pm_address_removed,
276
+    .subflow_established    = __bpf_mptcp_pm_subflow_established,
277
+    .subflow_closed        = __bpf_mptcp_pm_subflow_closed,
278
+    .get_local_id        = __bpf_mptcp_pm_get_local_id,
279
+    .get_priority        = __bpf_mptcp_pm_get_priority,
280
+    .set_priority        = __bpf_mptcp_pm_set_priority,
281
+    .listener_created    = __bpf_mptcp_pm_address_listener_created,
282
+    .listener_closed    = __bpf_mptcp_pm_address_listener_closed,
283
+    .init            = __bpf_mptcp_pm_init,
284
+    .release        = __bpf_mptcp_pm_release,
285
+};
286
+
287
+static struct bpf_struct_ops bpf_mptcp_pm_ops = {
288
+    .verifier_ops    = &bpf_mptcp_pm_verifier_ops,
289
+    .reg        = bpf_mptcp_pm_reg,
290
+    .unreg        = bpf_mptcp_pm_unreg,
291
+    .check_member    = bpf_mptcp_pm_check_member,
292
+    .init_member    = bpf_mptcp_pm_init_member,
293
+    .init        = bpf_mptcp_pm_init,
294
+    .validate    = bpf_mptcp_pm_validate,
295
+    .name        = "mptcp_pm_ops",
296
+    .cfi_stubs    = &__bpf_mptcp_pm_ops,
297
+};
298
+
299
static struct bpf_struct_ops bpf_mptcp_sched_ops;
300
static const struct btf_type *mptcp_sock_type, *mptcp_subflow_type __read_mostly;
301
-static u32 mptcp_sock_id, mptcp_subflow_id;
302
+static u32 mptcp_subflow_id;
303
304
static const struct bpf_func_proto *
305
bpf_mptcp_sched_get_func_proto(enum bpf_func_id func_id,
306
@@ -XXX,XX +XXX,XX @@ static int __init bpf_mptcp_kfunc_init(void)
307
    ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
308
                     &bpf_mptcp_sched_kfunc_set);
309
#ifdef CONFIG_BPF_JIT
310
+    ret = ret ?: register_bpf_struct_ops(&bpf_mptcp_pm_ops, mptcp_pm_ops);
311
    ret = ret ?: register_bpf_struct_ops(&bpf_mptcp_sched_ops, mptcp_sched_ops);
312
#endif
313
314
--
153
--
315
2.43.0
154
2.43.0
diff view generated by jsdifflib
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
This patch exports mptcp path manager helpers into BPF, adds these
3
Extract subflow_established() interface of the userspace PM from the
4
kfunc names into struct_ops kfunc_set and register this set with
4
handler of netlink command MPTCP_PM_CMD_SUBFLOW_CREATE
5
BPF_PROG_TYPE_STRUCT_OPS type.
5
6
mptcp_pm_nl_subflow_create_doit(),
7
8
only leave the code for obtaining msk through "info", parsing local address
9
entry and parsing remote address info in the handler.
10
11
This interface is invoked under holding the msk socket lock.
6
12
7
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
13
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
8
---
14
---
9
net/mptcp/bpf.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++
15
net/mptcp/pm_userspace.c | 54 +++++++++++++++++++++++++---------------
10
1 file changed, 96 insertions(+)
16
1 file changed, 34 insertions(+), 20 deletions(-)
11
17
12
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
18
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/net/mptcp/bpf.c
20
--- a/net/mptcp/pm_userspace.c
15
+++ b/net/mptcp/bpf.c
21
+++ b/net/mptcp/pm_userspace.c
16
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
17
#include <linux/btf_ids.h>
23
    return err;
18
#include <net/bpf_sk_storage.h>
19
#include "protocol.h"
20
+#include "mib.h"
21
22
#ifdef CONFIG_BPF_JIT
23
static struct bpf_struct_ops bpf_mptcp_pm_ops;
24
@@ -XXX,XX +XXX,XX @@ bpf_mptcp_subflow_ctx(const struct sock *sk)
25
    return NULL;
26
}
24
}
27
25
28
+__bpf_kfunc static struct sock *
26
+static int mptcp_userspace_pm_subflow_established(struct mptcp_sock *msk,
29
+bpf_mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow)
27
+                         struct mptcp_pm_param *param)
30
+{
28
+{
31
+    if (!subflow)
29
+    struct mptcp_pm_addr_entry *entry = &param->entry;
32
+        return NULL;
30
+    struct mptcp_addr_info *remote = &param->addr;
31
+    struct sock *sk = (struct sock *)msk;
32
+    struct mptcp_pm_local local;
33
+    int err;
33
+
34
+
34
+    return mptcp_subflow_tcp_sock(subflow);
35
+    err = mptcp_userspace_pm_append_new_local_addr(msk, entry, false);
35
+}
36
+    if (err < 0)
36
+
37
+        return err;
37
__bpf_kfunc static int
38
bpf_iter_mptcp_subflow_new(struct bpf_iter_mptcp_subflow *it,
39
             struct mptcp_sock *msk)
40
@@ -XXX,XX +XXX,XX @@ __bpf_kfunc static bool bpf_ipv4_is_private_10(__be32 addr)
41
    return ipv4_is_private_10(addr);
42
}
43
44
+__bpf_kfunc static void bpf_list_add_tail_rcu(struct list_head *new,
45
+                     struct list_head *head)
46
+{
47
+    list_add_tail_rcu(new, head);
48
+}
49
+
50
+__bpf_kfunc static void bpf_list_del_rcu(struct list_head *entry)
51
+{
52
+    list_del_rcu(entry);
53
+}
54
+
55
+__bpf_kfunc static struct mptcp_pm_addr_entry *
56
+bpf_sock_kmalloc_entry(struct sock *sk, int size, gfp_t priority)
57
+{
58
+    return sock_kmalloc(sk, size, priority);
59
+}
60
+
61
+__bpf_kfunc static void
62
+bpf_sock_kfree_entry(struct sock *sk, struct mptcp_pm_addr_entry *entry,
63
+         int size)
64
+{
65
+    sock_kfree_s(sk, entry, size);
66
+}
67
+
68
+__bpf_kfunc static void bpf_bitmap_zero(unsigned long *dst__ign, unsigned int nbits)
69
+{
70
+    bitmap_zero(dst__ign, nbits);
71
+}
72
+
73
+__bpf_kfunc static void bpf_set_bit(unsigned long nr, unsigned long *addr__ign)
74
+{
75
+    __set_bit(nr, addr__ign);
76
+}
77
+
78
+__bpf_kfunc static __u8 bpf_find_next_zero_bit(const unsigned long *addr__ign,
79
+                     unsigned long size, unsigned long offset)
80
+{
81
+    return find_next_zero_bit(addr__ign, size, offset);
82
+}
83
+
84
+__bpf_kfunc static int
85
+bpf_mptcp_subflow_connect(struct sock *sk,
86
+             const struct mptcp_pm_addr_entry *entry,
87
+             const struct mptcp_addr_info *remote)
88
+{
89
+    struct mptcp_pm_local local;
90
+
38
+
91
+    local.addr = entry->addr;
39
+    local.addr = entry->addr;
92
+    local.flags = entry->flags;
40
+    local.flags = entry->flags;
93
+    local.ifindex = entry->ifindex;
41
+    local.ifindex = entry->ifindex;
94
+
42
+
95
+    return __mptcp_subflow_connect(sk, &local, remote);
43
+    err = __mptcp_subflow_connect(sk, &local, remote);
44
+    spin_lock_bh(&msk->pm.lock);
45
+    if (err)
46
+        mptcp_userspace_pm_delete_local_addr(msk, entry);
47
+    else
48
+        msk->pm.subflows++;
49
+    spin_unlock_bh(&msk->pm.lock);
50
+
51
+    return err;
96
+}
52
+}
97
+
53
+
98
+__bpf_kfunc static struct net *bpf_sock_net(const struct sock *sk)
54
int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
99
+{
100
+    return sock_net(sk);
101
+}
102
+
103
+__bpf_kfunc static void BPF_MPTCP_INC_STATS(struct net *net,
104
+                     enum linux_mptcp_mib_field field)
105
+{
106
+    MPTCP_INC_STATS(net, field);
107
+}
108
+
109
__bpf_kfunc static bool bpf_mptcp_subflow_queues_empty(struct sock *sk)
110
{
55
{
111
    return tcp_rtx_queue_empty(sk);
56
    struct mptcp_pm_addr_entry entry = { 0 };
112
@@ -XXX,XX +XXX,XX @@ __bpf_kfunc_end_defs();
57
    struct mptcp_addr_info addr_r;
113
58
    struct nlattr *raddr, *laddr;
114
BTF_KFUNCS_START(bpf_mptcp_common_kfunc_ids)
59
-    struct mptcp_pm_local local;
115
BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx, KF_RET_NULL)
60
+    struct mptcp_pm_param param;
116
+BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock, KF_RET_NULL)
61
    struct mptcp_sock *msk;
117
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_new, KF_ITER_NEW | KF_TRUSTED_ARGS)
62
    int err = -EINVAL;
118
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_next, KF_ITER_NEXT | KF_RET_NULL)
63
    struct sock *sk;
119
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_destroy, KF_ITER_DESTROY)
64
@@ -XXX,XX +XXX,XX @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
120
@@ -XXX,XX +XXX,XX @@ BTF_ID_FLAGS(func, bpf_iter_mptcp_userspace_pm_addr_destroy, KF_ITER_DESTROY)
65
        goto create_err;
121
BTF_ID_FLAGS(func, bpf_spin_lock_bh)
66
    }
122
BTF_ID_FLAGS(func, bpf_spin_unlock_bh)
67
123
BTF_ID_FLAGS(func, bpf_ipv4_is_private_10)
68
-    err = mptcp_userspace_pm_append_new_local_addr(msk, &entry, false);
124
+BTF_ID_FLAGS(func, bpf_list_add_tail_rcu)
69
-    if (err < 0) {
125
+BTF_ID_FLAGS(func, bpf_list_del_rcu)
70
-        NL_SET_ERR_MSG_ATTR(info->extack, laddr,
126
+BTF_ID_FLAGS(func, bpf_sock_kmalloc_entry)
71
-                 "did not match address and id");
127
+BTF_ID_FLAGS(func, bpf_sock_kfree_entry)
72
-        goto create_err;
128
+BTF_ID_FLAGS(func, mptcp_pm_alloc_anno_list)
73
-    }
129
+BTF_ID_FLAGS(func, mptcp_pm_announce_addr)
74
-
130
+BTF_ID_FLAGS(func, mptcp_pm_nl_addr_send_ack, KF_SLEEPABLE)
75
-    local.addr = entry.addr;
131
+BTF_ID_FLAGS(func, bpf_bitmap_zero)
76
-    local.flags = entry.flags;
132
+BTF_ID_FLAGS(func, bpf_set_bit)
77
-    local.ifindex = entry.ifindex;
133
+BTF_ID_FLAGS(func, bpf_find_next_zero_bit)
78
-
134
+BTF_ID_FLAGS(func, mptcp_pm_remove_addr)
79
    lock_sock(sk);
135
+BTF_ID_FLAGS(func, mptcp_pm_remove_addr_entry, KF_SLEEPABLE)
80
-    err = __mptcp_subflow_connect(sk, &local, &addr_r);
136
+BTF_ID_FLAGS(func, bpf_mptcp_subflow_connect, KF_SLEEPABLE)
81
+    mptcp_pm_param_set_contexts(&param, &entry, &addr_r);
137
+BTF_ID_FLAGS(func, mptcp_subflow_shutdown, KF_SLEEPABLE)
82
+    err = msk->pm.ops && msk->pm.ops->subflow_established ?
138
+BTF_ID_FLAGS(func, mptcp_close_ssk, KF_SLEEPABLE)
83
+     msk->pm.ops->subflow_established(msk, &param) :
139
+BTF_ID_FLAGS(func, bpf_sock_net)
84
+     mptcp_userspace_pm_subflow_established(msk, &param);
140
+BTF_ID_FLAGS(func, BPF_MPTCP_INC_STATS)
85
    release_sock(sk);
141
+BTF_ID_FLAGS(func, mptcp_pm_nl_mp_prio_send_ack, KF_SLEEPABLE)
86
142
BTF_ID_FLAGS(func, bpf_mptcp_sock_acquire, KF_ACQUIRE | KF_RET_NULL)
87
    if (err)
143
BTF_ID_FLAGS(func, bpf_mptcp_sock_release, KF_RELEASE)
88
        GENL_SET_ERR_MSG_FMT(info, "connect error: %d", err);
144
BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids)
89
145
@@ -XXX,XX +XXX,XX @@ static int __init bpf_mptcp_kfunc_init(void)
90
-    spin_lock_bh(&msk->pm.lock);
146
    ret = register_btf_fmodret_id_set(&bpf_mptcp_fmodret_set);
91
-    if (err)
147
    ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCKOPT,
92
-        mptcp_userspace_pm_delete_local_addr(msk, &entry);
148
                     &bpf_mptcp_common_kfunc_set);
93
-    else
149
+    ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
94
-        msk->pm.subflows++;
150
+                     &bpf_mptcp_common_kfunc_set);
95
-    spin_unlock_bh(&msk->pm.lock);
151
    ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
96
-
152
                     &bpf_mptcp_sched_kfunc_set);
97
create_err:
153
#ifdef CONFIG_BPF_JIT
98
    sock_put(sk);
99
    return err;
100
@@ -XXX,XX +XXX,XX @@ int mptcp_userspace_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
101
static struct mptcp_pm_ops mptcp_userspace_pm = {
102
    .address_announced    = mptcp_userspace_pm_address_announced,
103
    .address_removed    = mptcp_userspace_pm_address_removed,
104
+    .subflow_established    = mptcp_userspace_pm_subflow_established,
105
    .get_local_id        = mptcp_userspace_pm_get_local_id,
106
    .get_priority        = mptcp_userspace_pm_get_priority,
107
    .type            = MPTCP_PM_TYPE_USERSPACE,
154
--
108
--
155
2.43.0
109
2.43.0
diff view generated by jsdifflib
1
From: Geliang Tang <tanggeliang@kylinos.cn>
1
From: Geliang Tang <tanggeliang@kylinos.cn>
2
2
3
This patch implements MPTCP path manager helpers mptcp_pm_copy_addr(),
3
Extract subflow_closed() interface of the userspace PM from the handler of
4
mptcp_pm_copy_entry(), ipv6_addr_equal(), mptcp_addresses_equal() and
4
netlink command MPTCP_PM_CMD_SUBFLOW_DESTROY
5
mptcp_pm_find_ssk() in BPF.
5
6
    mptcp_pm_nl_subflow_destroy_doit(),
7
8
only leave the code for obtaining msk through "info", parsing local address
9
entry and parsing remote address info in the handler.
10
11
This interface is invoked under holding the msk socket lock.
6
12
7
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
13
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
8
---
14
---
9
tools/testing/selftests/bpf/progs/mptcp_bpf.h | 110 ++++++++++++++++++
15
net/mptcp/pm_userspace.c | 45 ++++++++++++++++++++++++++--------------
10
1 file changed, 110 insertions(+)
16
1 file changed, 30 insertions(+), 15 deletions(-)
11
17
12
diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf.h b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
18
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/tools/testing/selftests/bpf/progs/mptcp_bpf.h
20
--- a/net/mptcp/pm_userspace.c
15
+++ b/tools/testing/selftests/bpf/progs/mptcp_bpf.h
21
+++ b/net/mptcp/pm_userspace.c
16
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
17
#define __MPTCP_BPF_H__
23
    return NULL;
18
24
}
19
#include "bpf_experimental.h"
25
20
+#include "bpf_tracing_net.h"
26
+static int mptcp_userspace_pm_subflow_closed(struct mptcp_sock *msk,
21
27
+                     struct mptcp_pm_param *param)
22
/* mptcp helpers from include/net/mptcp.h */
28
+{
23
#define MPTCP_SUBFLOWS_MAX 8
29
+    struct mptcp_pm_addr_entry *local = &param->entry;
24
@@ -XXX,XX +XXX,XX @@ static inline int list_is_head(const struct list_head *list,
30
+    struct mptcp_addr_info *remote = &param->addr;
25
#define mptcp_for_each_subflow(__msk, __subflow)            \
31
+    struct sock *ssk, *sk = (struct sock *)msk;
26
    list_for_each_entry(__subflow, &((__msk)->conn_list), node)
27
28
+/* errno macros from include/uapi/asm-generic/errno-base.h */
29
+#define    ESRCH        3    /* No such process */
30
+#define    ENOMEM        12    /* Out of Memory */
31
+#define    EINVAL        22    /* Invalid argument */
32
+
32
+
33
static __always_inline struct sock *
33
+    ssk = mptcp_nl_find_ssk(msk, &local->addr, remote);
34
mptcp_subflow_tcp_sock(const struct mptcp_subflow_context *subflow)
34
+    if (!ssk)
35
{
35
+        return -ESRCH;
36
@@ -XXX,XX +XXX,XX @@ extern void mptcp_subflow_set_scheduled(struct mptcp_subflow_context *subflow,
37
extern struct mptcp_subflow_context *
38
bpf_mptcp_subflow_ctx_by_pos(const struct mptcp_sched_data *data, unsigned int pos) __ksym;
39
40
+/* reimplemented BPF helpers */
41
+static __always_inline void
42
+mptcp_pm_copy_addr(struct mptcp_addr_info *dst,
43
+         struct mptcp_addr_info *src)
44
+{
45
+    dst->id = src->id;
46
+    dst->family = src->family;
47
+    dst->port = src->port;
48
+
36
+
49
+    if (src->family == AF_INET) {
37
+    spin_lock_bh(&msk->pm.lock);
50
+        dst->addr.s_addr = src->addr.s_addr;
38
+    mptcp_userspace_pm_delete_local_addr(msk, local);
51
+    } else if (src->family == AF_INET6) {
39
+    spin_unlock_bh(&msk->pm.lock);
52
+        dst->addr6.s6_addr32[0] = src->addr6.s6_addr32[0];
40
+    mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
53
+        dst->addr6.s6_addr32[1] = src->addr6.s6_addr32[1];
41
+    mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
54
+        dst->addr6.s6_addr32[2] = src->addr6.s6_addr32[2];
42
+    MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
55
+        dst->addr6.s6_addr32[3] = src->addr6.s6_addr32[3];
43
+
56
+    }
44
+    return 0;
57
+}
45
+}
58
+
46
+
59
+static __always_inline void
47
int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info)
60
+mptcp_pm_copy_entry(struct mptcp_pm_addr_entry *dst,
48
{
61
+         struct mptcp_pm_addr_entry *src)
49
    struct mptcp_pm_addr_entry addr_l;
62
+{
50
    struct mptcp_addr_info addr_r;
63
+    mptcp_pm_copy_addr(&dst->addr, &src->addr);
51
    struct nlattr *raddr, *laddr;
64
+
52
+    struct mptcp_pm_param param;
65
+    dst->flags = src->flags;
53
    struct mptcp_sock *msk;
66
+    dst->ifindex = src->ifindex;
54
-    struct sock *sk, *ssk;
67
+}
55
    int err = -EINVAL;
68
+
56
+    struct sock *sk;
69
+#define inet_sk(ptr) container_of(ptr, struct inet_sock, sk)
57
70
+
58
    if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR) ||
71
+#define ipv6_addr_equal(a, b)    ((a).s6_addr32[0] == (b).s6_addr32[0] &&    \
59
     GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR_REMOTE))
72
+                 (a).s6_addr32[1] == (b).s6_addr32[1] &&    \
60
@@ -XXX,XX +XXX,XX @@ int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info
73
+                 (a).s6_addr32[2] == (b).s6_addr32[2] &&    \
61
    }
74
+                 (a).s6_addr32[3] == (b).s6_addr32[3])
62
75
+
63
    lock_sock(sk);
76
+static __always_inline bool
64
-    ssk = mptcp_nl_find_ssk(msk, &addr_l.addr, &addr_r);
77
+mptcp_addresses_equal(const struct mptcp_addr_info *a,
65
-    if (!ssk) {
78
+         const struct mptcp_addr_info *b, bool use_port)
66
-        GENL_SET_ERR_MSG(info, "subflow not found");
79
+{
67
-        err = -ESRCH;
80
+    bool addr_equals = false;
68
-        goto release_sock;
81
+
69
-    }
82
+    if (a->family == b->family) {
70
-
83
+        if (a->family == AF_INET)
71
-    spin_lock_bh(&msk->pm.lock);
84
+            addr_equals = a->addr.s_addr == b->addr.s_addr;
72
-    mptcp_userspace_pm_delete_local_addr(msk, &addr_l);
85
+        else
73
-    spin_unlock_bh(&msk->pm.lock);
86
+            addr_equals = ipv6_addr_equal(a->addr6, b->addr6);
74
-    mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
87
+    }
75
-    mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
88
+
76
-    MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
89
+    if (!addr_equals)
77
-release_sock:
90
+        return false;
78
+    mptcp_pm_param_set_contexts(&param, &addr_l, &addr_r);
91
+    if (!use_port)
79
+    err = msk->pm.ops && msk->pm.ops->subflow_closed ?
92
+        return true;
80
+     msk->pm.ops->subflow_closed(msk, &param) :
93
+
81
+     mptcp_userspace_pm_subflow_closed(msk, &param);
94
+    return a->port == b->port;
82
    release_sock(sk);
95
+}
83
+    if (err)
96
+
84
+        GENL_SET_ERR_MSG(info, "subflow not found");
97
+static __always_inline struct sock *
85
98
+mptcp_pm_find_ssk(struct mptcp_sock *msk,
86
destroy_err:
99
+         const struct mptcp_addr_info *local,
87
    sock_put(sk);
100
+         const struct mptcp_addr_info *remote)
88
@@ -XXX,XX +XXX,XX @@ static struct mptcp_pm_ops mptcp_userspace_pm = {
101
+{
89
    .address_announced    = mptcp_userspace_pm_address_announced,
102
+    struct mptcp_subflow_context *subflow;
90
    .address_removed    = mptcp_userspace_pm_address_removed,
103
+
91
    .subflow_established    = mptcp_userspace_pm_subflow_established,
104
+    if (local->family != remote->family)
92
+    .subflow_closed        = mptcp_userspace_pm_subflow_closed,
105
+        return NULL;
93
    .get_local_id        = mptcp_userspace_pm_get_local_id,
106
+
94
    .get_priority        = mptcp_userspace_pm_get_priority,
107
+    bpf_for_each(mptcp_subflow, subflow, msk) {
95
    .type            = MPTCP_PM_TYPE_USERSPACE,
108
+        const struct inet_sock *issk;
109
+        struct sock *ssk;
110
+
111
+        ssk = bpf_mptcp_subflow_tcp_sock(subflow);
112
+        if (!ssk)
113
+            continue;
114
+
115
+        if (local->family != ssk->sk_family)
116
+            continue;
117
+
118
+        issk = bpf_core_cast(inet_sk(ssk), struct inet_sock);
119
+
120
+        switch (ssk->sk_family) {
121
+        case AF_INET:
122
+            if (issk->inet_saddr != local->addr.s_addr ||
123
+             issk->inet_daddr != remote->addr.s_addr)
124
+                continue;
125
+            break;
126
+        case AF_INET6: {
127
+            if (!ipv6_addr_equal(local->addr6, issk->pinet6->saddr) ||
128
+             !ipv6_addr_equal(remote->addr6, ssk->sk_v6_daddr))
129
+                continue;
130
+            break;
131
+        }
132
+        default:
133
+            continue;
134
+        }
135
+
136
+        if (issk->inet_sport == local->port &&
137
+         issk->inet_dport == remote->port)
138
+            return ssk;
139
+    }
140
+
141
+    return NULL;
142
+}
143
+
144
#endif
145
--
96
--
146
2.43.0
97
2.43.0
diff view generated by jsdifflib