diff options
Diffstat (limited to 'net/mptcp/protocol.h')
| -rw-r--r-- | net/mptcp/protocol.h | 253 | 
1 files changed, 237 insertions, 16 deletions
| diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 9f8663b30456..e4ca6320ce76 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -17,6 +17,12 @@  #define OPTION_MPTCP_MPC_SYN	BIT(0)  #define OPTION_MPTCP_MPC_SYNACK	BIT(1)  #define OPTION_MPTCP_MPC_ACK	BIT(2) +#define OPTION_MPTCP_MPJ_SYN	BIT(3) +#define OPTION_MPTCP_MPJ_SYNACK	BIT(4) +#define OPTION_MPTCP_MPJ_ACK	BIT(5) +#define OPTION_MPTCP_ADD_ADDR	BIT(6) +#define OPTION_MPTCP_ADD_ADDR6	BIT(7) +#define OPTION_MPTCP_RM_ADDR	BIT(8)  /* MPTCP option subtypes */  #define MPTCPOPT_MP_CAPABLE	0 @@ -33,12 +39,30 @@  #define TCPOLEN_MPTCP_MPC_SYNACK	12  #define TCPOLEN_MPTCP_MPC_ACK		20  #define TCPOLEN_MPTCP_MPC_ACK_DATA	22 +#define TCPOLEN_MPTCP_MPJ_SYN		12 +#define TCPOLEN_MPTCP_MPJ_SYNACK	16 +#define TCPOLEN_MPTCP_MPJ_ACK		24  #define TCPOLEN_MPTCP_DSS_BASE		4  #define TCPOLEN_MPTCP_DSS_ACK32		4  #define TCPOLEN_MPTCP_DSS_ACK64		8  #define TCPOLEN_MPTCP_DSS_MAP32		10  #define TCPOLEN_MPTCP_DSS_MAP64		14  #define TCPOLEN_MPTCP_DSS_CHECKSUM	2 +#define TCPOLEN_MPTCP_ADD_ADDR		16 +#define TCPOLEN_MPTCP_ADD_ADDR_PORT	18 +#define TCPOLEN_MPTCP_ADD_ADDR_BASE	8 +#define TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT	10 +#define TCPOLEN_MPTCP_ADD_ADDR6		28 +#define TCPOLEN_MPTCP_ADD_ADDR6_PORT	30 +#define TCPOLEN_MPTCP_ADD_ADDR6_BASE	20 +#define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT	22 +#define TCPOLEN_MPTCP_PORT_LEN		2 +#define TCPOLEN_MPTCP_RM_ADDR_BASE	4 + +/* MPTCP MP_JOIN flags */ +#define MPTCPOPT_BACKUP		BIT(0) +#define MPTCPOPT_HMAC_LEN	20 +#define MPTCPOPT_THMAC_LEN	8  /* MPTCP MP_CAPABLE flags */  #define MPTCP_VERSION_MASK	(0x0F) @@ -55,9 +79,115 @@  #define MPTCP_DSS_HAS_ACK	BIT(0)  #define MPTCP_DSS_FLAG_MASK	(0x1F) +/* MPTCP ADD_ADDR flags */ +#define MPTCP_ADDR_ECHO		BIT(0) +#define MPTCP_ADDR_HMAC_LEN	20 +#define MPTCP_ADDR_IPVERSION_4	4 +#define MPTCP_ADDR_IPVERSION_6	6 +  /* MPTCP socket flags */  #define MPTCP_DATA_READY	0  #define MPTCP_SEND_SPACE	1 +#define MPTCP_WORK_RTX		2 +#define MPTCP_WORK_EOF		3 + +struct mptcp_options_received { +	u64	sndr_key; +	u64	rcvr_key; +	u64	data_ack; +	u64	data_seq; +	u32	subflow_seq; +	u16	data_len; +	u16	mp_capable : 1, +		mp_join : 1, +		dss : 1, +		add_addr : 1, +		rm_addr : 1, +		family : 4, +		echo : 1, +		backup : 1; +	u32	token; +	u32	nonce; +	u64	thmac; +	u8	hmac[20]; +	u8	join_id; +	u8	use_map:1, +		dsn64:1, +		data_fin:1, +		use_ack:1, +		ack64:1, +		mpc_map:1, +		__unused:2; +	u8	addr_id; +	u8	rm_id; +	union { +		struct in_addr	addr; +#if IS_ENABLED(CONFIG_MPTCP_IPV6) +		struct in6_addr	addr6; +#endif +	}; +	u64	ahmac; +	u16	port; +}; + +static inline __be32 mptcp_option(u8 subopt, u8 len, u8 nib, u8 field) +{ +	return htonl((TCPOPT_MPTCP << 24) | (len << 16) | (subopt << 12) | +		     ((nib & 0xF) << 8) | field); +} + +#define MPTCP_PM_MAX_ADDR	4 + +struct mptcp_addr_info { +	sa_family_t		family; +	__be16			port; +	u8			id; +	union { +		struct in_addr addr; +#if IS_ENABLED(CONFIG_MPTCP_IPV6) +		struct in6_addr addr6; +#endif +	}; +}; + +enum mptcp_pm_status { +	MPTCP_PM_ADD_ADDR_RECEIVED, +	MPTCP_PM_ESTABLISHED, +	MPTCP_PM_SUBFLOW_ESTABLISHED, +}; + +struct mptcp_pm_data { +	struct mptcp_addr_info local; +	struct mptcp_addr_info remote; + +	spinlock_t	lock;		/*protects the whole PM data */ + +	bool		addr_signal; +	bool		server_side; +	bool		work_pending; +	bool		accept_addr; +	bool		accept_subflow; +	u8		add_addr_signaled; +	u8		add_addr_accepted; +	u8		local_addr_used; +	u8		subflows; +	u8		add_addr_signal_max; +	u8		add_addr_accept_max; +	u8		local_addr_max; +	u8		subflows_max; +	u8		status; + +	struct		work_struct work; +}; + +struct mptcp_data_frag { +	struct list_head list; +	u64 data_seq; +	int data_len; +	int offset; +	int overhead; +	struct page *page; +};  /* MPTCP connection sock */  struct mptcp_sock { @@ -67,13 +197,20 @@ struct mptcp_sock {  	u64		remote_key;  	u64		write_seq;  	u64		ack_seq; +	atomic64_t	snd_una; +	unsigned long	timer_ival;  	u32		token;  	unsigned long	flags;  	bool		can_ack; +	spinlock_t	join_list_lock; +	struct work_struct work;  	struct list_head conn_list; +	struct list_head rtx_queue; +	struct list_head join_list;  	struct skb_ext	*cached_ext;	/* for the next sendmsg */  	struct socket	*subflow; /* outgoing connect/listener/!mp_capable */  	struct sock	*first; +	struct mptcp_pm_data	pm;  };  #define mptcp_for_each_subflow(__msk, __subflow)			\ @@ -84,17 +221,40 @@ static inline struct mptcp_sock *mptcp_sk(const struct sock *sk)  	return (struct mptcp_sock *)sk;  } +static inline struct mptcp_data_frag *mptcp_rtx_tail(const struct sock *sk) +{ +	struct mptcp_sock *msk = mptcp_sk(sk); + +	if (list_empty(&msk->rtx_queue)) +		return NULL; + +	return list_last_entry(&msk->rtx_queue, struct mptcp_data_frag, list); +} + +static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk) +{ +	struct mptcp_sock *msk = mptcp_sk(sk); + +	if (list_empty(&msk->rtx_queue)) +		return NULL; + +	return list_first_entry(&msk->rtx_queue, struct mptcp_data_frag, list); +} +  struct mptcp_subflow_request_sock {  	struct	tcp_request_sock sk;  	u16	mp_capable : 1,  		mp_join : 1, -		backup : 1, -		remote_key_valid : 1; +		backup : 1; +	u8	local_id; +	u8	remote_id;  	u64	local_key; -	u64	remote_key;  	u64	idsn;  	u32	token;  	u32	ssn_offset; +	u64	thmac; +	u32	local_nonce; +	u32	remote_nonce;  };  static inline struct mptcp_subflow_request_sock * @@ -117,14 +277,28 @@ struct mptcp_subflow_context {  	u32	ssn_offset;  	u32	map_data_len;  	u32	request_mptcp : 1,  /* send MP_CAPABLE */ +		request_join : 1,   /* send MP_JOIN */ +		request_bkup : 1,  		mp_capable : 1,	    /* remote is MPTCP capable */ -		fourth_ack : 1,	    /* send initial DSS */ +		mp_join : 1,	    /* remote is JOINing */ +		fully_established : 1,	    /* path validated */ +		pm_notified : 1,    /* PM hook called for established status */  		conn_finished : 1,  		map_valid : 1,  		mpc_map : 1, +		backup : 1,  		data_avail : 1,  		rx_eof : 1, +		data_fin_tx_enable : 1,  		can_ack : 1;	    /* only after processing the remote a key */ +	u64	data_fin_tx_seq; +	u32	remote_nonce; +	u64	thmac; +	u32	local_nonce; +	u32	remote_token; +	u8	hmac[MPTCPOPT_HMAC_LEN]; +	u8	local_id; +	u8	remote_id;  	struct	sock *tcp_sock;	    /* tcp sk backpointer */  	struct	sock *conn;	    /* parent mptcp_sock */ @@ -168,6 +342,11 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow)  int mptcp_is_enabled(struct net *net);  bool mptcp_subflow_data_available(struct sock *sk);  void mptcp_subflow_init(void); + +/* called with sk socket lock held */ +int __mptcp_subflow_connect(struct sock *sk, int ifindex, +			    const struct mptcp_addr_info *loc, +			    const struct mptcp_addr_info *remote);  int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock);  static inline void mptcp_subflow_tcp_fallback(struct sock *sk, @@ -190,23 +369,23 @@ void mptcp_proto_init(void);  int mptcp_proto_v6_init(void);  #endif -struct mptcp_read_arg { -	struct msghdr *msg; -}; - -int mptcp_read_actor(read_descriptor_t *desc, struct sk_buff *skb, -		     unsigned int offset, size_t len); - +struct sock *mptcp_sk_clone(const struct sock *sk, +			    const struct mptcp_options_received *mp_opt, +			    struct request_sock *req);  void mptcp_get_options(const struct sk_buff *skb, -		       struct tcp_options_received *opt_rx); +		       struct mptcp_options_received *mp_opt);  void mptcp_finish_connect(struct sock *sk); +void mptcp_data_ready(struct sock *sk, struct sock *ssk); +bool mptcp_finish_join(struct sock *sk); +void mptcp_data_acked(struct sock *sk); +void mptcp_subflow_eof(struct sock *sk);  int mptcp_token_new_request(struct request_sock *req);  void mptcp_token_destroy_request(u32 token);  int mptcp_token_new_connect(struct sock *sk); -int mptcp_token_new_accept(u32 token); -void mptcp_token_update_accept(struct sock *sk, struct sock *conn); +int mptcp_token_new_accept(u32 token, struct sock *conn); +struct mptcp_sock *mptcp_token_get_sock(u32 token);  void mptcp_token_destroy(u32 token);  void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn); @@ -222,8 +401,48 @@ static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)  	mptcp_crypto_key_sha(*key, token, idsn);  } -void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2, -			   void *hash_out); +void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac); + +void mptcp_pm_init(void); +void mptcp_pm_data_init(struct mptcp_sock *msk); +void mptcp_pm_close(struct mptcp_sock *msk); +void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side); +void mptcp_pm_fully_established(struct mptcp_sock *msk); +bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk); +void mptcp_pm_connection_closed(struct mptcp_sock *msk); +void mptcp_pm_subflow_established(struct mptcp_sock *msk, +				  struct mptcp_subflow_context *subflow); +void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id); +void mptcp_pm_add_addr_received(struct mptcp_sock *msk, +				const struct mptcp_addr_info *addr); + +int mptcp_pm_announce_addr(struct mptcp_sock *msk, +			   const struct mptcp_addr_info *addr); +int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id); +int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id); + +static inline bool mptcp_pm_should_signal(struct mptcp_sock *msk) +{ +	return READ_ONCE(msk->pm.addr_signal); +} + +static inline unsigned int mptcp_add_addr_len(int family) +{ +	if (family == AF_INET) +		return TCPOLEN_MPTCP_ADD_ADDR; +	return TCPOLEN_MPTCP_ADD_ADDR6; +} + +bool mptcp_pm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, +			  struct mptcp_addr_info *saddr); +int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); + +void mptcp_pm_nl_init(void); +void mptcp_pm_nl_data_init(struct mptcp_sock *msk); +void mptcp_pm_nl_fully_established(struct mptcp_sock *msk); +void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk); +void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk); +int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);  static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)  { @@ -237,4 +456,6 @@ static inline bool before64(__u64 seq1, __u64 seq2)  #define after64(seq2, seq1)	before64(seq1, seq2) +void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops); +  #endif /* __MPTCP_PROTOCOL_H */ |