xref: /OK3568_Linux_fs/kernel/net/mptcp/pm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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