1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Multipath TCP |
4 | * |
5 | * Copyright (c) 2017 - 2019, Intel Corporation. |
6 | */ |
7 | |
8 | #ifndef __NET_MPTCP_H |
9 | #define __NET_MPTCP_H |
10 | |
11 | #include <linux/skbuff.h> |
12 | #include <linux/tcp.h> |
13 | #include <linux/types.h> |
14 | |
15 | struct mptcp_info; |
16 | struct mptcp_sock; |
17 | struct mptcp_pm_addr_entry; |
18 | struct seq_file; |
19 | |
20 | /* MPTCP sk_buff extension data */ |
21 | struct mptcp_ext { |
22 | union { |
23 | u64 data_ack; |
24 | u32 data_ack32; |
25 | }; |
26 | u64 data_seq; |
27 | u32 subflow_seq; |
28 | u16 data_len; |
29 | __sum16 csum; |
30 | u8 use_map:1, |
31 | dsn64:1, |
32 | data_fin:1, |
33 | use_ack:1, |
34 | ack64:1, |
35 | mpc_map:1, |
36 | frozen:1, |
37 | reset_transient:1; |
38 | u8 reset_reason:4, |
39 | csum_reqd:1, |
40 | infinite_map:1; |
41 | }; |
42 | |
43 | #define MPTCPOPT_HMAC_LEN 20 |
44 | #define MPTCP_RM_IDS_MAX 8 |
45 | |
46 | struct mptcp_rm_list { |
47 | u8 ids[MPTCP_RM_IDS_MAX]; |
48 | u8 nr; |
49 | }; |
50 | |
51 | struct mptcp_addr_info { |
52 | u8 id; |
53 | sa_family_t family; |
54 | __be16 port; |
55 | union { |
56 | struct in_addr addr; |
57 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
58 | struct in6_addr addr6; |
59 | #endif |
60 | }; |
61 | }; |
62 | |
63 | struct mptcp_out_options { |
64 | #if IS_ENABLED(CONFIG_MPTCP) |
65 | u16 suboptions; |
66 | struct mptcp_rm_list rm_list; |
67 | u8 join_id; |
68 | u8 backup; |
69 | u8 reset_reason:4, |
70 | reset_transient:1, |
71 | csum_reqd:1, |
72 | allow_join_id0:1; |
73 | union { |
74 | struct { |
75 | u64 sndr_key; |
76 | u64 rcvr_key; |
77 | u64 data_seq; |
78 | u32 subflow_seq; |
79 | u16 data_len; |
80 | __sum16 csum; |
81 | }; |
82 | struct { |
83 | struct mptcp_addr_info addr; |
84 | u64 ahmac; |
85 | }; |
86 | struct { |
87 | struct mptcp_ext ext_copy; |
88 | u64 fail_seq; |
89 | }; |
90 | struct { |
91 | u32 nonce; |
92 | u32 token; |
93 | u64 thmac; |
94 | u8 hmac[MPTCPOPT_HMAC_LEN]; |
95 | }; |
96 | }; |
97 | #endif |
98 | }; |
99 | |
100 | #define MPTCP_SCHED_NAME_MAX 16 |
101 | #define MPTCP_SCHED_MAX 128 |
102 | #define MPTCP_SCHED_BUF_MAX (MPTCP_SCHED_NAME_MAX * MPTCP_SCHED_MAX) |
103 | |
104 | struct mptcp_sched_ops { |
105 | int (*get_send)(struct mptcp_sock *msk); |
106 | int (*get_retrans)(struct mptcp_sock *msk); |
107 | |
108 | char name[MPTCP_SCHED_NAME_MAX]; |
109 | struct module *owner; |
110 | struct list_head list; |
111 | |
112 | void (*init)(struct mptcp_sock *msk); |
113 | void (*release)(struct mptcp_sock *msk); |
114 | } ____cacheline_aligned_in_smp; |
115 | |
116 | #define MPTCP_PM_NAME_MAX 16 |
117 | #define MPTCP_PM_MAX 128 |
118 | #define MPTCP_PM_BUF_MAX (MPTCP_PM_NAME_MAX * MPTCP_PM_MAX) |
119 | |
120 | struct mptcp_pm_ops { |
121 | char name[MPTCP_PM_NAME_MAX]; |
122 | struct module *owner; |
123 | struct list_head list; |
124 | |
125 | void (*init)(struct mptcp_sock *msk); |
126 | void (*release)(struct mptcp_sock *msk); |
127 | } ____cacheline_aligned_in_smp; |
128 | |
129 | #ifdef CONFIG_MPTCP |
130 | void mptcp_init(void); |
131 | |
132 | static inline bool sk_is_mptcp(const struct sock *sk) |
133 | { |
134 | return tcp_sk(sk)->is_mptcp; |
135 | } |
136 | |
137 | static inline bool rsk_is_mptcp(const struct request_sock *req) |
138 | { |
139 | return tcp_rsk(req)->is_mptcp; |
140 | } |
141 | |
142 | static inline bool rsk_drop_req(const struct request_sock *req) |
143 | { |
144 | return tcp_rsk(req)->is_mptcp && tcp_rsk(req)->drop_req; |
145 | } |
146 | |
147 | void mptcp_space(const struct sock *ssk, int *space, int *full_space); |
148 | bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, |
149 | unsigned int *size, struct mptcp_out_options *opts); |
150 | bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, |
151 | struct mptcp_out_options *opts); |
152 | bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, |
153 | unsigned int *size, unsigned int remaining, |
154 | struct mptcp_out_options *opts); |
155 | bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb); |
156 | |
157 | void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp, |
158 | struct mptcp_out_options *opts); |
159 | |
160 | void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info); |
161 | |
162 | /* move the skb extension owership, with the assumption that 'to' is |
163 | * newly allocated |
164 | */ |
165 | static inline void mptcp_skb_ext_move(struct sk_buff *to, |
166 | struct sk_buff *from) |
167 | { |
168 | if (!skb_ext_exist(skb: from, id: SKB_EXT_MPTCP)) |
169 | return; |
170 | |
171 | if (WARN_ON_ONCE(to->active_extensions)) |
172 | skb_ext_put(skb: to); |
173 | |
174 | to->active_extensions = from->active_extensions; |
175 | to->extensions = from->extensions; |
176 | from->active_extensions = 0; |
177 | } |
178 | |
179 | static inline void mptcp_skb_ext_copy(struct sk_buff *to, |
180 | struct sk_buff *from) |
181 | { |
182 | struct mptcp_ext *from_ext; |
183 | |
184 | from_ext = skb_ext_find(skb: from, id: SKB_EXT_MPTCP); |
185 | if (!from_ext) |
186 | return; |
187 | |
188 | from_ext->frozen = 1; |
189 | skb_ext_copy(dst: to, src: from); |
190 | } |
191 | |
192 | static inline bool mptcp_ext_matches(const struct mptcp_ext *to_ext, |
193 | const struct mptcp_ext *from_ext) |
194 | { |
195 | /* MPTCP always clears the ext when adding it to the skb, so |
196 | * holes do not bother us here |
197 | */ |
198 | return !from_ext || |
199 | (to_ext && from_ext && |
200 | !memcmp(p: from_ext, q: to_ext, size: sizeof(struct mptcp_ext))); |
201 | } |
202 | |
203 | /* check if skbs can be collapsed. |
204 | * MPTCP collapse is allowed if neither @to or @from carry an mptcp data |
205 | * mapping, or if the extension of @to is the same as @from. |
206 | * Collapsing is not possible if @to lacks an extension, but @from carries one. |
207 | */ |
208 | static inline bool mptcp_skb_can_collapse(const struct sk_buff *to, |
209 | const struct sk_buff *from) |
210 | { |
211 | return mptcp_ext_matches(to_ext: skb_ext_find(skb: to, id: SKB_EXT_MPTCP), |
212 | from_ext: skb_ext_find(skb: from, id: SKB_EXT_MPTCP)); |
213 | } |
214 | |
215 | void mptcp_seq_show(struct seq_file *seq); |
216 | int mptcp_subflow_init_cookie_req(struct request_sock *req, |
217 | const struct sock *sk_listener, |
218 | struct sk_buff *skb); |
219 | struct request_sock *mptcp_subflow_reqsk_alloc(const struct request_sock_ops *ops, |
220 | struct sock *sk_listener, |
221 | bool attach_listener); |
222 | |
223 | __be32 mptcp_get_reset_option(const struct sk_buff *skb); |
224 | |
225 | static inline __be32 mptcp_reset_option(const struct sk_buff *skb) |
226 | { |
227 | if (skb_ext_exist(skb, id: SKB_EXT_MPTCP)) |
228 | return mptcp_get_reset_option(skb); |
229 | |
230 | return htonl(0u); |
231 | } |
232 | |
233 | void mptcp_active_detect_blackhole(struct sock *sk, bool expired); |
234 | #else |
235 | |
236 | static inline void mptcp_init(void) |
237 | { |
238 | } |
239 | |
240 | static inline bool sk_is_mptcp(const struct sock *sk) |
241 | { |
242 | return false; |
243 | } |
244 | |
245 | static inline bool rsk_is_mptcp(const struct request_sock *req) |
246 | { |
247 | return false; |
248 | } |
249 | |
250 | static inline bool rsk_drop_req(const struct request_sock *req) |
251 | { |
252 | return false; |
253 | } |
254 | |
255 | static inline bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, |
256 | unsigned int *size, |
257 | struct mptcp_out_options *opts) |
258 | { |
259 | return false; |
260 | } |
261 | |
262 | static inline bool mptcp_synack_options(const struct request_sock *req, |
263 | unsigned int *size, |
264 | struct mptcp_out_options *opts) |
265 | { |
266 | return false; |
267 | } |
268 | |
269 | static inline bool mptcp_established_options(struct sock *sk, |
270 | struct sk_buff *skb, |
271 | unsigned int *size, |
272 | unsigned int remaining, |
273 | struct mptcp_out_options *opts) |
274 | { |
275 | return false; |
276 | } |
277 | |
278 | static inline bool mptcp_incoming_options(struct sock *sk, |
279 | struct sk_buff *skb) |
280 | { |
281 | return true; |
282 | } |
283 | |
284 | static inline void mptcp_skb_ext_move(struct sk_buff *to, |
285 | const struct sk_buff *from) |
286 | { |
287 | } |
288 | |
289 | static inline void mptcp_skb_ext_copy(struct sk_buff *to, |
290 | struct sk_buff *from) |
291 | { |
292 | } |
293 | |
294 | static inline bool mptcp_skb_can_collapse(const struct sk_buff *to, |
295 | const struct sk_buff *from) |
296 | { |
297 | return true; |
298 | } |
299 | |
300 | static inline void mptcp_space(const struct sock *ssk, int *s, int *fs) { } |
301 | static inline void mptcp_seq_show(struct seq_file *seq) { } |
302 | |
303 | static inline int mptcp_subflow_init_cookie_req(struct request_sock *req, |
304 | const struct sock *sk_listener, |
305 | struct sk_buff *skb) |
306 | { |
307 | return 0; /* TCP fallback */ |
308 | } |
309 | |
310 | static inline struct request_sock *mptcp_subflow_reqsk_alloc(const struct request_sock_ops *ops, |
311 | struct sock *sk_listener, |
312 | bool attach_listener) |
313 | { |
314 | return NULL; |
315 | } |
316 | |
317 | static inline __be32 mptcp_reset_option(const struct sk_buff *skb) { return htonl(0u); } |
318 | |
319 | static inline void mptcp_active_detect_blackhole(struct sock *sk, bool expired) { } |
320 | #endif /* CONFIG_MPTCP */ |
321 | |
322 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
323 | int mptcpv6_init(void); |
324 | void mptcpv6_handle_mapped(struct sock *sk, bool mapped); |
325 | #elif IS_ENABLED(CONFIG_IPV6) |
326 | static inline int mptcpv6_init(void) { return 0; } |
327 | static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } |
328 | #endif |
329 | |
330 | #if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) |
331 | struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); |
332 | #else |
333 | static inline struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) { return NULL; } |
334 | #endif |
335 | |
336 | #if !IS_ENABLED(CONFIG_MPTCP) |
337 | struct mptcp_sock { }; |
338 | #endif |
339 | |
340 | #endif /* __NET_MPTCP_H */ |
341 | |