diff options
Diffstat (limited to 'net/mptcp/subflow.c')
| -rw-r--r-- | net/mptcp/subflow.c | 23 | 
1 files changed, 19 insertions, 4 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 8c37087f0d84..be76ada89d96 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -888,7 +888,7 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *  {  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);  	u32 offset, seq, delta; -	u16 csum; +	__sum16 csum;  	int len;  	if (!csum_reqd) @@ -955,11 +955,14 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *  				 subflow->map_data_csum);  	if (unlikely(csum)) {  		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR); -		subflow->send_mp_fail = 1; -		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX); +		if (subflow->mp_join || subflow->valid_csum_seen) { +			subflow->send_mp_fail = 1; +			MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX); +		}  		return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY;  	} +	subflow->valid_csum_seen = 1;  	return MAPPING_OK;  } @@ -1141,6 +1144,18 @@ static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ss  	}  } +static bool subflow_can_fallback(struct mptcp_subflow_context *subflow) +{ +	struct mptcp_sock *msk = mptcp_sk(subflow->conn); + +	if (subflow->mp_join) +		return false; +	else if (READ_ONCE(msk->csum_enabled)) +		return !subflow->valid_csum_seen; +	else +		return !subflow->fully_established; +} +  static bool subflow_check_data_avail(struct sock *ssk)  {  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); @@ -1218,7 +1233,7 @@ fallback:  		return true;  	} -	if (subflow->mp_join || subflow->fully_established) { +	if (!subflow_can_fallback(subflow)) {  		/* fatal protocol error, close the socket.  		 * subflow_error_report() will introduce the appropriate barriers  		 */  |