13ee17bc7SMat Martineau /* SPDX-License-Identifier: GPL-2.0 */ 23ee17bc7SMat Martineau /* 33ee17bc7SMat Martineau * Multipath TCP 43ee17bc7SMat Martineau * 53ee17bc7SMat Martineau * Copyright (c) 2017 - 2019, Intel Corporation. 63ee17bc7SMat Martineau */ 73ee17bc7SMat Martineau 83ee17bc7SMat Martineau #ifndef __NET_MPTCP_H 93ee17bc7SMat Martineau #define __NET_MPTCP_H 103ee17bc7SMat Martineau 1185712484SMat Martineau #include <linux/skbuff.h> 12eda7acddSPeter Krystad #include <linux/tcp.h> 133ee17bc7SMat Martineau #include <linux/types.h> 143ee17bc7SMat Martineau 15fc518953SFlorian Westphal struct seq_file; 16fc518953SFlorian Westphal 173ee17bc7SMat Martineau /* MPTCP sk_buff extension data */ 183ee17bc7SMat Martineau struct mptcp_ext { 19a0c1d0eaSChristoph Paasch union { 203ee17bc7SMat Martineau u64 data_ack; 21a0c1d0eaSChristoph Paasch u32 data_ack32; 22a0c1d0eaSChristoph Paasch }; 233ee17bc7SMat Martineau u64 data_seq; 243ee17bc7SMat Martineau u32 subflow_seq; 253ee17bc7SMat Martineau u16 data_len; 26d0cc2987SGeliang Tang __sum16 csum; 273ee17bc7SMat Martineau u8 use_map:1, 283ee17bc7SMat Martineau dsn64:1, 293ee17bc7SMat Martineau data_fin:1, 303ee17bc7SMat Martineau use_ack:1, 313ee17bc7SMat Martineau ack64:1, 32cc7972eaSChristoph Paasch mpc_map:1, 335a369ca6SPaolo Abeni frozen:1, 34dc87efdbSFlorian Westphal reset_transient:1; 35208e8f66SGeliang Tang u8 reset_reason:4, 36208e8f66SGeliang Tang csum_reqd:1; 373ee17bc7SMat Martineau }; 383ee17bc7SMat Martineau 396445e17aSGeliang Tang #define MPTCP_RM_IDS_MAX 8 406445e17aSGeliang Tang 416445e17aSGeliang Tang struct mptcp_rm_list { 426445e17aSGeliang Tang u8 ids[MPTCP_RM_IDS_MAX]; 436445e17aSGeliang Tang u8 nr; 446445e17aSGeliang Tang }; 456445e17aSGeliang Tang 4630f60baeSGeliang Tang struct mptcp_addr_info { 4730f60baeSGeliang Tang u8 id; 4830f60baeSGeliang Tang sa_family_t family; 4930f60baeSGeliang Tang __be16 port; 503df523abSPeter Krystad union { 513df523abSPeter Krystad struct in_addr addr; 523df523abSPeter Krystad #if IS_ENABLED(CONFIG_MPTCP_IPV6) 533df523abSPeter Krystad struct in6_addr addr6; 543df523abSPeter Krystad #endif 553df523abSPeter Krystad }; 5630f60baeSGeliang Tang }; 5730f60baeSGeliang Tang 5830f60baeSGeliang Tang struct mptcp_out_options { 5930f60baeSGeliang Tang #if IS_ENABLED(CONFIG_MPTCP) 6030f60baeSGeliang Tang u16 suboptions; 616445e17aSGeliang Tang struct mptcp_rm_list rm_list; 62f296234cSPeter Krystad u8 join_id; 63f296234cSPeter Krystad u8 backup; 6406fe1719SGeliang Tang u8 reset_reason:4, 6506fe1719SGeliang Tang reset_transient:1, 66bab6b88eSGeliang Tang csum_reqd:1, 67bab6b88eSGeliang Tang allow_join_id0:1; 68d7b26908SPaolo Abeni union { 69d7b26908SPaolo Abeni struct { 70d7b26908SPaolo Abeni u64 sndr_key; 71d7b26908SPaolo Abeni u64 rcvr_key; 72d7b26908SPaolo Abeni }; 73d7b26908SPaolo Abeni struct { 74d7b26908SPaolo Abeni struct mptcp_addr_info addr; 75d7b26908SPaolo Abeni u64 ahmac; 76d7b26908SPaolo Abeni }; 77*c25aeb4eSGeliang Tang struct { 786d0060f6SMat Martineau struct mptcp_ext ext_copy; 79*c25aeb4eSGeliang Tang u64 fail_seq; 80*c25aeb4eSGeliang Tang }; 81d7b26908SPaolo Abeni struct { 82d7b26908SPaolo Abeni u32 nonce; 83d7b26908SPaolo Abeni u32 token; 84d7b26908SPaolo Abeni u64 thmac; 85d7b26908SPaolo Abeni u8 hmac[20]; 86d7b26908SPaolo Abeni }; 87d7b26908SPaolo Abeni }; 88eda7acddSPeter Krystad #endif 89eda7acddSPeter Krystad }; 90eda7acddSPeter Krystad 9185712484SMat Martineau #ifdef CONFIG_MPTCP 9208b8d080SFlorian Westphal extern struct request_sock_ops mptcp_subflow_request_sock_ops; 9385712484SMat Martineau 94f870fa0bSMat Martineau void mptcp_init(void); 95f870fa0bSMat Martineau 96cec37a6eSPeter Krystad static inline bool sk_is_mptcp(const struct sock *sk) 97cec37a6eSPeter Krystad { 98cec37a6eSPeter Krystad return tcp_sk(sk)->is_mptcp; 99cec37a6eSPeter Krystad } 100cec37a6eSPeter Krystad 101cec37a6eSPeter Krystad static inline bool rsk_is_mptcp(const struct request_sock *req) 102cec37a6eSPeter Krystad { 103cec37a6eSPeter Krystad return tcp_rsk(req)->is_mptcp; 104cec37a6eSPeter Krystad } 105cec37a6eSPeter Krystad 10690bf4513SPaolo Abeni static inline bool rsk_drop_req(const struct request_sock *req) 10790bf4513SPaolo Abeni { 10890bf4513SPaolo Abeni return tcp_rsk(req)->is_mptcp && tcp_rsk(req)->drop_req; 10990bf4513SPaolo Abeni } 11090bf4513SPaolo Abeni 111071c8ed6SFlorian Westphal void mptcp_space(const struct sock *ssk, int *space, int *full_space); 112cc7972eaSChristoph Paasch bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, 113cc7972eaSChristoph Paasch unsigned int *size, struct mptcp_out_options *opts); 114cec37a6eSPeter Krystad bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, 115cec37a6eSPeter Krystad struct mptcp_out_options *opts); 116cec37a6eSPeter Krystad bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, 117cec37a6eSPeter Krystad unsigned int *size, unsigned int remaining, 118cec37a6eSPeter Krystad struct mptcp_out_options *opts); 1196787b7e3SJianguo Wu bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb); 120cec37a6eSPeter Krystad 121fa3fe2b1SFlorian Westphal void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, 122fa3fe2b1SFlorian Westphal struct mptcp_out_options *opts); 123eda7acddSPeter Krystad 12485712484SMat Martineau /* move the skb extension owership, with the assumption that 'to' is 12585712484SMat Martineau * newly allocated 12685712484SMat Martineau */ 12785712484SMat Martineau static inline void mptcp_skb_ext_move(struct sk_buff *to, 12885712484SMat Martineau struct sk_buff *from) 12985712484SMat Martineau { 13085712484SMat Martineau if (!skb_ext_exist(from, SKB_EXT_MPTCP)) 13185712484SMat Martineau return; 13285712484SMat Martineau 13385712484SMat Martineau if (WARN_ON_ONCE(to->active_extensions)) 13485712484SMat Martineau skb_ext_put(to); 13585712484SMat Martineau 13685712484SMat Martineau to->active_extensions = from->active_extensions; 13785712484SMat Martineau to->extensions = from->extensions; 13885712484SMat Martineau from->active_extensions = 0; 13985712484SMat Martineau } 14085712484SMat Martineau 1415a369ca6SPaolo Abeni static inline void mptcp_skb_ext_copy(struct sk_buff *to, 1425a369ca6SPaolo Abeni struct sk_buff *from) 1435a369ca6SPaolo Abeni { 1445a369ca6SPaolo Abeni struct mptcp_ext *from_ext; 1455a369ca6SPaolo Abeni 1465a369ca6SPaolo Abeni from_ext = skb_ext_find(from, SKB_EXT_MPTCP); 1475a369ca6SPaolo Abeni if (!from_ext) 1485a369ca6SPaolo Abeni return; 1495a369ca6SPaolo Abeni 1505a369ca6SPaolo Abeni from_ext->frozen = 1; 1515a369ca6SPaolo Abeni skb_ext_copy(to, from); 1525a369ca6SPaolo Abeni } 1535a369ca6SPaolo Abeni 15485712484SMat Martineau static inline bool mptcp_ext_matches(const struct mptcp_ext *to_ext, 15585712484SMat Martineau const struct mptcp_ext *from_ext) 15685712484SMat Martineau { 15785712484SMat Martineau /* MPTCP always clears the ext when adding it to the skb, so 15885712484SMat Martineau * holes do not bother us here 15985712484SMat Martineau */ 16085712484SMat Martineau return !from_ext || 16185712484SMat Martineau (to_ext && from_ext && 16285712484SMat Martineau !memcmp(from_ext, to_ext, sizeof(struct mptcp_ext))); 16385712484SMat Martineau } 16485712484SMat Martineau 16585712484SMat Martineau /* check if skbs can be collapsed. 16685712484SMat Martineau * MPTCP collapse is allowed if neither @to or @from carry an mptcp data 16785712484SMat Martineau * mapping, or if the extension of @to is the same as @from. 16885712484SMat Martineau * Collapsing is not possible if @to lacks an extension, but @from carries one. 16985712484SMat Martineau */ 17085712484SMat Martineau static inline bool mptcp_skb_can_collapse(const struct sk_buff *to, 17185712484SMat Martineau const struct sk_buff *from) 17285712484SMat Martineau { 17385712484SMat Martineau return mptcp_ext_matches(skb_ext_find(to, SKB_EXT_MPTCP), 17485712484SMat Martineau skb_ext_find(from, SKB_EXT_MPTCP)); 17585712484SMat Martineau } 17685712484SMat Martineau 177fc518953SFlorian Westphal void mptcp_seq_show(struct seq_file *seq); 178c83a47e5SFlorian Westphal int mptcp_subflow_init_cookie_req(struct request_sock *req, 179c83a47e5SFlorian Westphal const struct sock *sk_listener, 180c83a47e5SFlorian Westphal struct sk_buff *skb); 181dc87efdbSFlorian Westphal 182dc87efdbSFlorian Westphal __be32 mptcp_get_reset_option(const struct sk_buff *skb); 183dc87efdbSFlorian Westphal 184dc87efdbSFlorian Westphal static inline __be32 mptcp_reset_option(const struct sk_buff *skb) 185dc87efdbSFlorian Westphal { 186dc87efdbSFlorian Westphal if (skb_ext_exist(skb, SKB_EXT_MPTCP)) 187dc87efdbSFlorian Westphal return mptcp_get_reset_option(skb); 188dc87efdbSFlorian Westphal 189dc87efdbSFlorian Westphal return htonl(0u); 190dc87efdbSFlorian Westphal } 19185712484SMat Martineau #else 19285712484SMat Martineau 193f870fa0bSMat Martineau static inline void mptcp_init(void) 194f870fa0bSMat Martineau { 195f870fa0bSMat Martineau } 196f870fa0bSMat Martineau 197cec37a6eSPeter Krystad static inline bool sk_is_mptcp(const struct sock *sk) 198cec37a6eSPeter Krystad { 199cec37a6eSPeter Krystad return false; 200cec37a6eSPeter Krystad } 201cec37a6eSPeter Krystad 202cec37a6eSPeter Krystad static inline bool rsk_is_mptcp(const struct request_sock *req) 203cec37a6eSPeter Krystad { 204cec37a6eSPeter Krystad return false; 205cec37a6eSPeter Krystad } 206cec37a6eSPeter Krystad 20790bf4513SPaolo Abeni static inline bool rsk_drop_req(const struct request_sock *req) 20890bf4513SPaolo Abeni { 20990bf4513SPaolo Abeni return false; 21090bf4513SPaolo Abeni } 21190bf4513SPaolo Abeni 212cc7972eaSChristoph Paasch static inline void mptcp_parse_option(const struct sk_buff *skb, 213cc7972eaSChristoph Paasch const unsigned char *ptr, int opsize, 214eda7acddSPeter Krystad struct tcp_options_received *opt_rx) 215eda7acddSPeter Krystad { 216eda7acddSPeter Krystad } 217eda7acddSPeter Krystad 218cc7972eaSChristoph Paasch static inline bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, 219cc7972eaSChristoph Paasch unsigned int *size, 220cec37a6eSPeter Krystad struct mptcp_out_options *opts) 221cec37a6eSPeter Krystad { 222cec37a6eSPeter Krystad return false; 223cec37a6eSPeter Krystad } 224cec37a6eSPeter Krystad 225cec37a6eSPeter Krystad static inline bool mptcp_synack_options(const struct request_sock *req, 226cec37a6eSPeter Krystad unsigned int *size, 227cec37a6eSPeter Krystad struct mptcp_out_options *opts) 228cec37a6eSPeter Krystad { 229cec37a6eSPeter Krystad return false; 230cec37a6eSPeter Krystad } 231cec37a6eSPeter Krystad 232cec37a6eSPeter Krystad static inline bool mptcp_established_options(struct sock *sk, 233cec37a6eSPeter Krystad struct sk_buff *skb, 234cec37a6eSPeter Krystad unsigned int *size, 235cec37a6eSPeter Krystad unsigned int remaining, 236cec37a6eSPeter Krystad struct mptcp_out_options *opts) 237cec37a6eSPeter Krystad { 238cec37a6eSPeter Krystad return false; 239cec37a6eSPeter Krystad } 240cec37a6eSPeter Krystad 2416787b7e3SJianguo Wu static inline bool mptcp_incoming_options(struct sock *sk, 24277d0cab9SFlorian Westphal struct sk_buff *skb) 243648ef4b8SMat Martineau { 2446787b7e3SJianguo Wu return true; 245648ef4b8SMat Martineau } 246648ef4b8SMat Martineau 24785712484SMat Martineau static inline void mptcp_skb_ext_move(struct sk_buff *to, 24885712484SMat Martineau const struct sk_buff *from) 24985712484SMat Martineau { 25085712484SMat Martineau } 25185712484SMat Martineau 2525a369ca6SPaolo Abeni static inline void mptcp_skb_ext_copy(struct sk_buff *to, 2535a369ca6SPaolo Abeni struct sk_buff *from) 2545a369ca6SPaolo Abeni { 2555a369ca6SPaolo Abeni } 2565a369ca6SPaolo Abeni 25785712484SMat Martineau static inline bool mptcp_skb_can_collapse(const struct sk_buff *to, 25885712484SMat Martineau const struct sk_buff *from) 25985712484SMat Martineau { 26085712484SMat Martineau return true; 26185712484SMat Martineau } 26285712484SMat Martineau 263071c8ed6SFlorian Westphal static inline void mptcp_space(const struct sock *ssk, int *s, int *fs) { } 264fc518953SFlorian Westphal static inline void mptcp_seq_show(struct seq_file *seq) { } 265c83a47e5SFlorian Westphal 266c83a47e5SFlorian Westphal static inline int mptcp_subflow_init_cookie_req(struct request_sock *req, 267c83a47e5SFlorian Westphal const struct sock *sk_listener, 268c83a47e5SFlorian Westphal struct sk_buff *skb) 269c83a47e5SFlorian Westphal { 270c83a47e5SFlorian Westphal return 0; /* TCP fallback */ 271c83a47e5SFlorian Westphal } 272dc87efdbSFlorian Westphal 273dc87efdbSFlorian Westphal static inline __be32 mptcp_reset_option(const struct sk_buff *skb) { return htonl(0u); } 27485712484SMat Martineau #endif /* CONFIG_MPTCP */ 275f870fa0bSMat Martineau 276f870fa0bSMat Martineau #if IS_ENABLED(CONFIG_MPTCP_IPV6) 277f870fa0bSMat Martineau int mptcpv6_init(void); 27831484d56SGeert Uytterhoeven void mptcpv6_handle_mapped(struct sock *sk, bool mapped); 279f870fa0bSMat Martineau #elif IS_ENABLED(CONFIG_IPV6) 28031484d56SGeert Uytterhoeven static inline int mptcpv6_init(void) { return 0; } 28131484d56SGeert Uytterhoeven static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } 282f870fa0bSMat Martineau #endif 283f870fa0bSMat Martineau 2843ee17bc7SMat Martineau #endif /* __NET_MPTCP_H */ 285