• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 seq_file;
16  
17  /* MPTCP sk_buff extension data */
18  struct mptcp_ext {
19  	union {
20  		u64	data_ack;
21  		u32	data_ack32;
22  	};
23  	u64		data_seq;
24  	u32		subflow_seq;
25  	u16		data_len;
26  	u8		use_map:1,
27  			dsn64:1,
28  			data_fin:1,
29  			use_ack:1,
30  			ack64:1,
31  			mpc_map:1,
32  			__unused:2;
33  	/* one byte hole */
34  };
35  
36  struct mptcp_out_options {
37  #if IS_ENABLED(CONFIG_MPTCP)
38  	u16 suboptions;
39  	u64 sndr_key;
40  	u64 rcvr_key;
41  	union {
42  		struct in_addr addr;
43  #if IS_ENABLED(CONFIG_MPTCP_IPV6)
44  		struct in6_addr addr6;
45  #endif
46  	};
47  	u8 addr_id;
48  	u64 ahmac;
49  	u8 rm_id;
50  	u8 join_id;
51  	u8 backup;
52  	u32 nonce;
53  	u64 thmac;
54  	u32 token;
55  	u8 hmac[20];
56  	struct mptcp_ext ext_copy;
57  #endif
58  };
59  
60  #ifdef CONFIG_MPTCP
61  extern struct request_sock_ops mptcp_subflow_request_sock_ops;
62  
63  void mptcp_init(void);
64  
sk_is_mptcp(const struct sock * sk)65  static inline bool sk_is_mptcp(const struct sock *sk)
66  {
67  	return tcp_sk(sk)->is_mptcp;
68  }
69  
rsk_is_mptcp(const struct request_sock * req)70  static inline bool rsk_is_mptcp(const struct request_sock *req)
71  {
72  	return tcp_rsk(req)->is_mptcp;
73  }
74  
rsk_drop_req(const struct request_sock * req)75  static inline bool rsk_drop_req(const struct request_sock *req)
76  {
77  	return tcp_rsk(req)->is_mptcp && tcp_rsk(req)->drop_req;
78  }
79  
80  void mptcp_space(const struct sock *ssk, int *space, int *full_space);
81  bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
82  		       unsigned int *size, struct mptcp_out_options *opts);
83  bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
84  			  struct mptcp_out_options *opts);
85  bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
86  			       unsigned int *size, unsigned int remaining,
87  			       struct mptcp_out_options *opts);
88  void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb);
89  
90  void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts);
91  
92  /* move the skb extension owership, with the assumption that 'to' is
93   * newly allocated
94   */
mptcp_skb_ext_move(struct sk_buff * to,struct sk_buff * from)95  static inline void mptcp_skb_ext_move(struct sk_buff *to,
96  				      struct sk_buff *from)
97  {
98  	if (!skb_ext_exist(from, SKB_EXT_MPTCP))
99  		return;
100  
101  	if (WARN_ON_ONCE(to->active_extensions))
102  		skb_ext_put(to);
103  
104  	to->active_extensions = from->active_extensions;
105  	to->extensions = from->extensions;
106  	from->active_extensions = 0;
107  }
108  
mptcp_ext_matches(const struct mptcp_ext * to_ext,const struct mptcp_ext * from_ext)109  static inline bool mptcp_ext_matches(const struct mptcp_ext *to_ext,
110  				     const struct mptcp_ext *from_ext)
111  {
112  	/* MPTCP always clears the ext when adding it to the skb, so
113  	 * holes do not bother us here
114  	 */
115  	return !from_ext ||
116  	       (to_ext && from_ext &&
117  	        !memcmp(from_ext, to_ext, sizeof(struct mptcp_ext)));
118  }
119  
120  /* check if skbs can be collapsed.
121   * MPTCP collapse is allowed if neither @to or @from carry an mptcp data
122   * mapping, or if the extension of @to is the same as @from.
123   * Collapsing is not possible if @to lacks an extension, but @from carries one.
124   */
mptcp_skb_can_collapse(const struct sk_buff * to,const struct sk_buff * from)125  static inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
126  					  const struct sk_buff *from)
127  {
128  	return mptcp_ext_matches(skb_ext_find(to, SKB_EXT_MPTCP),
129  				 skb_ext_find(from, SKB_EXT_MPTCP));
130  }
131  
132  void mptcp_seq_show(struct seq_file *seq);
133  int mptcp_subflow_init_cookie_req(struct request_sock *req,
134  				  const struct sock *sk_listener,
135  				  struct sk_buff *skb);
136  #else
137  
mptcp_init(void)138  static inline void mptcp_init(void)
139  {
140  }
141  
sk_is_mptcp(const struct sock * sk)142  static inline bool sk_is_mptcp(const struct sock *sk)
143  {
144  	return false;
145  }
146  
rsk_is_mptcp(const struct request_sock * req)147  static inline bool rsk_is_mptcp(const struct request_sock *req)
148  {
149  	return false;
150  }
151  
rsk_drop_req(const struct request_sock * req)152  static inline bool rsk_drop_req(const struct request_sock *req)
153  {
154  	return false;
155  }
156  
mptcp_parse_option(const struct sk_buff * skb,const unsigned char * ptr,int opsize,struct tcp_options_received * opt_rx)157  static inline void mptcp_parse_option(const struct sk_buff *skb,
158  				      const unsigned char *ptr, int opsize,
159  				      struct tcp_options_received *opt_rx)
160  {
161  }
162  
mptcp_syn_options(struct sock * sk,const struct sk_buff * skb,unsigned int * size,struct mptcp_out_options * opts)163  static inline bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
164  				     unsigned int *size,
165  				     struct mptcp_out_options *opts)
166  {
167  	return false;
168  }
169  
mptcp_synack_options(const struct request_sock * req,unsigned int * size,struct mptcp_out_options * opts)170  static inline bool mptcp_synack_options(const struct request_sock *req,
171  					unsigned int *size,
172  					struct mptcp_out_options *opts)
173  {
174  	return false;
175  }
176  
mptcp_established_options(struct sock * sk,struct sk_buff * skb,unsigned int * size,unsigned int remaining,struct mptcp_out_options * opts)177  static inline bool mptcp_established_options(struct sock *sk,
178  					     struct sk_buff *skb,
179  					     unsigned int *size,
180  					     unsigned int remaining,
181  					     struct mptcp_out_options *opts)
182  {
183  	return false;
184  }
185  
mptcp_incoming_options(struct sock * sk,struct sk_buff * skb)186  static inline void mptcp_incoming_options(struct sock *sk,
187  					  struct sk_buff *skb)
188  {
189  }
190  
mptcp_skb_ext_move(struct sk_buff * to,const struct sk_buff * from)191  static inline void mptcp_skb_ext_move(struct sk_buff *to,
192  				      const struct sk_buff *from)
193  {
194  }
195  
mptcp_skb_can_collapse(const struct sk_buff * to,const struct sk_buff * from)196  static inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
197  					  const struct sk_buff *from)
198  {
199  	return true;
200  }
201  
mptcp_space(const struct sock * ssk,int * s,int * fs)202  static inline void mptcp_space(const struct sock *ssk, int *s, int *fs) { }
mptcp_seq_show(struct seq_file * seq)203  static inline void mptcp_seq_show(struct seq_file *seq) { }
204  
mptcp_subflow_init_cookie_req(struct request_sock * req,const struct sock * sk_listener,struct sk_buff * skb)205  static inline int mptcp_subflow_init_cookie_req(struct request_sock *req,
206  						const struct sock *sk_listener,
207  						struct sk_buff *skb)
208  {
209  	return 0; /* TCP fallback */
210  }
211  #endif /* CONFIG_MPTCP */
212  
213  #if IS_ENABLED(CONFIG_MPTCP_IPV6)
214  int mptcpv6_init(void);
215  void mptcpv6_handle_mapped(struct sock *sk, bool mapped);
216  #elif IS_ENABLED(CONFIG_IPV6)
mptcpv6_init(void)217  static inline int mptcpv6_init(void) { return 0; }
mptcpv6_handle_mapped(struct sock * sk,bool mapped)218  static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { }
219  #endif
220  
221  #endif /* __NET_MPTCP_H */
222