]>
Commit | Line | Data |
---|---|---|
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 | ||
15 | int mptcp_pm_announce_addr(struct mptcp_sock *msk, | |
6a6c05a8 | 16 | const struct mptcp_addr_info *addr, |
f7efc777 | 17 | bool echo) |
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); | |
f7efc777 | 36 | if (addr->port) |
0f5c9e3f | 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 | 42 | int 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); |
b46a0238 | 56 | mptcp_pm_nl_addr_send_ack(msk); |
b6c08380 | 57 | return 0; |
1b1c7a0e PK |
58 | } |
59 | ||
ddd14bb8 | 60 | int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list) |
1b1c7a0e | 61 | { |
ddd14bb8 | 62 | pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr); |
0ee4261a GT |
63 | |
64 | spin_lock_bh(&msk->pm.lock); | |
ddd14bb8 | 65 | mptcp_pm_nl_rm_subflow_received(msk, rm_list); |
0ee4261a GT |
66 | spin_unlock_bh(&msk->pm.lock); |
67 | return 0; | |
1b1c7a0e PK |
68 | } |
69 | ||
70 | /* path manager event handlers */ | |
71 | ||
6c714f1b | 72 | void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side) |
1b1c7a0e PK |
73 | { |
74 | struct mptcp_pm_data *pm = &msk->pm; | |
75 | ||
76 | pr_debug("msk=%p, token=%u side=%d", msk, msk->token, server_side); | |
77 | ||
78 | WRITE_ONCE(pm->server_side, server_side); | |
b911c97c | 79 | mptcp_event(MPTCP_EVENT_CREATED, msk, ssk, GFP_ATOMIC); |
1b1c7a0e PK |
80 | } |
81 | ||
82 | bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk) | |
83 | { | |
926bdeab | 84 | struct mptcp_pm_data *pm = &msk->pm; |
a914e586 | 85 | unsigned int subflows_max; |
f58f065a | 86 | int ret = 0; |
926bdeab | 87 | |
a914e586 GT |
88 | subflows_max = mptcp_pm_get_subflows_max(msk); |
89 | ||
926bdeab | 90 | pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows, |
a914e586 | 91 | subflows_max, READ_ONCE(pm->accept_subflow)); |
926bdeab PK |
92 | |
93 | /* try to avoid acquiring the lock below */ | |
94 | if (!READ_ONCE(pm->accept_subflow)) | |
95 | return false; | |
96 | ||
97 | spin_lock_bh(&pm->lock); | |
f58f065a | 98 | if (READ_ONCE(pm->accept_subflow)) { |
a914e586 GT |
99 | ret = pm->subflows < subflows_max; |
100 | if (ret && ++pm->subflows == subflows_max) | |
f58f065a GT |
101 | WRITE_ONCE(pm->accept_subflow, false); |
102 | } | |
926bdeab PK |
103 | spin_unlock_bh(&pm->lock); |
104 | ||
105 | return ret; | |
106 | } | |
107 | ||
108 | /* return true if the new status bit is currently cleared, that is, this event | |
109 | * can be server, eventually by an already scheduled work | |
110 | */ | |
111 | static bool mptcp_pm_schedule_work(struct mptcp_sock *msk, | |
112 | enum mptcp_pm_status new_status) | |
113 | { | |
114 | pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status, | |
115 | BIT(new_status)); | |
116 | if (msk->pm.status & BIT(new_status)) | |
117 | return false; | |
118 | ||
119 | msk->pm.status |= BIT(new_status); | |
ba8f48f7 | 120 | mptcp_schedule_work((struct sock *)msk); |
926bdeab | 121 | return true; |
1b1c7a0e PK |
122 | } |
123 | ||
6c714f1b | 124 | void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk, gfp_t gfp) |
1b1c7a0e | 125 | { |
926bdeab | 126 | struct mptcp_pm_data *pm = &msk->pm; |
b911c97c | 127 | bool announce = false; |
926bdeab | 128 | |
1b1c7a0e | 129 | pr_debug("msk=%p", msk); |
926bdeab | 130 | |
926bdeab PK |
131 | spin_lock_bh(&pm->lock); |
132 | ||
5b950ff4 PA |
133 | /* mptcp_pm_fully_established() can be invoked by multiple |
134 | * racing paths - accept() and check_fully_established() | |
135 | * be sure to serve this event only once. | |
136 | */ | |
137 | if (READ_ONCE(pm->work_pending) && | |
138 | !(msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED))) | |
926bdeab PK |
139 | mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED); |
140 | ||
b911c97c FW |
141 | if ((msk->pm.status & BIT(MPTCP_PM_ALREADY_ESTABLISHED)) == 0) |
142 | announce = true; | |
143 | ||
144 | msk->pm.status |= BIT(MPTCP_PM_ALREADY_ESTABLISHED); | |
926bdeab | 145 | spin_unlock_bh(&pm->lock); |
b911c97c FW |
146 | |
147 | if (announce) | |
148 | mptcp_event(MPTCP_EVENT_ESTABLISHED, msk, ssk, gfp); | |
1b1c7a0e PK |
149 | } |
150 | ||
151 | void mptcp_pm_connection_closed(struct mptcp_sock *msk) | |
152 | { | |
153 | pr_debug("msk=%p", msk); | |
154 | } | |
155 | ||
62535200 | 156 | void mptcp_pm_subflow_established(struct mptcp_sock *msk) |
1b1c7a0e | 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 | ||
173 | void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id) | |
174 | { | |
175 | pr_debug("msk=%p", msk); | |
176 | } | |
177 | ||
178 | void 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)) { |
f7efc777 | 191 | mptcp_pm_announce_addr(msk, addr, true); |
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 | ||
557963c3 GT |
200 | void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk, |
201 | struct mptcp_addr_info *addr) | |
202 | { | |
203 | struct mptcp_pm_data *pm = &msk->pm; | |
204 | ||
205 | pr_debug("msk=%p", msk); | |
206 | ||
207 | spin_lock_bh(&pm->lock); | |
208 | ||
209 | if (mptcp_lookup_anno_list_by_saddr(msk, addr) && READ_ONCE(pm->work_pending)) | |
210 | mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED); | |
211 | ||
212 | spin_unlock_bh(&pm->lock); | |
213 | } | |
214 | ||
84dfe367 GT |
215 | void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk) |
216 | { | |
b5a7acd3 | 217 | if (!mptcp_pm_should_add_signal(msk)) |
84dfe367 GT |
218 | return; |
219 | ||
220 | mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_SEND_ACK); | |
1b1c7a0e PK |
221 | } |
222 | ||
5c4a824d GT |
223 | void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, |
224 | const struct mptcp_rm_list *rm_list) | |
d0876b22 GT |
225 | { |
226 | struct mptcp_pm_data *pm = &msk->pm; | |
5c4a824d | 227 | u8 i; |
d0876b22 | 228 | |
5c4a824d | 229 | pr_debug("msk=%p remote_ids_nr=%d", msk, rm_list->nr); |
d0876b22 | 230 | |
5c4a824d GT |
231 | for (i = 0; i < rm_list->nr; i++) |
232 | mptcp_event_addr_removed(msk, rm_list->ids[i]); | |
b911c97c | 233 | |
d0876b22 GT |
234 | spin_lock_bh(&pm->lock); |
235 | mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED); | |
b5c55f33 | 236 | pm->rm_list_rx = *rm_list; |
d0876b22 GT |
237 | spin_unlock_bh(&pm->lock); |
238 | } | |
239 | ||
40453a5c GT |
240 | void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup) |
241 | { | |
242 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | |
243 | ||
244 | pr_debug("subflow->backup=%d, bkup=%d\n", subflow->backup, bkup); | |
245 | subflow->backup = bkup; | |
b911c97c FW |
246 | |
247 | mptcp_event(MPTCP_EVENT_SUB_PRIORITY, mptcp_sk(subflow->conn), sk, GFP_ATOMIC); | |
40453a5c GT |
248 | } |
249 | ||
1b1c7a0e PK |
250 | /* path manager helpers */ |
251 | ||
f643b803 | 252 | bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining, |
4a2777a8 | 253 | struct mptcp_addr_info *saddr, bool *echo, bool *port) |
1b1c7a0e | 254 | { |
926bdeab PK |
255 | int ret = false; |
256 | ||
257 | spin_lock_bh(&msk->pm.lock); | |
258 | ||
259 | /* double check after the lock is acquired */ | |
f643b803 | 260 | if (!mptcp_pm_should_add_signal(msk)) |
926bdeab PK |
261 | goto out_unlock; |
262 | ||
d91d322a | 263 | *echo = mptcp_pm_should_add_signal_echo(msk); |
4a2777a8 | 264 | *port = mptcp_pm_should_add_signal_port(msk); |
456afe01 | 265 | |
4a2777a8 | 266 | if (remaining < mptcp_add_addr_len(msk->pm.local.family, *echo, *port)) |
926bdeab PK |
267 | goto out_unlock; |
268 | ||
269 | *saddr = msk->pm.local; | |
13ad9f01 | 270 | WRITE_ONCE(msk->pm.addr_signal, 0); |
926bdeab PK |
271 | ret = true; |
272 | ||
273 | out_unlock: | |
274 | spin_unlock_bh(&msk->pm.lock); | |
275 | return ret; | |
1b1c7a0e PK |
276 | } |
277 | ||
5cb104ae | 278 | bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, |
6445e17a | 279 | struct mptcp_rm_list *rm_list) |
5cb104ae | 280 | { |
cbde2787 | 281 | int ret = false, len; |
5cb104ae GT |
282 | |
283 | spin_lock_bh(&msk->pm.lock); | |
284 | ||
285 | /* double check after the lock is acquired */ | |
286 | if (!mptcp_pm_should_rm_signal(msk)) | |
287 | goto out_unlock; | |
288 | ||
cbde2787 GT |
289 | len = mptcp_rm_addr_len(&msk->pm.rm_list_tx); |
290 | if (len < 0) { | |
291 | WRITE_ONCE(msk->pm.addr_signal, 0); | |
292 | goto out_unlock; | |
293 | } | |
294 | if (remaining < len) | |
5cb104ae GT |
295 | goto out_unlock; |
296 | ||
cbde2787 | 297 | *rm_list = msk->pm.rm_list_tx; |
13ad9f01 | 298 | WRITE_ONCE(msk->pm.addr_signal, 0); |
5cb104ae GT |
299 | ret = true; |
300 | ||
301 | out_unlock: | |
302 | spin_unlock_bh(&msk->pm.lock); | |
303 | return ret; | |
304 | } | |
305 | ||
1b1c7a0e PK |
306 | int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc) |
307 | { | |
01cacb00 | 308 | return mptcp_pm_nl_get_local_id(msk, skc); |
1b1c7a0e PK |
309 | } |
310 | ||
1b1c7a0e PK |
311 | void mptcp_pm_data_init(struct mptcp_sock *msk) |
312 | { | |
313 | msk->pm.add_addr_signaled = 0; | |
314 | msk->pm.add_addr_accepted = 0; | |
315 | msk->pm.local_addr_used = 0; | |
316 | msk->pm.subflows = 0; | |
cbde2787 | 317 | msk->pm.rm_list_tx.nr = 0; |
b5c55f33 | 318 | msk->pm.rm_list_rx.nr = 0; |
1b1c7a0e | 319 | WRITE_ONCE(msk->pm.work_pending, false); |
13ad9f01 | 320 | WRITE_ONCE(msk->pm.addr_signal, 0); |
1b1c7a0e PK |
321 | WRITE_ONCE(msk->pm.accept_addr, false); |
322 | WRITE_ONCE(msk->pm.accept_subflow, false); | |
df377be3 | 323 | WRITE_ONCE(msk->pm.remote_deny_join_id0, false); |
1b1c7a0e PK |
324 | msk->pm.status = 0; |
325 | ||
326 | spin_lock_init(&msk->pm.lock); | |
b6c08380 | 327 | INIT_LIST_HEAD(&msk->pm.anno_list); |
01cacb00 PA |
328 | |
329 | mptcp_pm_nl_data_init(msk); | |
1b1c7a0e PK |
330 | } |
331 | ||
d39dceca | 332 | void __init mptcp_pm_init(void) |
1b1c7a0e | 333 | { |
01cacb00 | 334 | mptcp_pm_nl_init(); |
1b1c7a0e | 335 | } |