Commit 964efdab authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'mptcp-advertisement-reliability-improvement-and-misc-updates'

Mat Martineau says:

====================
mptcp: Advertisement reliability improvement and misc. updates

Patch 1 adds a helpful debug tracepoint for outgoing MPTCP packets.

Patch 2 is a small "magic number" refactor.

Patches 3 & 4 refactor parts of the mptcp_join.sh selftest. No change in
test coverage.

Patch 5 ensures only advertised address IDs are un-advertised.

Patches 6-8 improve handling of an edge case where endpoint IDs need to
be created on-the-fly when adding subflows. Includes selftest coverage.

Patch 9 adds validation of the fullmesh flag in a MPTCP netlink command,
which was overlooked when this flag was introduced for 5.18.
====================

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


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d307eab5 0dc626e5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -115,6 +115,10 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
		  __entry->csum_reqd)
);

DEFINE_EVENT(mptcp_dump_mpext, mptcp_sendmsg_frag,
	TP_PROTO(struct mptcp_ext *mpext),
	TP_ARGS(mpext));

DEFINE_EVENT(mptcp_dump_mpext, get_mapping_status,
	TP_PROTO(struct mptcp_ext *mpext),
	TP_ARGS(mpext));
+1 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ enum {
#define MPTCP_PM_ADDR_FLAG_SUBFLOW			(1 << 1)
#define MPTCP_PM_ADDR_FLAG_BACKUP			(1 << 2)
#define MPTCP_PM_ADDR_FLAG_FULLMESH			(1 << 3)
#define MPTCP_PM_ADDR_FLAG_IMPLICIT			(1 << 4)

enum {
	MPTCP_PM_CMD_UNSPEC,
+54 −36
Original line number Diff line number Diff line
@@ -83,16 +83,6 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
	return a->port == b->port;
}

static bool address_zero(const struct mptcp_addr_info *addr)
{
	struct mptcp_addr_info zero;

	memset(&zero, 0, sizeof(zero));
	zero.family = addr->family;

	return addresses_equal(addr, &zero, true);
}

static void local_address(const struct sock_common *skc,
			  struct mptcp_addr_info *addr)
{
@@ -877,10 +867,18 @@ static bool address_use_port(struct mptcp_pm_addr_entry *entry)
		MPTCP_PM_ADDR_FLAG_SIGNAL;
}

/* caller must ensure the RCU grace period is already elapsed */
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
{
	if (entry->lsk)
		sock_release(entry->lsk);
	kfree(entry);
}

static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
					     struct mptcp_pm_addr_entry *entry)
{
	struct mptcp_pm_addr_entry *cur;
	struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
	unsigned int addr_max;
	int ret = -EINVAL;

@@ -901,8 +899,22 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
	list_for_each_entry(cur, &pernet->local_addr_list, list) {
		if (addresses_equal(&cur->addr, &entry->addr,
				    address_use_port(entry) &&
				    address_use_port(cur)))
				    address_use_port(cur))) {
			/* allow replacing the exiting endpoint only if such
			 * endpoint is an implicit one and the user-space
			 * did not provide an endpoint id
			 */
			if (!(cur->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT))
				goto out;
			if (entry->addr.id)
				goto out;

			pernet->addrs--;
			entry->addr.id = cur->addr.id;
			list_del_rcu(&cur->list);
			del_entry = cur;
			break;
		}
	}

	if (!entry->addr.id) {
@@ -938,6 +950,12 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,

out:
	spin_unlock_bh(&pernet->lock);

	/* just replaced an existing entry, free it */
	if (del_entry) {
		synchronize_rcu();
		__mptcp_pm_release_addr_entry(del_entry);
	}
	return ret;
}

@@ -1011,9 +1029,6 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
	if (addresses_equal(&msk_local, &skc_local, false))
		return 0;

	if (address_zero(&skc_local))
		return 0;

	pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);

	rcu_read_lock();
@@ -1036,7 +1051,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
	entry->addr.id = 0;
	entry->addr.port = 0;
	entry->ifindex = 0;
	entry->flags = 0;
	entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
	entry->lsk = NULL;
	ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
	if (ret < 0)
@@ -1249,6 +1264,17 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
		return -EINVAL;
	}

	if (addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
	    addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
		GENL_SET_ERR_MSG(info, "flags mustn't have both signal and fullmesh");
		return -EINVAL;
	}

	if (addr.flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
		GENL_SET_ERR_MSG(info, "can't create IMPLICIT endpoint");
		return -EINVAL;
	}

	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry) {
		GENL_SET_ERR_MSG(info, "can't allocate addr");
@@ -1333,11 +1359,12 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
}

static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
						   struct mptcp_addr_info *addr)
						   const struct mptcp_pm_addr_entry *entry)
{
	struct mptcp_sock *msk;
	long s_slot = 0, s_num = 0;
	const struct mptcp_addr_info *addr = &entry->addr;
	struct mptcp_rm_list list = { .nr = 0 };
	long s_slot = 0, s_num = 0;
	struct mptcp_sock *msk;

	pr_debug("remove_id=%d", addr->id);

@@ -1354,7 +1381,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,

		lock_sock(sk);
		remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
		mptcp_pm_remove_anno_addr(msk, addr, remove_subflow);
		mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
					  !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
		if (remove_subflow)
			mptcp_pm_remove_subflow(msk, &list);
		release_sock(sk);
@@ -1367,14 +1395,6 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
	return 0;
}

/* caller must ensure the RCU grace period is already elapsed */
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
{
	if (entry->lsk)
		sock_release(entry->lsk);
	kfree(entry);
}

static int mptcp_nl_remove_id_zero_address(struct net *net,
					   struct mptcp_addr_info *addr)
{
@@ -1451,7 +1471,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
	__clear_bit(entry->addr.id, pernet->id_bitmap);
	spin_unlock_bh(&pernet->lock);

	mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
	mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), entry);
	synchronize_rcu();
	__mptcp_pm_release_addr_entry(entry);

@@ -1466,15 +1486,13 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,

	list_for_each_entry(entry, rm_list, list) {
		if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
		    alist.nr < MPTCP_RM_IDS_MAX &&
		    slist.nr < MPTCP_RM_IDS_MAX) {
			alist.ids[alist.nr++] = entry->addr.id;
		    slist.nr < MPTCP_RM_IDS_MAX)
			slist.ids[slist.nr++] = entry->addr.id;
		} else if (remove_anno_list_by_saddr(msk, &entry->addr) &&
			 alist.nr < MPTCP_RM_IDS_MAX) {

		if (remove_anno_list_by_saddr(msk, &entry->addr) &&
		    alist.nr < MPTCP_RM_IDS_MAX)
			alist.ids[alist.nr++] = entry->addr.id;
	}
	}

	if (alist.nr) {
		spin_lock_bh(&msk->pm.lock);
+4 −0
Original line number Diff line number Diff line
@@ -117,6 +117,9 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
	list_add(&subflow->node, &msk->conn_list);
	sock_hold(ssock->sk);
	subflow->request_mptcp = 1;

	/* This is the first subflow, always with id 0 */
	subflow->local_id_valid = 1;
	mptcp_sock_graft(msk->first, sk->sk_socket);

	return 0;
@@ -1356,6 +1359,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
out:
	if (READ_ONCE(msk->csum_enabled))
		mptcp_update_data_checksum(skb, copy);
	trace_mptcp_sendmsg_frag(mpext);
	mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
	return copy;
}
+2 −1
Original line number Diff line number Diff line
@@ -442,7 +442,8 @@ struct mptcp_subflow_context {
		rx_eof : 1,
		can_ack : 1,        /* only after processing the remote a key */
		disposable : 1,	    /* ctx can be free at ulp release time */
		stale : 1;	    /* unable to snd/rcv data, do not use for xmit */
		stale : 1,	    /* unable to snd/rcv data, do not use for xmit */
		local_id_valid : 1; /* local_id is correctly initialized */
	enum mptcp_data_avail data_avail;
	u32	remote_nonce;
	u64	thmac;
Loading