1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Multipath TCP
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 2019, Intel Corporation.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun #define pr_fmt(fmt) "MPTCP: " fmt
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <net/tcp.h>
10*4882a593Smuzhiyun #include <net/mptcp.h>
11*4882a593Smuzhiyun #include "protocol.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /* path manager command handlers */
14*4882a593Smuzhiyun
mptcp_pm_announce_addr(struct mptcp_sock * msk,const struct mptcp_addr_info * addr,bool echo)15*4882a593Smuzhiyun int mptcp_pm_announce_addr(struct mptcp_sock *msk,
16*4882a593Smuzhiyun const struct mptcp_addr_info *addr,
17*4882a593Smuzhiyun bool echo)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun pr_debug("msk=%p, local_id=%d", msk, addr->id);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun msk->pm.local = *addr;
22*4882a593Smuzhiyun WRITE_ONCE(msk->pm.add_addr_echo, echo);
23*4882a593Smuzhiyun WRITE_ONCE(msk->pm.add_addr_signal, true);
24*4882a593Smuzhiyun return 0;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
mptcp_pm_remove_addr(struct mptcp_sock * msk,u8 local_id)27*4882a593Smuzhiyun int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun pr_debug("msk=%p, local_id=%d", msk, local_id);
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun msk->pm.rm_id = local_id;
32*4882a593Smuzhiyun WRITE_ONCE(msk->pm.rm_addr_signal, true);
33*4882a593Smuzhiyun return 0;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
mptcp_pm_remove_subflow(struct mptcp_sock * msk,u8 local_id)36*4882a593Smuzhiyun int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun pr_debug("msk=%p, local_id=%d", msk, local_id);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun spin_lock_bh(&msk->pm.lock);
41*4882a593Smuzhiyun mptcp_pm_nl_rm_subflow_received(msk, local_id);
42*4882a593Smuzhiyun spin_unlock_bh(&msk->pm.lock);
43*4882a593Smuzhiyun return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* path manager event handlers */
47*4882a593Smuzhiyun
mptcp_pm_new_connection(struct mptcp_sock * msk,int server_side)48*4882a593Smuzhiyun void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun pr_debug("msk=%p, token=%u side=%d", msk, msk->token, server_side);
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun WRITE_ONCE(pm->server_side, server_side);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
mptcp_pm_allow_new_subflow(struct mptcp_sock * msk)57*4882a593Smuzhiyun bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
60*4882a593Smuzhiyun int ret = 0;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun pr_debug("msk=%p subflows=%d max=%d allow=%d", msk, pm->subflows,
63*4882a593Smuzhiyun pm->subflows_max, READ_ONCE(pm->accept_subflow));
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* try to avoid acquiring the lock below */
66*4882a593Smuzhiyun if (!READ_ONCE(pm->accept_subflow))
67*4882a593Smuzhiyun return false;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun spin_lock_bh(&pm->lock);
70*4882a593Smuzhiyun if (READ_ONCE(pm->accept_subflow)) {
71*4882a593Smuzhiyun ret = pm->subflows < pm->subflows_max;
72*4882a593Smuzhiyun if (ret && ++pm->subflows == pm->subflows_max)
73*4882a593Smuzhiyun WRITE_ONCE(pm->accept_subflow, false);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun spin_unlock_bh(&pm->lock);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun return ret;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* return true if the new status bit is currently cleared, that is, this event
81*4882a593Smuzhiyun * can be server, eventually by an already scheduled work
82*4882a593Smuzhiyun */
mptcp_pm_schedule_work(struct mptcp_sock * msk,enum mptcp_pm_status new_status)83*4882a593Smuzhiyun static bool mptcp_pm_schedule_work(struct mptcp_sock *msk,
84*4882a593Smuzhiyun enum mptcp_pm_status new_status)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun pr_debug("msk=%p status=%x new=%lx", msk, msk->pm.status,
87*4882a593Smuzhiyun BIT(new_status));
88*4882a593Smuzhiyun if (msk->pm.status & BIT(new_status))
89*4882a593Smuzhiyun return false;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun msk->pm.status |= BIT(new_status);
92*4882a593Smuzhiyun if (schedule_work(&msk->work))
93*4882a593Smuzhiyun sock_hold((struct sock *)msk);
94*4882a593Smuzhiyun return true;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
mptcp_pm_fully_established(struct mptcp_sock * msk)97*4882a593Smuzhiyun void mptcp_pm_fully_established(struct mptcp_sock *msk)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun pr_debug("msk=%p", msk);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* try to avoid acquiring the lock below */
104*4882a593Smuzhiyun if (!READ_ONCE(pm->work_pending))
105*4882a593Smuzhiyun return;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun spin_lock_bh(&pm->lock);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun if (READ_ONCE(pm->work_pending))
110*4882a593Smuzhiyun mptcp_pm_schedule_work(msk, MPTCP_PM_ESTABLISHED);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun spin_unlock_bh(&pm->lock);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
mptcp_pm_connection_closed(struct mptcp_sock * msk)115*4882a593Smuzhiyun void mptcp_pm_connection_closed(struct mptcp_sock *msk)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun pr_debug("msk=%p", msk);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
mptcp_pm_subflow_established(struct mptcp_sock * msk,struct mptcp_subflow_context * subflow)120*4882a593Smuzhiyun void mptcp_pm_subflow_established(struct mptcp_sock *msk,
121*4882a593Smuzhiyun struct mptcp_subflow_context *subflow)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun pr_debug("msk=%p", msk);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (!READ_ONCE(pm->work_pending))
128*4882a593Smuzhiyun return;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun spin_lock_bh(&pm->lock);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun if (READ_ONCE(pm->work_pending))
133*4882a593Smuzhiyun mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun spin_unlock_bh(&pm->lock);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
mptcp_pm_subflow_closed(struct mptcp_sock * msk,u8 id)138*4882a593Smuzhiyun void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun pr_debug("msk=%p", msk);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
mptcp_pm_add_addr_received(struct mptcp_sock * msk,const struct mptcp_addr_info * addr)143*4882a593Smuzhiyun void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
144*4882a593Smuzhiyun const struct mptcp_addr_info *addr)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun pr_debug("msk=%p remote_id=%d accept=%d", msk, addr->id,
149*4882a593Smuzhiyun READ_ONCE(pm->accept_addr));
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun spin_lock_bh(&pm->lock);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (!READ_ONCE(pm->accept_addr))
154*4882a593Smuzhiyun mptcp_pm_announce_addr(msk, addr, true);
155*4882a593Smuzhiyun else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED))
156*4882a593Smuzhiyun pm->remote = *addr;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun spin_unlock_bh(&pm->lock);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
mptcp_pm_rm_addr_received(struct mptcp_sock * msk,u8 rm_id)161*4882a593Smuzhiyun void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun struct mptcp_pm_data *pm = &msk->pm;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun pr_debug("msk=%p remote_id=%d", msk, rm_id);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun spin_lock_bh(&pm->lock);
168*4882a593Smuzhiyun mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
169*4882a593Smuzhiyun pm->rm_id = rm_id;
170*4882a593Smuzhiyun spin_unlock_bh(&pm->lock);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* path manager helpers */
174*4882a593Smuzhiyun
mptcp_pm_add_addr_signal(struct mptcp_sock * msk,unsigned int remaining,struct mptcp_addr_info * saddr,bool * echo)175*4882a593Smuzhiyun bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
176*4882a593Smuzhiyun struct mptcp_addr_info *saddr, bool *echo)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun int ret = false;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun spin_lock_bh(&msk->pm.lock);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* double check after the lock is acquired */
183*4882a593Smuzhiyun if (!mptcp_pm_should_add_signal(msk))
184*4882a593Smuzhiyun goto out_unlock;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun *echo = READ_ONCE(msk->pm.add_addr_echo);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (remaining < mptcp_add_addr_len(msk->pm.local.family, *echo))
189*4882a593Smuzhiyun goto out_unlock;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun *saddr = msk->pm.local;
192*4882a593Smuzhiyun WRITE_ONCE(msk->pm.add_addr_signal, false);
193*4882a593Smuzhiyun ret = true;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun out_unlock:
196*4882a593Smuzhiyun spin_unlock_bh(&msk->pm.lock);
197*4882a593Smuzhiyun return ret;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
mptcp_pm_rm_addr_signal(struct mptcp_sock * msk,unsigned int remaining,u8 * rm_id)200*4882a593Smuzhiyun bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
201*4882a593Smuzhiyun u8 *rm_id)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun int ret = false;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun spin_lock_bh(&msk->pm.lock);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /* double check after the lock is acquired */
208*4882a593Smuzhiyun if (!mptcp_pm_should_rm_signal(msk))
209*4882a593Smuzhiyun goto out_unlock;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
212*4882a593Smuzhiyun goto out_unlock;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun *rm_id = msk->pm.rm_id;
215*4882a593Smuzhiyun WRITE_ONCE(msk->pm.rm_addr_signal, false);
216*4882a593Smuzhiyun ret = true;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun out_unlock:
219*4882a593Smuzhiyun spin_unlock_bh(&msk->pm.lock);
220*4882a593Smuzhiyun return ret;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
mptcp_pm_get_local_id(struct mptcp_sock * msk,struct sock_common * skc)223*4882a593Smuzhiyun int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun return mptcp_pm_nl_get_local_id(msk, skc);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
mptcp_pm_data_init(struct mptcp_sock * msk)228*4882a593Smuzhiyun void mptcp_pm_data_init(struct mptcp_sock *msk)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun msk->pm.add_addr_signaled = 0;
231*4882a593Smuzhiyun msk->pm.add_addr_accepted = 0;
232*4882a593Smuzhiyun msk->pm.local_addr_used = 0;
233*4882a593Smuzhiyun msk->pm.subflows = 0;
234*4882a593Smuzhiyun msk->pm.rm_id = 0;
235*4882a593Smuzhiyun WRITE_ONCE(msk->pm.work_pending, false);
236*4882a593Smuzhiyun WRITE_ONCE(msk->pm.add_addr_signal, false);
237*4882a593Smuzhiyun WRITE_ONCE(msk->pm.rm_addr_signal, false);
238*4882a593Smuzhiyun WRITE_ONCE(msk->pm.accept_addr, false);
239*4882a593Smuzhiyun WRITE_ONCE(msk->pm.accept_subflow, false);
240*4882a593Smuzhiyun WRITE_ONCE(msk->pm.add_addr_echo, false);
241*4882a593Smuzhiyun msk->pm.status = 0;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun spin_lock_init(&msk->pm.lock);
244*4882a593Smuzhiyun INIT_LIST_HEAD(&msk->pm.anno_list);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun mptcp_pm_nl_data_init(msk);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
mptcp_pm_init(void)249*4882a593Smuzhiyun void __init mptcp_pm_init(void)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun mptcp_pm_nl_init();
252*4882a593Smuzhiyun }
253