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