Commit ae9fdf6c authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mptcp-path-manager-fixes'



Mat Martineau says:

====================
mptcp: Path manager fixes for 5.19

The MPTCP userspace path manager is new in 5.19, and these patches fix
some issues in that new code.

Patches 1-3 fix path manager locking issues.

Patches 4 and 5 allow userspace path managers to change priority of
established subflows using the existing MPTCP_PM_CMD_SET_FLAGS generic
netlink command. Includes corresponding self test update.

Patches 6 and 7 fix accounting of available endpoint IDs and the
MPTCP_MIB_RMSUBFLOW counter.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 44d632d5 d2d21f17
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1584,6 +1584,9 @@ void mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
		*ptr++ = mptcp_option(MPTCPOPT_MP_PRIO,
				      TCPOLEN_MPTCP_PRIO,
				      opts->backup, TCPOPT_NOP);

		MPTCP_INC_STATS(sock_net((const struct sock *)tp),
				MPTCP_MIB_MPPRIOTX);
	}

mp_capable_done:
+33 −13
Original line number Diff line number Diff line
@@ -717,8 +717,9 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
	}
}

static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
				 struct mptcp_addr_info *addr,
				 struct mptcp_addr_info *rem,
				 u8 bkup)
{
	struct mptcp_subflow_context *subflow;
@@ -727,24 +728,29 @@ static int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,

	mptcp_for_each_subflow(msk, subflow) {
		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
		struct sock *sk = (struct sock *)msk;
		struct mptcp_addr_info local;
		struct mptcp_addr_info local, remote;
		bool slow;

		local_address((struct sock_common *)ssk, &local);
		if (!mptcp_addresses_equal(&local, addr, addr->port))
			continue;

		if (rem && rem->family != AF_UNSPEC) {
			remote_address((struct sock_common *)ssk, &remote);
			if (!mptcp_addresses_equal(&remote, rem, rem->port))
				continue;
		}

		slow = lock_sock_fast(ssk);
		if (subflow->backup != bkup)
			msk->last_snd = NULL;
		subflow->backup = bkup;
		subflow->send_mp_prio = 1;
		subflow->request_bkup = bkup;
		__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIOTX);

		spin_unlock_bh(&msk->pm.lock);
		pr_debug("send ack for mp_prio");
		mptcp_subflow_send_ack(ssk);
		spin_lock_bh(&msk->pm.lock);
		__mptcp_subflow_send_ack(ssk);
		unlock_sock_fast(ssk, slow);

		return 0;
	}
@@ -801,6 +807,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
			removed = true;
			__MPTCP_INC_STATS(sock_net(sk), rm_type);
		}
		if (rm_type == MPTCP_MIB_RMSUBFLOW)
			__set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap);
		if (!removed)
			continue;
@@ -1816,8 +1823,10 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,

	list.ids[list.nr++] = addr->id;

	spin_lock_bh(&msk->pm.lock);
	mptcp_pm_nl_rm_subflow_received(msk, &list);
	mptcp_pm_create_subflow_or_signal_addr(msk);
	spin_unlock_bh(&msk->pm.lock);
}

static int mptcp_nl_set_flags(struct net *net,
@@ -1835,12 +1844,10 @@ static int mptcp_nl_set_flags(struct net *net,
			goto next;

		lock_sock(sk);
		spin_lock_bh(&msk->pm.lock);
		if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
			ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, bkup);
			ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
		if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
			mptcp_pm_nl_fullmesh(msk, addr);
		spin_unlock_bh(&msk->pm.lock);
		release_sock(sk);

next:
@@ -1854,6 +1861,9 @@ static int mptcp_nl_set_flags(struct net *net,
static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
{
	struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, }, *entry;
	struct mptcp_pm_addr_entry remote = { .addr = { .family = AF_UNSPEC }, };
	struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
	struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
	struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
	struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
	u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
@@ -1866,6 +1876,12 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
	if (ret < 0)
		return ret;

	if (attr_rem) {
		ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote);
		if (ret < 0)
			return ret;
	}

	if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP)
		bkup = 1;
	if (addr.addr.family == AF_UNSPEC) {
@@ -1874,6 +1890,10 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
			return -EOPNOTSUPP;
	}

	if (token)
		return mptcp_userspace_pm_set_flags(sock_net(skb->sk),
						    token, &addr, &remote, bkup);

	spin_lock_bh(&pernet->lock);
	entry = __lookup_addr(pernet, &addr.addr, lookup_by_id);
	if (!entry) {
+38 −13
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 */

#include "protocol.h"
#include "mib.h"

void mptcp_free_local_addr_list(struct mptcp_sock *msk)
{
@@ -306,15 +307,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
				      const struct mptcp_addr_info *local,
				      const struct mptcp_addr_info *remote)
{
	struct sock *sk = &msk->sk.icsk_inet.sk;
	struct mptcp_subflow_context *subflow;
	struct sock *found = NULL;

	if (local->family != remote->family)
		return NULL;

	lock_sock(sk);

	mptcp_for_each_subflow(msk, subflow) {
		const struct inet_sock *issk;
		struct sock *ssk;
@@ -347,16 +344,11 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
		}

		if (issk->inet_sport == local->port &&
		    issk->inet_dport == remote->port) {
			found = ssk;
			goto found;
		}
		    issk->inet_dport == remote->port)
			return ssk;
	}

found:
	release_sock(sk);

	return found;
	return NULL;
}

int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
@@ -412,18 +404,51 @@ int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
	}

	sk = &msk->sk.icsk_inet.sk;
	lock_sock(sk);
	ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r);
	if (ssk) {
		struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);

		mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
		mptcp_close_ssk(sk, ssk, subflow);
		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
		err = 0;
	} else {
		err = -ESRCH;
	}
	release_sock(sk);

destroy_err:
	sock_put((struct sock *)msk);
	return err;
}

int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
				 struct mptcp_pm_addr_entry *loc,
				 struct mptcp_pm_addr_entry *rem, u8 bkup)
{
	struct mptcp_sock *msk;
	int ret = -EINVAL;
	u32 token_val;

	token_val = nla_get_u32(token);

	msk = mptcp_token_get_sock(net, token_val);
	if (!msk)
		return ret;

	if (!mptcp_pm_is_userspace(msk))
		goto set_flags_err;

	if (loc->addr.family == AF_UNSPEC ||
	    rem->addr.family == AF_UNSPEC)
		goto set_flags_err;

	lock_sock((struct sock *)msk);
	ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc->addr, &rem->addr, bkup);
	release_sock((struct sock *)msk);

set_flags_err:
	sock_put((struct sock *)msk);
	return ret;
}
+7 −2
Original line number Diff line number Diff line
@@ -506,13 +506,18 @@ static inline bool tcp_can_send_ack(const struct sock *ssk)
	       (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN));
}

void __mptcp_subflow_send_ack(struct sock *ssk)
{
	if (tcp_can_send_ack(ssk))
		tcp_send_ack(ssk);
}

void mptcp_subflow_send_ack(struct sock *ssk)
{
	bool slow;

	slow = lock_sock_fast(ssk);
	if (tcp_can_send_ack(ssk))
		tcp_send_ack(ssk);
	__mptcp_subflow_send_ack(ssk);
	unlock_sock_fast(ssk, slow);
}

+8 −1
Original line number Diff line number Diff line
@@ -607,6 +607,7 @@ void __init mptcp_subflow_init(void);
void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how);
void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
		     struct mptcp_subflow_context *subflow);
void __mptcp_subflow_send_ack(struct sock *ssk);
void mptcp_subflow_send_ack(struct sock *ssk);
void mptcp_subflow_reset(struct sock *ssk);
void mptcp_subflow_queue_clean(struct sock *ssk);
@@ -771,6 +772,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
			       const struct mptcp_rm_list *rm_list);
void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup);
void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq);
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
				 struct mptcp_addr_info *addr,
				 struct mptcp_addr_info *rem,
				 u8 bkup);
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
			      const struct mptcp_pm_addr_entry *entry);
void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
@@ -787,7 +792,9 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
						   unsigned int id,
						   u8 *flags, int *ifindex);

int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
				 struct mptcp_pm_addr_entry *loc,
				 struct mptcp_pm_addr_entry *rem, u8 bkup);
int mptcp_pm_announce_addr(struct mptcp_sock *msk,
			   const struct mptcp_addr_info *addr,
			   bool echo);
Loading