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