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

Merge branch 'mptcp-RM_ADDR-ADD_ADDR-enhancements'



Geliang Tang says:

====================
mptcp: RM_ADDR/ADD_ADDR enhancements

This series include two enhancements for the MPTCP path management,
namely RM_ADDR support and ADD_ADDR echo support, as specified by RFC
sections 3.4.1 and 3.4.2.

1 RM_ADDR support include 9 patches (1-3 and 8-13):

Patch 1 is the helper for patch 2, these two patches add the RM_ADDR
outgoing functions, which are derived from ADD_ADDR's corresponding
functions.

Patch 3 adds the RM_ADDR incoming logic, when RM_ADDR suboption is
received, close the subflow matching the rm_id, and update PM counter.

Patch 8 is the main remove routine. When the PM netlink removes an address,
we traverse all the existing msk sockets to find the relevant sockets. Then
trigger the RM_ADDR signal and remove the subflow which using this local
address, this subflow removing functions has been implemented in patch 9.

Finally, patches 10-13 are the self-tests for RM_ADDR.

2 ADD_ADDR echo support include 7 patches (4-7 and 14-16).

Patch 4 adds the ADD_ADDR echo logic, when the ADD_ADDR suboption has been
received, send out the same ADD_ADDR suboption with echo-flag, and no HMAC
included.

Patches 5 and 6 are the self-tests for ADD_ADDR echo. Patch 7 is a little
cleaning up.

Patch 14 and 15 are the helpers for patch 16. These three patches add
the ADD_ADDR retransmition when no ADD_ADDR echo is received.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 075c1568 00cfd77b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2195,6 +2195,8 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,

void sk_stop_timer(struct sock *sk, struct timer_list *timer);

void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer);

int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue,
			struct sk_buff *skb, unsigned int flags,
			void (*destructor)(struct sock *sk,
+7 −0
Original line number Diff line number Diff line
@@ -2947,6 +2947,13 @@ void sk_stop_timer(struct sock *sk, struct timer_list* timer)
}
EXPORT_SYMBOL(sk_stop_timer);

void sk_stop_timer_sync(struct sock *sk, struct timer_list *timer)
{
	if (del_timer_sync(timer))
		__sock_put(sk);
}
EXPORT_SYMBOL(sk_stop_timer_sync);

void sock_init_data(struct socket *sock, struct sock *sk)
{
	sk_init_common(sk);
+4 −0
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ static const struct snmp_mib mptcp_snmp_list[] = {
	SNMP_MIB_ITEM("OFOMerge", MPTCP_MIB_OFOMERGE),
	SNMP_MIB_ITEM("NoDSSInWindow", MPTCP_MIB_NODSSWINDOW),
	SNMP_MIB_ITEM("DuplicateData", MPTCP_MIB_DUPDATA),
	SNMP_MIB_ITEM("AddAddr", MPTCP_MIB_ADDADDR),
	SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD),
	SNMP_MIB_ITEM("RmAddr", MPTCP_MIB_RMADDR),
	SNMP_MIB_ITEM("RmSubflow", MPTCP_MIB_RMSUBFLOW),
	SNMP_MIB_SENTINEL
};

+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ enum linux_mptcp_mib_field {
	MPTCP_MIB_OFOMERGE,		/* Segments merged in OoO queue */
	MPTCP_MIB_NODSSWINDOW,		/* Segments not in MPTCP windows */
	MPTCP_MIB_DUPDATA,		/* Segments discarded due to duplicate DSS */
	MPTCP_MIB_ADDADDR,		/* Received ADD_ADDR with echo-flag=0 */
	MPTCP_MIB_ECHOADD,		/* Received ADD_ADDR with echo-flag=1 */
	MPTCP_MIB_RMADDR,		/* Received RM_ADDR */
	MPTCP_MIB_RMSUBFLOW,		/* Remove a subflow */
	__MPTCP_MIB_MAX
};

+63 −18
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <net/tcp.h>
#include <net/mptcp.h>
#include "protocol.h"
#include "mib.h"

static bool mptcp_cap_flag_sha256(u8 flags)
{
@@ -242,7 +243,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
		mp_opt->add_addr = 1;
		mp_opt->port = 0;
		mp_opt->addr_id = *ptr++;
		pr_debug("ADD_ADDR: id=%d", mp_opt->addr_id);
		pr_debug("ADD_ADDR: id=%d, echo=%d", mp_opt->addr_id, mp_opt->echo);
		if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) {
			memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4);
			ptr += 4;
@@ -571,7 +572,7 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
}
#endif

static bool mptcp_established_options_addr(struct sock *sk,
static bool mptcp_established_options_add_addr(struct sock *sk,
					       unsigned int *size,
					       unsigned int remaining,
					       struct mptcp_out_options *opts)
@@ -579,10 +580,11 @@ static bool mptcp_established_options_addr(struct sock *sk,
	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
	struct mptcp_addr_info saddr;
	bool echo;
	int len;

	if (!mptcp_pm_should_signal(msk) ||
	    !(mptcp_pm_addr_signal(msk, remaining, &saddr)))
	if (!mptcp_pm_should_add_signal(msk) ||
	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo)))
		return false;

	len = mptcp_add_addr_len(saddr.family);
@@ -594,22 +596,51 @@ static bool mptcp_established_options_addr(struct sock *sk,
	if (saddr.family == AF_INET) {
		opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
		opts->addr = saddr.addr;
		if (!echo) {
			opts->ahmac = add_addr_generate_hmac(msk->local_key,
							     msk->remote_key,
							     opts->addr_id,
							     &opts->addr);
		}
	}
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
	else if (saddr.family == AF_INET6) {
		opts->suboptions |= OPTION_MPTCP_ADD_ADDR6;
		opts->addr6 = saddr.addr6;
		if (!echo) {
			opts->ahmac = add_addr6_generate_hmac(msk->local_key,
							      msk->remote_key,
							      opts->addr_id,
							      &opts->addr6);
		}
	}
#endif
	pr_debug("addr_id=%d, ahmac=%llu", opts->addr_id, opts->ahmac);
	pr_debug("addr_id=%d, ahmac=%llu, echo=%d", opts->addr_id, opts->ahmac, echo);

	return true;
}

static bool mptcp_established_options_rm_addr(struct sock *sk,
					      unsigned int *size,
					      unsigned int remaining,
					      struct mptcp_out_options *opts)
{
	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
	u8 rm_id;

	if (!mptcp_pm_should_rm_signal(msk) ||
	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
		return false;

	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
		return false;

	*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
	opts->rm_id = rm_id;

	pr_debug("rm_id=%d", opts->rm_id);

	return true;
}
@@ -640,7 +671,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,

	*size += opt_size;
	remaining -= opt_size;
	if (mptcp_established_options_addr(sk, &opt_size, remaining, opts)) {
	if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
		*size += opt_size;
		remaining -= opt_size;
		ret = true;
	} else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
		*size += opt_size;
		remaining -= opt_size;
		ret = true;
@@ -854,11 +889,21 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
			addr.addr6 = mp_opt.addr6;
		}
#endif
		if (!mp_opt.echo)
		if (!mp_opt.echo) {
			mptcp_pm_add_addr_received(msk, &addr);
			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
		} else {
			mptcp_pm_del_add_timer(msk, &addr);
			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
		}
		mp_opt.add_addr = 0;
	}

	if (mp_opt.rm_addr) {
		mptcp_pm_rm_addr_received(msk, mp_opt.rm_id);
		mp_opt.rm_addr = 0;
	}

	if (!mp_opt.dss)
		return;

Loading