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