forked from mirrors/linux
		
	mptcp: MP_FAIL suboption sending
This patch added the MP_FAIL suboption sending support. Add a new flag named send_mp_fail in struct mptcp_subflow_context. If this flag is set, send out MP_FAIL suboption. Add a new member fail_seq in struct mptcp_out_options to save the data sequence number to put into the MP_FAIL suboption. An MP_FAIL option could be included in a RST or on the subflow-level ACK. Suggested-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Geliang Tang <geliangtang@xiaomi.com> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d7b2690837
								
							
						
					
					
						commit
						c25aeb4e09
					
				
					 3 changed files with 62 additions and 5 deletions
				
			
		|  | @ -74,7 +74,10 @@ struct mptcp_out_options { | |||
| 			struct mptcp_addr_info addr; | ||||
| 			u64 ahmac; | ||||
| 		}; | ||||
| 		struct mptcp_ext ext_copy; | ||||
| 		struct { | ||||
| 			struct mptcp_ext ext_copy; | ||||
| 			u64 fail_seq; | ||||
| 		}; | ||||
| 		struct { | ||||
| 			u32 nonce; | ||||
| 			u32 token; | ||||
|  |  | |||
|  | @ -767,7 +767,7 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, | |||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb, | ||||
| static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb, | ||||
| 						   unsigned int *size, | ||||
| 						   unsigned int remaining, | ||||
| 						   struct mptcp_out_options *opts) | ||||
|  | @ -775,12 +775,36 @@ static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_bu | |||
| 	const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | ||||
| 
 | ||||
| 	if (remaining < TCPOLEN_MPTCP_RST) | ||||
| 		return; | ||||
| 		return false; | ||||
| 
 | ||||
| 	*size = TCPOLEN_MPTCP_RST; | ||||
| 	opts->suboptions |= OPTION_MPTCP_RST; | ||||
| 	opts->reset_transient = subflow->reset_transient; | ||||
| 	opts->reset_reason = subflow->reset_reason; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool mptcp_established_options_mp_fail(struct sock *sk, | ||||
| 					      unsigned int *size, | ||||
| 					      unsigned int remaining, | ||||
| 					      struct mptcp_out_options *opts) | ||||
| { | ||||
| 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | ||||
| 
 | ||||
| 	if (likely(!subflow->send_mp_fail)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (remaining < TCPOLEN_MPTCP_FAIL) | ||||
| 		return false; | ||||
| 
 | ||||
| 	*size = TCPOLEN_MPTCP_FAIL; | ||||
| 	opts->suboptions |= OPTION_MPTCP_FAIL; | ||||
| 	opts->fail_seq = subflow->map_seq; | ||||
| 
 | ||||
| 	pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, | ||||
|  | @ -799,15 +823,28 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, | |||
| 		return false; | ||||
| 
 | ||||
| 	if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) { | ||||
| 		mptcp_established_options_rst(sk, skb, size, remaining, opts); | ||||
| 		if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { | ||||
| 			*size += opt_size; | ||||
| 			remaining -= opt_size; | ||||
| 		} | ||||
| 		if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { | ||||
| 			*size += opt_size; | ||||
| 			remaining -= opt_size; | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	snd_data_fin = mptcp_data_fin_enabled(msk); | ||||
| 	if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts)) | ||||
| 		ret = true; | ||||
| 	else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) | ||||
| 	else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) { | ||||
| 		ret = true; | ||||
| 		if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { | ||||
| 			*size += opt_size; | ||||
| 			remaining -= opt_size; | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* we reserved enough space for the above options, and exceeding the
 | ||||
| 	 * TCP option space would be fatal | ||||
|  | @ -1210,6 +1247,20 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) | |||
| void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, | ||||
| 			 struct mptcp_out_options *opts) | ||||
| { | ||||
| 	if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) { | ||||
| 		const struct sock *ssk = (const struct sock *)tp; | ||||
| 		struct mptcp_subflow_context *subflow; | ||||
| 
 | ||||
| 		subflow = mptcp_subflow_ctx(ssk); | ||||
| 		subflow->send_mp_fail = 0; | ||||
| 
 | ||||
| 		*ptr++ = mptcp_option(MPTCPOPT_MP_FAIL, | ||||
| 				      TCPOLEN_MPTCP_FAIL, | ||||
| 				      0, 0); | ||||
| 		put_unaligned_be64(opts->fail_seq, ptr); | ||||
| 		ptr += 2; | ||||
| 	} | ||||
| 
 | ||||
| 	/* RST is mutually exclusive with everything else */ | ||||
| 	if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { | ||||
| 		*ptr++ = mptcp_option(MPTCPOPT_RST, | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #define OPTION_MPTCP_PRIO	BIT(9) | ||||
| #define OPTION_MPTCP_RST	BIT(10) | ||||
| #define OPTION_MPTCP_DSS	BIT(11) | ||||
| #define OPTION_MPTCP_FAIL	BIT(12) | ||||
| 
 | ||||
| /* MPTCP option subtypes */ | ||||
| #define MPTCPOPT_MP_CAPABLE	0 | ||||
|  | @ -68,6 +69,7 @@ | |||
| #define TCPOLEN_MPTCP_PRIO_ALIGN	4 | ||||
| #define TCPOLEN_MPTCP_FASTCLOSE		12 | ||||
| #define TCPOLEN_MPTCP_RST		4 | ||||
| #define TCPOLEN_MPTCP_FAIL		12 | ||||
| 
 | ||||
| #define TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM	(TCPOLEN_MPTCP_DSS_CHECKSUM + TCPOLEN_MPTCP_MPC_ACK_DATA) | ||||
| 
 | ||||
|  | @ -429,6 +431,7 @@ struct mptcp_subflow_context { | |||
| 		mpc_map : 1, | ||||
| 		backup : 1, | ||||
| 		send_mp_prio : 1, | ||||
| 		send_mp_fail : 1, | ||||
| 		rx_eof : 1, | ||||
| 		can_ack : 1,        /* only after processing the remote a key */ | ||||
| 		disposable : 1,	    /* ctx can be free at ulp release time */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Geliang Tang
						Geliang Tang