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

Merge branch 'mptcp-pm-listener-events-selftests-cleanup'

Matthieu Baerts says:

====================
mptcp: PM listener events + selftests cleanup

Thanks to the patch 6/11, the MPTCP path manager now sends Netlink events
when MPTCP listening sockets are created and closed. The reason why it is
needed is explained in the linked ticket [1]:

  MPTCP for Linux, when not using the in-kernel PM, depends on the
  userspace PM to create extra listening sockets before announcing
  addresses and ports. Let's call these "PM listeners".

  With the existing MPTCP netlink events, a userspace PM can create
  PM listeners at startup time, or in response to an incoming connection.
  Creating sockets in response to connections is not optimal: ADD_ADDRs
  can't be sent until the sockets are created and listen()ed, and if all
  connections are closed then it may not be clear to the userspace
  PM daemon that PM listener sockets should be cleaned up.

  Hence this feature request: to add MPTCP netlink events for listening
  socket close & create, so PM listening sockets can be managed based
  on application activity.

  [1] https://github.com/multipath-tcp/mptcp_net-next/issues/313

Selftests for these new Netlink events have been added in patches 9,11/11.

The remaining patches introduce different cleanups and small improvements
in MPTCP selftests to ease the maintenance and the addition of new tests.
====================

Link: https://lore.kernel.org/r/20221130140637.409926-1-matthieu.baerts@tessares.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a802073d 178d0232
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -160,6 +160,12 @@ struct mptcp_info {
 *                           daddr4 | daddr6, sport, dport, backup, if_idx
 *                           [, error]
 * The priority of a subflow has changed. 'error' should not be set.
 *
 * MPTCP_EVENT_LISTENER_CREATED: family, sport, saddr4 | saddr6
 * A new PM listener is created.
 *
 * MPTCP_EVENT_LISTENER_CLOSED: family, sport, saddr4 | saddr6
 * A PM listener is closed.
 */
enum mptcp_event_type {
	MPTCP_EVENT_UNSPEC = 0,
@@ -174,6 +180,9 @@ enum mptcp_event_type {
	MPTCP_EVENT_SUB_CLOSED = 11,

	MPTCP_EVENT_SUB_PRIORITY = 13,

	MPTCP_EVENT_LISTENER_CREATED = 15,
	MPTCP_EVENT_LISTENER_CLOSED = 16,
};

enum mptcp_event_attr {
+57 −0
Original line number Diff line number Diff line
@@ -1029,6 +1029,8 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
	if (err)
		return err;

	mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);

	return 0;
}

@@ -2152,6 +2154,58 @@ void mptcp_event_addr_announced(const struct sock *ssk,
	kfree_skb(skb);
}

void mptcp_event_pm_listener(const struct sock *ssk,
			     enum mptcp_event_type event)
{
	const struct inet_sock *issk = inet_sk(ssk);
	struct net *net = sock_net(ssk);
	struct nlmsghdr *nlh;
	struct sk_buff *skb;

	if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
		return;

	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!skb)
		return;

	nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, event);
	if (!nlh)
		goto nla_put_failure;

	if (nla_put_u16(skb, MPTCP_ATTR_FAMILY, ssk->sk_family))
		goto nla_put_failure;

	if (nla_put_be16(skb, MPTCP_ATTR_SPORT, issk->inet_sport))
		goto nla_put_failure;

	switch (ssk->sk_family) {
	case AF_INET:
		if (nla_put_in_addr(skb, MPTCP_ATTR_SADDR4, issk->inet_saddr))
			goto nla_put_failure;
		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))
			goto nla_put_failure;
		break;
	}
#endif
	default:
		WARN_ON_ONCE(1);
		goto nla_put_failure;
	}

	genlmsg_end(skb, nlh);
	mptcp_nl_mcast_send(net, skb, GFP_KERNEL);
	return;

nla_put_failure:
	kfree_skb(skb);
}

void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
		 const struct sock *ssk, gfp_t gfp)
{
@@ -2197,6 +2251,9 @@ void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
		if (mptcp_event_sub_closed(skb, msk, ssk) < 0)
			goto nla_put_failure;
		break;
	case MPTCP_EVENT_LISTENER_CREATED:
	case MPTCP_EVENT_LISTENER_CLOSED:
		break;
	}

	genlmsg_end(skb, nlh);
+3 −0
Original line number Diff line number Diff line
@@ -2355,6 +2355,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
			tcp_set_state(ssk, TCP_CLOSE);
			mptcp_subflow_queue_clean(ssk);
			inet_csk_listen_stop(ssk);
			mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
		}
		__tcp_close(ssk, 0);

@@ -3647,6 +3648,8 @@ static int mptcp_listen(struct socket *sock, int backlog)
	if (!err)
		mptcp_copy_inaddrs(sock->sk, ssock->sk);

	mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);

unlock:
	release_sock(sock->sk);
	return err;
+2 −0
Original line number Diff line number Diff line
@@ -839,6 +839,8 @@ void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
		 const struct sock *ssk, gfp_t gfp);
void mptcp_event_addr_announced(const struct sock *ssk, const struct mptcp_addr_info *info);
void mptcp_event_addr_removed(const struct mptcp_sock *msk, u8 id);
void mptcp_event_pm_listener(const struct sock *ssk,
			     enum mptcp_event_type event);
bool mptcp_userspace_pm_active(const struct mptcp_sock *msk);

void mptcp_fastopen_gen_msk_ackseq(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
+1 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

sec=$(date +%s)
rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
ns="ns1-$rndh"
ksft_skip=4
Loading