diff options
Diffstat (limited to 'net/mptcp/subflow.c')
| -rw-r--r-- | net/mptcp/subflow.c | 80 | 
1 files changed, 51 insertions, 29 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 39e2cbdf3801..064ab3235893 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -39,7 +39,7 @@ static void subflow_req_destructor(struct request_sock *req)  {  	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); -	pr_debug("subflow_req=%p", subflow_req); +	pr_debug("subflow_req=%p\n", subflow_req);  	if (subflow_req->msk)  		sock_put((struct sock *)subflow_req->msk); @@ -100,6 +100,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)  		return NULL;  	}  	subflow_req->local_id = local_id; +	subflow_req->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)req);  	return msk;  } @@ -145,7 +146,7 @@ static int subflow_check_req(struct request_sock *req,  	struct mptcp_options_received mp_opt;  	bool opt_mp_capable, opt_mp_join; -	pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); +	pr_debug("subflow_req=%p, listener=%p\n", subflow_req, listener);  #ifdef CONFIG_TCP_MD5SIG  	/* no MPTCP if MD5SIG is enabled on this socket or we may run out of @@ -168,6 +169,9 @@ static int subflow_check_req(struct request_sock *req,  			return 0;  	} else if (opt_mp_join) {  		SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX); + +		if (mp_opt.backup) +			SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNBACKUPRX);  	}  	if (opt_mp_capable && listener->request_mptcp) { @@ -217,7 +221,7 @@ again:  		}  		if (subflow_use_different_sport(subflow_req->msk, sk_listener)) { -			pr_debug("syn inet_sport=%d %d", +			pr_debug("syn inet_sport=%d %d\n",  				 ntohs(inet_sk(sk_listener)->inet_sport),  				 ntohs(inet_sk((struct sock *)subflow_req->msk)->inet_sport));  			if (!mptcp_pm_sport_in_anno_list(subflow_req->msk, sk_listener)) { @@ -239,7 +243,7 @@ again:  			subflow_init_req_cookie_join_save(subflow_req, skb);  		} -		pr_debug("token=%u, remote_nonce=%u msk=%p", subflow_req->token, +		pr_debug("token=%u, remote_nonce=%u msk=%p\n", subflow_req->token,  			 subflow_req->remote_nonce, subflow_req->msk);  	} @@ -523,7 +527,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)  	subflow->rel_write_seq = 1;  	subflow->conn_finished = 1;  	subflow->ssn_offset = TCP_SKB_CB(skb)->seq; -	pr_debug("subflow=%p synack seq=%x", subflow, subflow->ssn_offset); +	pr_debug("subflow=%p synack seq=%x\n", subflow, subflow->ssn_offset);  	mptcp_get_options(skb, &mp_opt);  	if (subflow->request_mptcp) { @@ -555,7 +559,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)  		subflow->thmac = mp_opt.thmac;  		subflow->remote_nonce = mp_opt.nonce;  		WRITE_ONCE(subflow->remote_id, mp_opt.join_id); -		pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u backup=%d", +		pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u backup=%d\n",  			 subflow, subflow->thmac, subflow->remote_nonce,  			 subflow->backup); @@ -577,8 +581,11 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)  		subflow->mp_join = 1;  		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); +		if (subflow->backup) +			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKBACKUPRX); +  		if (subflow_use_different_dport(msk, sk)) { -			pr_debug("synack inet_dport=%d %d", +			pr_debug("synack inet_dport=%d %d\n",  				 ntohs(inet_sk(sk)->inet_dport),  				 ntohs(inet_sk(parent)->inet_dport));  			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINPORTSYNACKRX); @@ -614,6 +621,8 @@ static int subflow_chk_local_id(struct sock *sk)  		return err;  	subflow_set_local_id(subflow, err); +	subflow->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)sk); +  	return 0;  } @@ -646,7 +655,7 @@ static int subflow_v4_conn_request(struct sock *sk, struct sk_buff *skb)  {  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); -	pr_debug("subflow=%p", subflow); +	pr_debug("subflow=%p\n", subflow);  	/* Never answer to SYNs sent to broadcast or multicast */  	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) @@ -677,7 +686,7 @@ static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb)  {  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); -	pr_debug("subflow=%p", subflow); +	pr_debug("subflow=%p\n", subflow);  	if (skb->protocol == htons(ETH_P_IP))  		return subflow_v4_conn_request(sk, skb); @@ -798,7 +807,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,  	struct mptcp_sock *owner;  	struct sock *child; -	pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); +	pr_debug("listener=%p, req=%p, conn=%p\n", listener, req, listener->conn);  	/* After child creation we must look for MPC even when options  	 * are not parsed @@ -889,7 +898,7 @@ create_child:  			ctx->conn = (struct sock *)owner;  			if (subflow_use_different_sport(owner, sk)) { -				pr_debug("ack inet_sport=%d %d", +				pr_debug("ack inet_sport=%d %d\n",  					 ntohs(inet_sk(sk)->inet_sport),  					 ntohs(inet_sk((struct sock *)owner)->inet_sport));  				if (!mptcp_pm_sport_in_anno_list(owner, sk)) { @@ -952,7 +961,7 @@ enum mapping_status {  static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn)  { -	pr_debug("Bad mapping: ssn=%d map_seq=%d map_data_len=%d", +	pr_debug("Bad mapping: ssn=%d map_seq=%d map_data_len=%d\n",  		 ssn, subflow->map_subflow_seq, subflow->map_data_len);  } @@ -1112,7 +1121,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,  	data_len = mpext->data_len;  	if (data_len == 0) { -		pr_debug("infinite mapping received"); +		pr_debug("infinite mapping received\n");  		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);  		subflow->map_data_len = 0;  		return MAPPING_INVALID; @@ -1124,7 +1133,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,  		if (data_len == 1) {  			bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,  								 mpext->dsn64); -			pr_debug("DATA_FIN with no payload seq=%llu", mpext->data_seq); +			pr_debug("DATA_FIN with no payload seq=%llu\n", mpext->data_seq);  			if (subflow->map_valid) {  				/* A DATA_FIN might arrive in a DSS  				 * option before the previous mapping @@ -1150,7 +1159,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,  			data_fin_seq &= GENMASK_ULL(31, 0);  		mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64); -		pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d", +		pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d\n",  			 data_fin_seq, mpext->dsn64);  		/* Adjust for DATA_FIN using 1 byte of sequence space */ @@ -1196,7 +1205,7 @@ static enum mapping_status get_mapping_status(struct sock *ssk,  	if (unlikely(subflow->map_csum_reqd != csum_reqd))  		return MAPPING_INVALID; -	pr_debug("new map seq=%llu subflow_seq=%u data_len=%u csum=%d:%u", +	pr_debug("new map seq=%llu subflow_seq=%u data_len=%u csum=%d:%u\n",  		 subflow->map_seq, subflow->map_subflow_seq,  		 subflow->map_data_len, subflow->map_csum_reqd,  		 subflow->map_data_csum); @@ -1221,14 +1230,22 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,  {  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);  	bool fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN; -	u32 incr; +	struct tcp_sock *tp = tcp_sk(ssk); +	u32 offset, incr, avail_len; + +	offset = tp->copied_seq - TCP_SKB_CB(skb)->seq; +	if (WARN_ON_ONCE(offset > skb->len)) +		goto out; -	incr = limit >= skb->len ? skb->len + fin : limit; +	avail_len = skb->len - offset; +	incr = limit >= avail_len ? avail_len + fin : limit; -	pr_debug("discarding=%d len=%d seq=%d", incr, skb->len, -		 subflow->map_subflow_seq); +	pr_debug("discarding=%d len=%d offset=%d seq=%d\n", incr, skb->len, +		 offset, subflow->map_subflow_seq);  	MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DUPDATA);  	tcp_sk(ssk)->copied_seq += incr; + +out:  	if (!before(tcp_sk(ssk)->copied_seq, TCP_SKB_CB(skb)->end_seq))  		sk_eat_skb(ssk, skb);  	if (mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) @@ -1238,12 +1255,16 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,  /* sched mptcp worker to remove the subflow if no more data is pending */  static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)  { -	if (likely(ssk->sk_state != TCP_CLOSE)) +	struct sock *sk = (struct sock *)msk; + +	if (likely(ssk->sk_state != TCP_CLOSE && +		   (ssk->sk_state != TCP_CLOSE_WAIT || +		    inet_sk_state_load(sk) != TCP_ESTABLISHED)))  		return;  	if (skb_queue_empty(&ssk->sk_receive_queue) &&  	    !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) -		mptcp_schedule_work((struct sock *)msk); +		mptcp_schedule_work(sk);  }  static bool subflow_can_fallback(struct mptcp_subflow_context *subflow) @@ -1320,7 +1341,7 @@ static bool subflow_check_data_avail(struct sock *ssk)  		old_ack = READ_ONCE(msk->ack_seq);  		ack_seq = mptcp_subflow_get_mapped_dsn(subflow); -		pr_debug("msk ack_seq=%llx subflow ack_seq=%llx", old_ack, +		pr_debug("msk ack_seq=%llx subflow ack_seq=%llx\n", old_ack,  			 ack_seq);  		if (unlikely(before64(ack_seq, old_ack))) {  			mptcp_subflow_discard_data(ssk, skb, old_ack - ack_seq); @@ -1392,7 +1413,7 @@ bool mptcp_subflow_data_available(struct sock *sk)  		subflow->map_valid = 0;  		WRITE_ONCE(subflow->data_avail, false); -		pr_debug("Done with mapping: seq=%u data_len=%u", +		pr_debug("Done with mapping: seq=%u data_len=%u\n",  			 subflow->map_subflow_seq,  			 subflow->map_data_len);  	} @@ -1502,7 +1523,7 @@ void mptcpv6_handle_mapped(struct sock *sk, bool mapped)  	target = mapped ? &subflow_v6m_specific : subflow_default_af_ops(sk); -	pr_debug("subflow=%p family=%d ops=%p target=%p mapped=%d", +	pr_debug("subflow=%p family=%d ops=%p target=%p mapped=%d\n",  		 subflow, sk->sk_family, icsk->icsk_af_ops, target, mapped);  	if (likely(icsk->icsk_af_ops == target)) @@ -1595,7 +1616,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,  		goto failed;  	mptcp_crypto_key_sha(subflow->remote_key, &remote_token, NULL); -	pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk, +	pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d\n", msk,  		 remote_token, local_id, remote_id);  	subflow->remote_token = remote_token;  	WRITE_ONCE(subflow->remote_id, remote_id); @@ -1730,7 +1751,7 @@ int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,  	SOCK_INODE(sf)->i_gid = SOCK_INODE(sk->sk_socket)->i_gid;  	subflow = mptcp_subflow_ctx(sf->sk); -	pr_debug("subflow=%p", subflow); +	pr_debug("subflow=%p\n", subflow);  	*new_sock = sf;  	sock_hold(sk); @@ -1759,7 +1780,7 @@ static struct mptcp_subflow_context *subflow_create_ctx(struct sock *sk,  	INIT_LIST_HEAD(&ctx->node);  	INIT_LIST_HEAD(&ctx->delegated_node); -	pr_debug("subflow=%p", ctx); +	pr_debug("subflow=%p\n", ctx);  	ctx->tcp_sock = sk;  	WRITE_ONCE(ctx->local_id, -1); @@ -1910,7 +1931,7 @@ static int subflow_ulp_init(struct sock *sk)  		goto out;  	} -	pr_debug("subflow=%p, family=%d", ctx, sk->sk_family); +	pr_debug("subflow=%p, family=%d\n", ctx, sk->sk_family);  	tp->is_mptcp = 1;  	ctx->icsk_af_ops = icsk->icsk_af_ops; @@ -2005,6 +2026,7 @@ static void subflow_ulp_clone(const struct request_sock *req,  		new_ctx->fully_established = 1;  		new_ctx->remote_key_valid = 1;  		new_ctx->backup = subflow_req->backup; +		new_ctx->request_bkup = subflow_req->request_bkup;  		WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id);  		new_ctx->token = subflow_req->token;  		new_ctx->thmac = subflow_req->thmac;  | 
