Commit 7842f3d1 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'mptcp-pm-misc-cleanups-part-3'

Matthieu Baerts says:

====================
mptcp: pm: misc cleanups, part 3

These cleanups lead the way to the unification of the path-manager
interfaces, and allow future extensions. The following patches are not
all linked to each others, but are all related to the path-managers,
except the last three.

- Patch 1: remove unused returned value in mptcp_nl_set_flags().
- Patch 2: new flag: avoid iterating over all connections if not needed.
- Patch 3: add a build check making sure there is enough space in cb-ctx.
- Patch 4: new mptcp_pm_genl_fill_addr helper to reduce duplicated code.
- Patch 5: simplify userspace_pm_append_new_local_addr helper.
- Patch 6: drop unneeded inet6_sk().
- Patch 7: use ipv6_addr_equal() instead of !ipv6_addr_cmp()
- Patch 8: scheduler: split an interface in two.
- Patch 9: scheduler: save 64 bytes of currently unused data.
- Patch 10: small optimisation to exit early in case of retransmissions.
====================

Link: https://patch.msgid.link/20250221-net-next-mptcp-pm-misc-cleanup-3-v1-0-2b70ab1cee79@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 8f3f4464 8275ac79
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -103,13 +103,14 @@ struct mptcp_out_options {
#define MPTCP_SUBFLOWS_MAX	8

struct mptcp_sched_data {
	bool	reinject;
	u8	subflows;
	struct mptcp_subflow_context *contexts[MPTCP_SUBFLOWS_MAX];
};

struct mptcp_sched_ops {
	int (*get_subflow)(struct mptcp_sock *msk,
	int (*get_send)(struct mptcp_sock *msk,
			struct mptcp_sched_data *data);
	int (*get_retrans)(struct mptcp_sock *msk,
			   struct mptcp_sched_data *data);

	char			name[MPTCP_SCHED_NAME_MAX];
+17 −13
Original line number Diff line number Diff line
@@ -401,16 +401,23 @@ void mptcp_active_enable(struct sock *sk)
void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
{
	struct mptcp_subflow_context *subflow;
	u8 timeouts, to_max;
	struct net *net;

	if (!sk_is_mptcp(ssk))
	/* Only check MPTCP SYN ... */
	if (likely(!sk_is_mptcp(ssk) || ssk->sk_state != TCP_SYN_SENT))
		return;

	subflow = mptcp_subflow_ctx(ssk);

	if (subflow->request_mptcp && ssk->sk_state == TCP_SYN_SENT) {
		struct net *net = sock_net(ssk);
		u8 timeouts, to_max;
	/* ... + MP_CAPABLE */
	if (!subflow->request_mptcp) {
		/* Mark as blackhole iif the 1st non-MPTCP SYN is accepted */
		subflow->mpc_drop = 0;
		return;
	}

	net = sock_net(ssk);
	timeouts = inet_csk(ssk)->icsk_retransmits;
	to_max = mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback;

@@ -419,9 +426,6 @@ void mptcp_active_detect_blackhole(struct sock *ssk, bool expired)
		subflow->mpc_drop = 1;
		mptcp_subflow_early_fallback(mptcp_sk(subflow->conn), subflow);
	}
	} else if (ssk->sk_state == TCP_SYN_SENT) {
		subflow->mpc_drop = 0;
	}
}

static int __net_init mptcp_net_init(struct net *net)
+21 −0
Original line number Diff line number Diff line
@@ -489,6 +489,27 @@ int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
	return ret;
}

int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
			    struct netlink_callback *cb,
			    struct mptcp_pm_addr_entry *entry)
{
	void *hdr;

	hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
			  cb->nlh->nlmsg_seq, &mptcp_genl_family,
			  NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
	if (!hdr)
		return -EINVAL;

	if (mptcp_nl_fill_addr(msg, entry) < 0) {
		genlmsg_cancel(msg, hdr);
		return -EINVAL;
	}

	genlmsg_end(msg, hdr);
	return 0;
}

static int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)
{
	const struct genl_info *info = genl_info_dump(cb);
+16 −30
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
			addr_equals = a->addr.s_addr == b->addr.s_addr;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
		else
			addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
			addr_equals = ipv6_addr_equal(&a->addr6, &b->addr6);
	} else if (a->family == AF_INET) {
		if (ipv6_addr_v4mapped(&b->addr6))
			addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
@@ -1798,7 +1798,6 @@ int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
	struct mptcp_pm_addr_entry *entry;
	struct pm_nl_pernet *pernet;
	int id = cb->args[0];
	void *hdr;
	int i;

	pernet = pm_nl_get_pernet(net);
@@ -1813,19 +1812,10 @@ int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
			if (entry->addr.id <= id)
				continue;

			hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
					  cb->nlh->nlmsg_seq, &mptcp_genl_family,
					  NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
			if (!hdr)
			if (mptcp_pm_genl_fill_addr(msg, cb, entry) < 0)
				break;

			if (mptcp_nl_fill_addr(msg, entry) < 0) {
				genlmsg_cancel(msg, hdr);
				break;
			}

			id = entry->addr.id;
			genlmsg_end(msg, hdr);
		}
	}
	rcu_read_unlock();
@@ -1922,13 +1912,16 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
	spin_unlock_bh(&msk->pm.lock);
}

static int mptcp_nl_set_flags(struct net *net,
			      struct mptcp_addr_info *addr,
			      u8 bkup, u8 changed)
static void mptcp_nl_set_flags(struct net *net, struct mptcp_addr_info *addr,
			       u8 flags, u8 changed)
{
	u8 is_subflow = !!(flags & MPTCP_PM_ADDR_FLAG_SUBFLOW);
	u8 bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
	long s_slot = 0, s_num = 0;
	struct mptcp_sock *msk;
	int ret = -EINVAL;

	if (changed == MPTCP_PM_ADDR_FLAG_FULLMESH && !is_subflow)
		return;

	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
		struct sock *sk = (struct sock *)msk;
@@ -1938,8 +1931,9 @@ static int mptcp_nl_set_flags(struct net *net,

		lock_sock(sk);
		if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
			ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
		if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
			mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
		/* Subflows will only be recreated if the SUBFLOW flag is set */
		if (is_subflow && (changed & MPTCP_PM_ADDR_FLAG_FULLMESH))
			mptcp_pm_nl_fullmesh(msk, addr);
		release_sock(sk);

@@ -1948,7 +1942,7 @@ static int mptcp_nl_set_flags(struct net *net,
		cond_resched();
	}

	return ret;
	return;
}

int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
@@ -1961,7 +1955,6 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
	struct mptcp_pm_addr_entry *entry;
	struct pm_nl_pernet *pernet;
	u8 lookup_by_id = 0;
	u8 bkup = 0;

	pernet = pm_nl_get_pernet(net);

@@ -1974,9 +1967,6 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
		}
	}

	if (local->flags & MPTCP_PM_ADDR_FLAG_BACKUP)
		bkup = 1;

	spin_lock_bh(&pernet->lock);
	entry = lookup_by_id ? __lookup_addr_by_id(pernet, local->addr.id) :
			       __lookup_addr(pernet, &local->addr);
@@ -1998,7 +1988,7 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
	*local = *entry;
	spin_unlock_bh(&pernet->lock);

	mptcp_nl_set_flags(net, &local->addr, bkup, changed);
	mptcp_nl_set_flags(net, &local->addr, entry->flags, changed);
	return 0;
}

@@ -2032,9 +2022,7 @@ static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk)
		break;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
	case AF_INET6: {
		const struct ipv6_pinfo *np = inet6_sk(ssk);

		if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
		if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
			return -EMSGSIZE;
		if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &ssk->sk_v6_daddr))
			return -EMSGSIZE;
@@ -2261,9 +2249,7 @@ void mptcp_event_pm_listener(const struct sock *ssk,
		break;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
	case AF_INET6: {
		const struct ipv6_pinfo *np = inet6_sk(ssk);

		if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
		if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &issk->pinet6->saddr))
			goto nla_put_failure;
		break;
	}
+7 −22
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
						    bool needs_id)
{
	DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
	struct mptcp_pm_addr_entry *match = NULL;
	struct sock *sk = (struct sock *)msk;
	struct mptcp_pm_addr_entry *e;
	bool addr_match = false;
@@ -63,16 +62,12 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
		if (addr_match && entry->addr.id == 0 && needs_id)
			entry->addr.id = e->addr.id;
		id_match = (e->addr.id == entry->addr.id);
		if (addr_match && id_match) {
			match = e;
		if (addr_match || id_match)
			break;
		} else if (addr_match || id_match) {
			break;
		}
		__set_bit(e->addr.id, id_bitmap);
	}

	if (!match && !addr_match && !id_match) {
	if (!addr_match && !id_match) {
		/* Memory for the entry is allocated from the
		 * sock option buffer.
		 */
@@ -90,7 +85,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
		list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
		msk->pm.local_addr_used++;
		ret = e->addr.id;
	} else if (match) {
	} else if (addr_match && id_match) {
		ret = entry->addr.id;
	}

@@ -465,9 +460,7 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
			break;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
		case AF_INET6: {
			const struct ipv6_pinfo *pinfo = inet6_sk(ssk);

			if (!ipv6_addr_equal(&local->addr6, &pinfo->saddr) ||
			if (!ipv6_addr_equal(&local->addr6, &issk->pinet6->saddr) ||
			    !ipv6_addr_equal(&remote->addr6, &ssk->sk_v6_daddr))
				continue;
			break;
@@ -641,7 +634,8 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
	struct mptcp_sock *msk;
	int ret = -EINVAL;
	struct sock *sk;
	void *hdr;

	BUILD_BUG_ON(sizeof(struct id_bitmap) > sizeof(cb->ctx));

	bitmap = (struct id_bitmap *)cb->ctx;

@@ -657,19 +651,10 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
		if (test_bit(entry->addr.id, bitmap->map))
			continue;

		hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
				  cb->nlh->nlmsg_seq, &mptcp_genl_family,
				  NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
		if (!hdr)
		if (mptcp_pm_genl_fill_addr(msg, cb, entry) < 0)
			break;

		if (mptcp_nl_fill_addr(msg, entry) < 0) {
			genlmsg_cancel(msg, hdr);
			break;
		}

		__set_bit(entry->addr.id, bitmap->map);
		genlmsg_end(msg, hdr);
	}
	spin_unlock_bh(&msk->pm.lock);
	release_sock(sk);
Loading