162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Multipath TCP
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2017 - 2019, Intel Corporation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef __NET_MPTCP_H
962306a36Sopenharmony_ci#define __NET_MPTCP_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/skbuff.h>
1262306a36Sopenharmony_ci#include <linux/tcp.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct mptcp_info;
1662306a36Sopenharmony_cistruct mptcp_sock;
1762306a36Sopenharmony_cistruct seq_file;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* MPTCP sk_buff extension data */
2062306a36Sopenharmony_cistruct mptcp_ext {
2162306a36Sopenharmony_ci	union {
2262306a36Sopenharmony_ci		u64	data_ack;
2362306a36Sopenharmony_ci		u32	data_ack32;
2462306a36Sopenharmony_ci	};
2562306a36Sopenharmony_ci	u64		data_seq;
2662306a36Sopenharmony_ci	u32		subflow_seq;
2762306a36Sopenharmony_ci	u16		data_len;
2862306a36Sopenharmony_ci	__sum16		csum;
2962306a36Sopenharmony_ci	u8		use_map:1,
3062306a36Sopenharmony_ci			dsn64:1,
3162306a36Sopenharmony_ci			data_fin:1,
3262306a36Sopenharmony_ci			use_ack:1,
3362306a36Sopenharmony_ci			ack64:1,
3462306a36Sopenharmony_ci			mpc_map:1,
3562306a36Sopenharmony_ci			frozen:1,
3662306a36Sopenharmony_ci			reset_transient:1;
3762306a36Sopenharmony_ci	u8		reset_reason:4,
3862306a36Sopenharmony_ci			csum_reqd:1,
3962306a36Sopenharmony_ci			infinite_map:1;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define MPTCPOPT_HMAC_LEN	20
4362306a36Sopenharmony_ci#define MPTCP_RM_IDS_MAX	8
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct mptcp_rm_list {
4662306a36Sopenharmony_ci	u8 ids[MPTCP_RM_IDS_MAX];
4762306a36Sopenharmony_ci	u8 nr;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct mptcp_addr_info {
5162306a36Sopenharmony_ci	u8			id;
5262306a36Sopenharmony_ci	sa_family_t		family;
5362306a36Sopenharmony_ci	__be16			port;
5462306a36Sopenharmony_ci	union {
5562306a36Sopenharmony_ci		struct in_addr	addr;
5662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
5762306a36Sopenharmony_ci		struct in6_addr	addr6;
5862306a36Sopenharmony_ci#endif
5962306a36Sopenharmony_ci	};
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistruct mptcp_out_options {
6362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP)
6462306a36Sopenharmony_ci	u16 suboptions;
6562306a36Sopenharmony_ci	struct mptcp_rm_list rm_list;
6662306a36Sopenharmony_ci	u8 join_id;
6762306a36Sopenharmony_ci	u8 backup;
6862306a36Sopenharmony_ci	u8 reset_reason:4,
6962306a36Sopenharmony_ci	   reset_transient:1,
7062306a36Sopenharmony_ci	   csum_reqd:1,
7162306a36Sopenharmony_ci	   allow_join_id0:1;
7262306a36Sopenharmony_ci	union {
7362306a36Sopenharmony_ci		struct {
7462306a36Sopenharmony_ci			u64 sndr_key;
7562306a36Sopenharmony_ci			u64 rcvr_key;
7662306a36Sopenharmony_ci			u64 data_seq;
7762306a36Sopenharmony_ci			u32 subflow_seq;
7862306a36Sopenharmony_ci			u16 data_len;
7962306a36Sopenharmony_ci			__sum16 csum;
8062306a36Sopenharmony_ci		};
8162306a36Sopenharmony_ci		struct {
8262306a36Sopenharmony_ci			struct mptcp_addr_info addr;
8362306a36Sopenharmony_ci			u64 ahmac;
8462306a36Sopenharmony_ci		};
8562306a36Sopenharmony_ci		struct {
8662306a36Sopenharmony_ci			struct mptcp_ext ext_copy;
8762306a36Sopenharmony_ci			u64 fail_seq;
8862306a36Sopenharmony_ci		};
8962306a36Sopenharmony_ci		struct {
9062306a36Sopenharmony_ci			u32 nonce;
9162306a36Sopenharmony_ci			u32 token;
9262306a36Sopenharmony_ci			u64 thmac;
9362306a36Sopenharmony_ci			u8 hmac[MPTCPOPT_HMAC_LEN];
9462306a36Sopenharmony_ci		};
9562306a36Sopenharmony_ci	};
9662306a36Sopenharmony_ci#endif
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#define MPTCP_SCHED_NAME_MAX	16
10062306a36Sopenharmony_ci#define MPTCP_SUBFLOWS_MAX	8
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct mptcp_sched_data {
10362306a36Sopenharmony_ci	bool	reinject;
10462306a36Sopenharmony_ci	u8	subflows;
10562306a36Sopenharmony_ci	struct mptcp_subflow_context *contexts[MPTCP_SUBFLOWS_MAX];
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct mptcp_sched_ops {
10962306a36Sopenharmony_ci	int (*get_subflow)(struct mptcp_sock *msk,
11062306a36Sopenharmony_ci			   struct mptcp_sched_data *data);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	char			name[MPTCP_SCHED_NAME_MAX];
11362306a36Sopenharmony_ci	struct module		*owner;
11462306a36Sopenharmony_ci	struct list_head	list;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	void (*init)(struct mptcp_sock *msk);
11762306a36Sopenharmony_ci	void (*release)(struct mptcp_sock *msk);
11862306a36Sopenharmony_ci} ____cacheline_aligned_in_smp;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#ifdef CONFIG_MPTCP
12162306a36Sopenharmony_civoid mptcp_init(void);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline bool sk_is_mptcp(const struct sock *sk)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	return tcp_sk(sk)->is_mptcp;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline bool rsk_is_mptcp(const struct request_sock *req)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	return tcp_rsk(req)->is_mptcp;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic inline bool rsk_drop_req(const struct request_sock *req)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	return tcp_rsk(req)->is_mptcp && tcp_rsk(req)->drop_req;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_civoid mptcp_space(const struct sock *ssk, int *space, int *full_space);
13962306a36Sopenharmony_cibool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
14062306a36Sopenharmony_ci		       unsigned int *size, struct mptcp_out_options *opts);
14162306a36Sopenharmony_cibool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
14262306a36Sopenharmony_ci			  struct mptcp_out_options *opts);
14362306a36Sopenharmony_cibool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
14462306a36Sopenharmony_ci			       unsigned int *size, unsigned int remaining,
14562306a36Sopenharmony_ci			       struct mptcp_out_options *opts);
14662306a36Sopenharmony_cibool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_civoid mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
14962306a36Sopenharmony_ci			 struct mptcp_out_options *opts);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_civoid mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/* move the skb extension owership, with the assumption that 'to' is
15462306a36Sopenharmony_ci * newly allocated
15562306a36Sopenharmony_ci */
15662306a36Sopenharmony_cistatic inline void mptcp_skb_ext_move(struct sk_buff *to,
15762306a36Sopenharmony_ci				      struct sk_buff *from)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	if (!skb_ext_exist(from, SKB_EXT_MPTCP))
16062306a36Sopenharmony_ci		return;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (WARN_ON_ONCE(to->active_extensions))
16362306a36Sopenharmony_ci		skb_ext_put(to);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	to->active_extensions = from->active_extensions;
16662306a36Sopenharmony_ci	to->extensions = from->extensions;
16762306a36Sopenharmony_ci	from->active_extensions = 0;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic inline void mptcp_skb_ext_copy(struct sk_buff *to,
17162306a36Sopenharmony_ci				      struct sk_buff *from)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct mptcp_ext *from_ext;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	from_ext = skb_ext_find(from, SKB_EXT_MPTCP);
17662306a36Sopenharmony_ci	if (!from_ext)
17762306a36Sopenharmony_ci		return;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	from_ext->frozen = 1;
18062306a36Sopenharmony_ci	skb_ext_copy(to, from);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic inline bool mptcp_ext_matches(const struct mptcp_ext *to_ext,
18462306a36Sopenharmony_ci				     const struct mptcp_ext *from_ext)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	/* MPTCP always clears the ext when adding it to the skb, so
18762306a36Sopenharmony_ci	 * holes do not bother us here
18862306a36Sopenharmony_ci	 */
18962306a36Sopenharmony_ci	return !from_ext ||
19062306a36Sopenharmony_ci	       (to_ext && from_ext &&
19162306a36Sopenharmony_ci	        !memcmp(from_ext, to_ext, sizeof(struct mptcp_ext)));
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/* check if skbs can be collapsed.
19562306a36Sopenharmony_ci * MPTCP collapse is allowed if neither @to or @from carry an mptcp data
19662306a36Sopenharmony_ci * mapping, or if the extension of @to is the same as @from.
19762306a36Sopenharmony_ci * Collapsing is not possible if @to lacks an extension, but @from carries one.
19862306a36Sopenharmony_ci */
19962306a36Sopenharmony_cistatic inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
20062306a36Sopenharmony_ci					  const struct sk_buff *from)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	return mptcp_ext_matches(skb_ext_find(to, SKB_EXT_MPTCP),
20362306a36Sopenharmony_ci				 skb_ext_find(from, SKB_EXT_MPTCP));
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_civoid mptcp_seq_show(struct seq_file *seq);
20762306a36Sopenharmony_ciint mptcp_subflow_init_cookie_req(struct request_sock *req,
20862306a36Sopenharmony_ci				  const struct sock *sk_listener,
20962306a36Sopenharmony_ci				  struct sk_buff *skb);
21062306a36Sopenharmony_cistruct request_sock *mptcp_subflow_reqsk_alloc(const struct request_sock_ops *ops,
21162306a36Sopenharmony_ci					       struct sock *sk_listener,
21262306a36Sopenharmony_ci					       bool attach_listener);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci__be32 mptcp_get_reset_option(const struct sk_buff *skb);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic inline __be32 mptcp_reset_option(const struct sk_buff *skb)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	if (skb_ext_exist(skb, SKB_EXT_MPTCP))
21962306a36Sopenharmony_ci		return mptcp_get_reset_option(skb);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	return htonl(0u);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci#else
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic inline void mptcp_init(void)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic inline bool sk_is_mptcp(const struct sock *sk)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	return false;
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic inline bool rsk_is_mptcp(const struct request_sock *req)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	return false;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic inline bool rsk_drop_req(const struct request_sock *req)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	return false;
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistatic inline bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
24562306a36Sopenharmony_ci				     unsigned int *size,
24662306a36Sopenharmony_ci				     struct mptcp_out_options *opts)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	return false;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic inline bool mptcp_synack_options(const struct request_sock *req,
25262306a36Sopenharmony_ci					unsigned int *size,
25362306a36Sopenharmony_ci					struct mptcp_out_options *opts)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	return false;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic inline bool mptcp_established_options(struct sock *sk,
25962306a36Sopenharmony_ci					     struct sk_buff *skb,
26062306a36Sopenharmony_ci					     unsigned int *size,
26162306a36Sopenharmony_ci					     unsigned int remaining,
26262306a36Sopenharmony_ci					     struct mptcp_out_options *opts)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	return false;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic inline bool mptcp_incoming_options(struct sock *sk,
26862306a36Sopenharmony_ci					  struct sk_buff *skb)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	return true;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic inline void mptcp_skb_ext_move(struct sk_buff *to,
27462306a36Sopenharmony_ci				      const struct sk_buff *from)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic inline void mptcp_skb_ext_copy(struct sk_buff *to,
27962306a36Sopenharmony_ci				      struct sk_buff *from)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic inline bool mptcp_skb_can_collapse(const struct sk_buff *to,
28462306a36Sopenharmony_ci					  const struct sk_buff *from)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	return true;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic inline void mptcp_space(const struct sock *ssk, int *s, int *fs) { }
29062306a36Sopenharmony_cistatic inline void mptcp_seq_show(struct seq_file *seq) { }
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic inline int mptcp_subflow_init_cookie_req(struct request_sock *req,
29362306a36Sopenharmony_ci						const struct sock *sk_listener,
29462306a36Sopenharmony_ci						struct sk_buff *skb)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	return 0; /* TCP fallback */
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic inline struct request_sock *mptcp_subflow_reqsk_alloc(const struct request_sock_ops *ops,
30062306a36Sopenharmony_ci							     struct sock *sk_listener,
30162306a36Sopenharmony_ci							     bool attach_listener)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	return NULL;
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic inline __be32 mptcp_reset_option(const struct sk_buff *skb)  { return htonl(0u); }
30762306a36Sopenharmony_ci#endif /* CONFIG_MPTCP */
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
31062306a36Sopenharmony_ciint mptcpv6_init(void);
31162306a36Sopenharmony_civoid mptcpv6_handle_mapped(struct sock *sk, bool mapped);
31262306a36Sopenharmony_ci#elif IS_ENABLED(CONFIG_IPV6)
31362306a36Sopenharmony_cistatic inline int mptcpv6_init(void) { return 0; }
31462306a36Sopenharmony_cistatic inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { }
31562306a36Sopenharmony_ci#endif
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL)
31862306a36Sopenharmony_cistruct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk);
31962306a36Sopenharmony_ci#else
32062306a36Sopenharmony_cistatic inline struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) { return NULL; }
32162306a36Sopenharmony_ci#endif
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci#if !IS_ENABLED(CONFIG_MPTCP)
32462306a36Sopenharmony_cistruct mptcp_sock { };
32562306a36Sopenharmony_ci#endif
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci#endif /* __NET_MPTCP_H */
328