Commit ebf32282 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'mptcp-another-set-of-miscellaneous-mptcp-fixes'

Mat Martineau says:

====================
mptcp: Another set of miscellaneous MPTCP fixes

This is another collection of MPTCP fixes and enhancements that we have
tested in the MPTCP tree:

Patch 1 cleans up cgroup attachment for in-kernel subflow sockets.

Patches 2 and 3 make sure that deletion of advertised addresses by an
MPTCP path manager when flushing all addresses behaves similarly to the
remove-single-address operation, and adds related tests.

Patches 4 and 8 do some minor cleanup.

Patches 5-7 add MPTCP_FASTCLOSE functionality. Note that patch 6 adds MPTCP
option parsing to tcp_reset().

Patch 9 optimizes skb size for outgoing MPTCP packets.
====================

Link: https://lore.kernel.org/r/20201210222506.222251-1-mathew.j.martineau@linux.intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents efc36d3c 15e6ca97
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -611,7 +611,7 @@ void tcp_skb_collapse_tstamp(struct sk_buff *skb,
/* tcp_input.c */
void tcp_rearm_rto(struct sock *sk);
void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req);
void tcp_reset(struct sock *sk);
void tcp_reset(struct sock *sk, struct sk_buff *skb);
void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
void tcp_fin(struct sock *sk);

+8 −5
Original line number Diff line number Diff line
@@ -4218,10 +4218,13 @@ static inline bool tcp_sequence(const struct tcp_sock *tp, u32 seq, u32 end_seq)
}

/* When we get a reset we do this. */
void tcp_reset(struct sock *sk)
void tcp_reset(struct sock *sk, struct sk_buff *skb)
{
	trace_tcp_receive_reset(sk);

	if (sk_is_mptcp(sk))
		mptcp_incoming_options(sk, skb);

	/* We want the right error as BSD sees it (and indeed as we do). */
	switch (sk->sk_state) {
	case TCP_SYN_SENT:
@@ -5604,7 +5607,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
						  &tp->last_oow_ack_time))
				tcp_send_dupack(sk, skb);
		} else if (tcp_reset_check(sk, skb)) {
			tcp_reset(sk);
			tcp_reset(sk, skb);
		}
		goto discard;
	}
@@ -5640,7 +5643,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
		}

		if (rst_seq_match)
			tcp_reset(sk);
			tcp_reset(sk, skb);
		else {
			/* Disable TFO if RST is out-of-order
			 * and no data has been received
@@ -6077,7 +6080,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
		 */

		if (th->rst) {
			tcp_reset(sk);
			tcp_reset(sk, skb);
			goto discard;
		}

@@ -6519,7 +6522,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
			if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
			    after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
				NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
				tcp_reset(sk);
				tcp_reset(sk, skb);
				return 1;
			}
		}
+1 −1
Original line number Diff line number Diff line
@@ -801,7 +801,7 @@ embryonic_reset:
		req->rsk_ops->send_reset(sk, skb);
	} else if (fastopen) { /* received a valid RST pkt */
		reqsk_fastopen_remove(sk, req, true);
		tcp_reset(sk);
		tcp_reset(sk, skb);
	}
	if (!fastopen) {
		inet_csk_reqsk_queue_drop(sk, req);
+17 −0
Original line number Diff line number Diff line
@@ -282,6 +282,16 @@ static void mptcp_parse_option(const struct sk_buff *skb,
		pr_debug("RM_ADDR: id=%d", mp_opt->rm_id);
		break;

	case MPTCPOPT_MP_FASTCLOSE:
		if (opsize != TCPOLEN_MPTCP_FASTCLOSE)
			break;

		ptr += 2;
		mp_opt->rcvr_key = get_unaligned_be64(ptr);
		ptr += 8;
		mp_opt->fastclose = 1;
		break;

	default:
		break;
	}
@@ -299,6 +309,7 @@ void mptcp_get_options(const struct sk_buff *skb,
	mp_opt->mp_join = 0;
	mp_opt->add_addr = 0;
	mp_opt->ahmac = 0;
	mp_opt->fastclose = 0;
	mp_opt->port = 0;
	mp_opt->rm_addr = 0;
	mp_opt->dss = 0;
@@ -942,6 +953,12 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
	if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
		return;

	if (mp_opt.fastclose &&
	    msk->local_key == mp_opt.rcvr_key) {
		WRITE_ONCE(msk->rcv_fastclose, true);
		mptcp_schedule_work((struct sock *)msk);
	}

	if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) {
		struct mptcp_addr_info addr;

+12 −9
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ select_local_address(const struct pm_nl_pernet *pernet,
	struct mptcp_pm_addr_entry *entry, *ret = NULL;

	rcu_read_lock();
	spin_lock_bh(&msk->join_list_lock);
	__mptcp_flush_join_list(msk);
	list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
		if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
			continue;
@@ -144,13 +144,11 @@ select_local_address(const struct pm_nl_pernet *pernet,
		 * pending join
		 */
		if (entry->addr.family == ((struct sock *)msk)->sk_family &&
		    !lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
		    !lookup_subflow_by_saddr(&msk->join_list, &entry->addr)) {
		    !lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
			ret = entry;
			break;
		}
	}
	spin_unlock_bh(&msk->join_list_lock);
	rcu_read_unlock();
	return ret;
}
@@ -867,13 +865,14 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
	return ret;
}

static void __flush_addrs(struct pm_nl_pernet *pernet)
static void __flush_addrs(struct net *net, struct list_head *list)
{
	while (!list_empty(&pernet->local_addr_list)) {
	while (!list_empty(list)) {
		struct mptcp_pm_addr_entry *cur;

		cur = list_entry(pernet->local_addr_list.next,
		cur = list_entry(list->next,
				 struct mptcp_pm_addr_entry, list);
		mptcp_nl_remove_subflow_and_signal_addr(net, &cur->addr);
		list_del_rcu(&cur->list);
		kfree_rcu(cur, rcu);
	}
@@ -890,11 +889,13 @@ static void __reset_counters(struct pm_nl_pernet *pernet)
static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
{
	struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
	LIST_HEAD(free_list);

	spin_lock_bh(&pernet->lock);
	__flush_addrs(pernet);
	list_splice_init(&pernet->local_addr_list, &free_list);
	__reset_counters(pernet);
	spin_unlock_bh(&pernet->lock);
	__flush_addrs(sock_net(skb->sk), &free_list);
	return 0;
}

@@ -1156,10 +1157,12 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
	struct net *net;

	list_for_each_entry(net, net_list, exit_list) {
		struct pm_nl_pernet *pernet = net_generic(net, pm_nl_pernet_id);

		/* net is removed from namespace list, can't race with
		 * other modifiers
		 */
		__flush_addrs(net_generic(net, pm_nl_pernet_id));
		__flush_addrs(net, &pernet->local_addr_list);
	}
}

Loading