]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - net/mptcp/pm.c
mptcp: add rm_list in mptcp_options_received
[mirror_ubuntu-jammy-kernel.git] / net / mptcp / pm.c
CommitLineData
1b1c7a0e
PK
1// SPDX-License-Identifier: GPL-2.0
2/* Multipath TCP
3 *
4 * Copyright (c) 2019, Intel Corporation.
5 */
c85adced
GT
6#define pr_fmt(fmt) "MPTCP: " fmt
7
1b1c7a0e
PK
8#include <linux/kernel.h>
9#include <net/tcp.h>
10#include <net/mptcp.h>
11#include "protocol.h"
12
1b1c7a0e
PK
13/* path manager command handlers */
14
15int mptcp_pm_announce_addr(struct mptcp_sock *msk,
6a6c05a8 16 const struct mptcp_addr_info *addr,
0f5c9e3f 17 bool echo, bool port)
1b1c7a0e 18{
13ad9f01 19 u8 add_addr = READ_ONCE(msk->pm.addr_signal);
d91d322a 20
926bdeab
PK
21 pr_debug("msk=%p, local_id=%d", msk, addr->id);
22
3abc05d9
FW
23 lockdep_assert_held(&msk->pm.lock);
24
42842a42
GT
25 if (add_addr) {
26 pr_warn("addr_signal error, add_addr=%d", add_addr);
27 return -EINVAL;
28 }
29
926bdeab 30 msk->pm.local = *addr;
d91d322a
GT
31 add_addr |= BIT(MPTCP_ADD_ADDR_SIGNAL);
32 if (echo)
33 add_addr |= BIT(MPTCP_ADD_ADDR_ECHO);
84dfe367
GT
34 if (addr->family == AF_INET6)
35 add_addr |= BIT(MPTCP_ADD_ADDR_IPV6);
0f5c9e3f
GT
36 if (port)
37 add_addr |= BIT(MPTCP_ADD_ADDR_PORT);
13ad9f01 38 WRITE_ONCE(msk->pm.addr_signal, add_addr);
926bdeab 39 return 0;
1b1c7a0e
PK
40}
41
cbde2787 42int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list)
1b1c7a0e 43{
13ad9f01 44 u8 rm_addr = READ_ONCE(msk->pm.addr_signal);
42842a42 45
cbde2787 46 pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);
b6c08380 47
42842a42
GT
48 if (rm_addr) {
49 pr_warn("addr_signal error, rm_addr=%d", rm_addr);
50 return -EINVAL;
51 }
52
cbde2787 53 msk->pm.rm_list_tx = *rm_list;
42842a42 54 rm_addr |= BIT(MPTCP_RM_ADDR_SIGNAL);
13ad9f01 55 WRITE_ONCE(msk->pm.addr_signal, rm_addr);
b6c08380 56 return 0;
1b1c7a0e
PK
57}
58
0ee4261a 59int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id)
1b1c7a0e 60{
0ee4261a
GT
61 pr_debug("msk=%p, local_id=%d", msk, local_id);
62
63 spin_lock_bh(&msk->pm.lock);
64 mptcp_pm_nl_rm_subflow_received(msk, local_id);
65 spin_unlock_bh(&msk->pm.lock);
66 return 0;
1b1c7a0e
PK
67}
68
69/* path manager event handlers */
70
6c714f1b 71void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side)
1b1c7a0e
PK
72{
73 struct mptcp_pm_data *pm = &msk->pm;
74
75 pr_debug("msk=%p, token=%u side=%d", msk, msk->token, server_side);
76
77 WRITE_ONCE(pm->server_side, server_side);
b911c97c 78 mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC);
1b1c7a0e
PK
79}
80
81bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
82{
926bdeab 83 struct mptcp_pm_data *pm = &msk->pm;
a914e586 84 unsigned int subflows_max;
f58f065a 85 int ret = 0;
926bdeab 86
a914e586
GT
87 subflows_max = mptcp_pm_get_subflows_max(msk);
88
926bdeab 89 pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
a914e586 90 subflows_max, READ_ONCE(pm->accept_subflow));
926bdeab
PK
91
92 /* try to avoid acquiring the lock below */
93 if (!READ_ONCE(pm->accept_subflow))
94 return false;
95
96 spin_lock_bh(&pm->lock);
f58f065a 97 if (READ_ONCE(pm->accept_subflow)) {
a914e586
GT
98 ret = pm->subflows < subflows_max;
99 if (ret && ++pm->subflows == subflows_max)
f58f065a
GT
100 WRITE_ONCE(pm->accept_subflow, false);
101 }
926bdeab
PK
102 spin_unlock_bh(&pm->lock);
103
104 return ret;
105}
106
107/* return true if the new status bit is currently cleared, that is, this event
108 * can be server, eventually by an already scheduled work
109 */
110static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
111 enum mptcp_pm_status new_status)
112{
113 pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status,
114 BIT(new_status));
115 if (msk->pm.status & BIT(new_status))
116 return false;
117
118 msk->pm.status |= BIT(new_status);
ba8f48f7 119 mptcp_schedule_work((struct sock *)msk);
926bdeab 120 return true;
1b1c7a0e
PK
121}
122
6c714f1b 123void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk, gfp_t gfp)
1b1c7a0e 124{
926bdeab 125 struct mptcp_pm_data *pm = &msk->pm;
b911c97c 126 bool announce = false;
926bdeab 127
1b1c7a0e 128 pr_debug("msk=%p", msk);
926bdeab 129
926bdeab
PK
130 spin_lock_bh(&pm->lock);
131
5b950ff4
PA
132 /* mptcp_pm_fully_established() can be invoked by multiple
133 * racing paths - accept() and check_fully_established()
134 * be sure to serve this event only once.
135 */
136 if (READ_ONCE(pm->work_pending) &&
137 !(msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)))
926bdeab
PK
138 mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
139
b911c97c
FW
140 if ((msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)) == 0)
141 announce = true;
142
143 msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED);
926bdeab 144 spin_unlock_bh(&pm->lock);
b911c97c
FW
145
146 if (announce)
147 mptcp_event(MPTCP_EVENT_ESTABLISHED, msk, ssk, gfp);
1b1c7a0e
PK
148}
149
150void mptcp_pm_connection_closed(struct mptcp_sock *msk)
151{
152 pr_debug("msk=%p", msk);
153}
154
155void mptcp_pm_subflow_established(struct mptcp_sock *msk,
156 struct mptcp_subflow_context *subflow)
157{
926bdeab
PK
158 struct mptcp_pm_data *pm = &msk->pm;
159
1b1c7a0e 160 pr_debug("msk=%p", msk);
926bdeab
PK
161
162 if (!READ_ONCE(pm->work_pending))
163 return;
164
165 spin_lock_bh(&pm->lock);
166
167 if (READ_ONCE(pm->work_pending))
168 mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
169
170 spin_unlock_bh(&pm->lock);
1b1c7a0e
PK
171}
172
173void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id)
174{
175 pr_debug("msk=%p", msk);
176}
177
178void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
179 const struct mptcp_addr_info *addr)
180{
926bdeab
PK
181 struct mptcp_pm_data *pm = &msk->pm;
182
183 pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
184 READ_ONCE(pm->accept_addr));
185
b911c97c
FW
186 mptcp_event_addr_announced(msk, addr);
187
926bdeab
PK
188 spin_lock_bh(&pm->lock);
189
84dfe367 190 if (!READ_ONCE(pm->accept_addr)) {
0f5c9e3f 191 mptcp_pm_announce_addr(msk, addr, true, addr->port);
84dfe367
GT
192 mptcp_pm_add_addr_send_ack(msk);
193 } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
926bdeab 194 pm->remote = *addr;
84dfe367 195 }
926bdeab
PK
196
197 spin_unlock_bh(&pm->lock);
84dfe367
GT
198}
199
200void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
201{
b5a7acd3 202 if (!mptcp_pm_should_add_signal(msk))
84dfe367
GT
203 return;
204
205 mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_SEND_ACK);
1b1c7a0e
PK
206}
207
5c4a824d
GT
208void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
209 const struct mptcp_rm_list *rm_list)
d0876b22
GT
210{
211 struct mptcp_pm_data *pm = &msk->pm;
5c4a824d 212 u8 i;
d0876b22 213
5c4a824d 214 pr_debug("msk=%p remote_ids_nr=%d", msk, rm_list->nr);
d0876b22 215
5c4a824d
GT
216 for (i = 0; i < rm_list->nr; i++)
217 mptcp_event_addr_removed(msk, rm_list->ids[i]);
b911c97c 218
d0876b22
GT
219 spin_lock_bh(&pm->lock);
220 mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
5c4a824d 221 pm->rm_id = rm_list->ids[0];
d0876b22
GT
222 spin_unlock_bh(&pm->lock);
223}
224
40453a5c
GT
225void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup)
226{
227 struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
228
229 pr_debug("subflow->backup=%d, bkup=%d\n", subflow->backup, bkup);
230 subflow->backup = bkup;
b911c97c
FW
231
232 mptcp_event(MPTCP_EVENT_SUB_PRIORITY, mptcp_sk(subflow->conn), sk, GFP_ATOMIC);
40453a5c
GT
233}
234
1b1c7a0e
PK
235/* path manager helpers */
236
f643b803 237bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
4a2777a8 238 struct mptcp_addr_info *saddr, bool *echo, bool *port)
1b1c7a0e 239{
926bdeab
PK
240 int ret = false;
241
242 spin_lock_bh(&msk->pm.lock);
243
244 /* double check after the lock is acquired */
f643b803 245 if (!mptcp_pm_should_add_signal(msk))
926bdeab
PK
246 goto out_unlock;
247
d91d322a 248 *echo = mptcp_pm_should_add_signal_echo(msk);
4a2777a8 249 *port = mptcp_pm_should_add_signal_port(msk);
456afe01 250
4a2777a8 251 if (remaining < mptcp_add_addr_len(msk->pm.local.family, *echo, *port))
926bdeab
PK
252 goto out_unlock;
253
254 *saddr = msk->pm.local;
13ad9f01 255 WRITE_ONCE(msk->pm.addr_signal, 0);
926bdeab
PK
256 ret = true;
257
258out_unlock:
259 spin_unlock_bh(&msk->pm.lock);
260 return ret;
1b1c7a0e
PK
261}
262
5cb104ae 263bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
6445e17a 264 struct mptcp_rm_list *rm_list)
5cb104ae 265{
cbde2787 266 int ret = false, len;
5cb104ae
GT
267
268 spin_lock_bh(&msk->pm.lock);
269
270 /* double check after the lock is acquired */
271 if (!mptcp_pm_should_rm_signal(msk))
272 goto out_unlock;
273
cbde2787
GT
274 len = mptcp_rm_addr_len(&msk->pm.rm_list_tx);
275 if (len < 0) {
276 WRITE_ONCE(msk->pm.addr_signal, 0);
277 goto out_unlock;
278 }
279 if (remaining < len)
5cb104ae
GT
280 goto out_unlock;
281
cbde2787 282 *rm_list = msk->pm.rm_list_tx;
13ad9f01 283 WRITE_ONCE(msk->pm.addr_signal, 0);
5cb104ae
GT
284 ret = true;
285
286out_unlock:
287 spin_unlock_bh(&msk->pm.lock);
288 return ret;
289}
290
1b1c7a0e
PK
291int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
292{
01cacb00 293 return mptcp_pm_nl_get_local_id(msk, skc);
1b1c7a0e
PK
294}
295
1b1c7a0e
PK
296void mptcp_pm_data_init(struct mptcp_sock *msk)
297{
298 msk->pm.add_addr_signaled = 0;
299 msk->pm.add_addr_accepted = 0;
300 msk->pm.local_addr_used = 0;
301 msk->pm.subflows = 0;
cbde2787 302 msk->pm.rm_list_tx.nr = 0;
1b1c7a0e 303 WRITE_ONCE(msk->pm.work_pending, false);
13ad9f01 304 WRITE_ONCE(msk->pm.addr_signal, 0);
1b1c7a0e
PK
305 WRITE_ONCE(msk->pm.accept_addr, false);
306 WRITE_ONCE(msk->pm.accept_subflow, false);
307 msk->pm.status = 0;
308
309 spin_lock_init(&msk->pm.lock);
b6c08380 310 INIT_LIST_HEAD(&msk->pm.anno_list);
01cacb00
PA
311
312 mptcp_pm_nl_data_init(msk);
1b1c7a0e
PK
313}
314
d39dceca 315void __init mptcp_pm_init(void)
1b1c7a0e 316{
01cacb00 317 mptcp_pm_nl_init();
1b1c7a0e 318}