Skip to content

Commit

Permalink
Merge branch 'mptcp-Include-multiple-address-ids-in-RM_ADDR'
Browse files Browse the repository at this point in the history
Mat Martineau says:

====================
mptcp: Include multiple address ids in RM_ADDR

Here's a patch series from the MPTCP tree that extends the capabilities
of the MPTCP RM_ADDR header.

MPTCP peers can exchange information about their IP addresses that are
available for additional MPTCP subflows. IP addresses are advertised
with an ADD_ADDR header type, and those advertisements are revoked with
the RM_ADDR header type. RFC 8684 allows the RM_ADDR header to include
more than one address ID, so multiple advertisements can be revoked in a
single header. Previous kernel versions have only used RM_ADDR with a
single address ID, so multiple removals required multiple packets.

Patches 1-4 plumb address id list structures around the MPTCP code,
where before only a single address ID was passed.

Patches 5-8 make use of the address lists at the path manager layer that
tracks available addresses for both peers.

Patches 9-11 update the selftests to cover the new use of RM_ADDR with
multiple address IDs.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 13, 2021
2 parents e9e90a7 + d2c4333 commit 7c67882
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 93 deletions.
9 changes: 8 additions & 1 deletion include/net/mptcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ struct mptcp_ext {
/* one byte hole */
};

#define MPTCP_RM_IDS_MAX 8

struct mptcp_rm_list {
u8 ids[MPTCP_RM_IDS_MAX];
u8 nr;
};

struct mptcp_out_options {
#if IS_ENABLED(CONFIG_MPTCP)
u16 suboptions;
Expand All @@ -48,7 +55,7 @@ struct mptcp_out_options {
u8 addr_id;
u16 port;
u64 ahmac;
u8 rm_id;
struct mptcp_rm_list rm_list;
u8 join_id;
u8 backup;
u32 nonce;
Expand Down
47 changes: 35 additions & 12 deletions net/mptcp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
int expected_opsize;
u8 version;
u8 flags;
u8 i;

switch (subtype) {
case MPTCPOPT_MP_CAPABLE:
Expand Down Expand Up @@ -272,14 +273,17 @@ static void mptcp_parse_option(const struct sk_buff *skb,
break;

case MPTCPOPT_RM_ADDR:
if (opsize != TCPOLEN_MPTCP_RM_ADDR_BASE)
if (opsize < TCPOLEN_MPTCP_RM_ADDR_BASE + 1 ||
opsize > TCPOLEN_MPTCP_RM_ADDR_BASE + MPTCP_RM_IDS_MAX)
break;

ptr++;

mp_opt->rm_addr = 1;
mp_opt->rm_id = *ptr++;
pr_debug("RM_ADDR: id=%d", mp_opt->rm_id);
mp_opt->rm_list.nr = opsize - TCPOLEN_MPTCP_RM_ADDR_BASE;
for (i = 0; i < mp_opt->rm_list.nr; i++)
mp_opt->rm_list.ids[i] = *ptr++;
pr_debug("RM_ADDR: rm_list_nr=%d", mp_opt->rm_list.nr);
break;

case MPTCPOPT_MP_PRIO:
Expand Down Expand Up @@ -674,20 +678,25 @@ static bool mptcp_established_options_rm_addr(struct sock *sk,
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
u8 rm_id;
struct mptcp_rm_list rm_list;
int i, len;

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

if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
len = mptcp_rm_addr_len(&rm_list);
if (len < 0)
return false;
if (remaining < len)
return false;

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

pr_debug("rm_id=%d", opts->rm_id);
for (i = 0; i < opts->rm_list.nr; i++)
pr_debug("rm_list_ids[%d]=%d", i, opts->rm_list.ids[i]);

return true;
}
Expand Down Expand Up @@ -1038,7 +1047,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
}

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

Expand Down Expand Up @@ -1217,9 +1226,23 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
}

if (OPTION_MPTCP_RM_ADDR & opts->suboptions) {
u8 i = 1;

*ptr++ = mptcp_option(MPTCPOPT_RM_ADDR,
TCPOLEN_MPTCP_RM_ADDR_BASE,
0, opts->rm_id);
TCPOLEN_MPTCP_RM_ADDR_BASE + opts->rm_list.nr,
0, opts->rm_list.ids[0]);

while (i < opts->rm_list.nr) {
u8 id1, id2, id3, id4;

id1 = opts->rm_list.ids[i];
id2 = i + 1 < opts->rm_list.nr ? opts->rm_list.ids[i + 1] : TCPOPT_NOP;
id3 = i + 2 < opts->rm_list.nr ? opts->rm_list.ids[i + 2] : TCPOPT_NOP;
id4 = i + 3 < opts->rm_list.nr ? opts->rm_list.ids[i + 3] : TCPOPT_NOP;
put_unaligned_be32(id1 << 24 | id2 << 16 | id3 << 8 | id4, ptr);
ptr += 1;
i += 4;
}
}

if (OPTION_MPTCP_PRIO & opts->suboptions) {
Expand Down
39 changes: 24 additions & 15 deletions net/mptcp/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,29 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
return 0;
}

int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list)
{
u8 rm_addr = READ_ONCE(msk->pm.addr_signal);

pr_debug("msk=%p, local_id=%d", msk, local_id);
pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);

if (rm_addr) {
pr_warn("addr_signal error, rm_addr=%d", rm_addr);
return -EINVAL;
}

msk->pm.rm_id = local_id;
msk->pm.rm_list_tx = *rm_list;
rm_addr |= BIT(MPTCP_RM_ADDR_SIGNAL);
WRITE_ONCE(msk->pm.addr_signal, rm_addr);
return 0;
}

int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id)
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list)
{
pr_debug("msk=%p, local_id=%d", msk, local_id);
pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr);

spin_lock_bh(&msk->pm.lock);
mptcp_pm_nl_rm_subflow_received(msk, local_id);
mptcp_pm_nl_rm_subflow_received(msk, rm_list);
spin_unlock_bh(&msk->pm.lock);
return 0;
}
Expand Down Expand Up @@ -205,17 +205,20 @@ void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_SEND_ACK);
}

void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id)
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list)
{
struct mptcp_pm_data *pm = &msk->pm;
u8 i;

pr_debug("msk=%p remote_id=%d", msk, rm_id);
pr_debug("msk=%p remote_ids_nr=%d", msk, rm_list->nr);

mptcp_event_addr_removed(msk, rm_id);
for (i = 0; i < rm_list->nr; i++)
mptcp_event_addr_removed(msk, rm_list->ids[i]);

spin_lock_bh(&pm->lock);
mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED);
pm->rm_id = rm_id;
pm->rm_list_rx = *rm_list;
spin_unlock_bh(&pm->lock);
}

Expand Down Expand Up @@ -258,20 +261,25 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
}

bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
u8 *rm_id)
struct mptcp_rm_list *rm_list)
{
int ret = false;
int ret = false, len;

spin_lock_bh(&msk->pm.lock);

/* double check after the lock is acquired */
if (!mptcp_pm_should_rm_signal(msk))
goto out_unlock;

if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
len = mptcp_rm_addr_len(&msk->pm.rm_list_tx);
if (len < 0) {
WRITE_ONCE(msk->pm.addr_signal, 0);
goto out_unlock;
}
if (remaining < len)
goto out_unlock;

*rm_id = msk->pm.rm_id;
*rm_list = msk->pm.rm_list_tx;
WRITE_ONCE(msk->pm.addr_signal, 0);
ret = true;

Expand All @@ -291,7 +299,8 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
msk->pm.add_addr_accepted = 0;
msk->pm.local_addr_used = 0;
msk->pm.subflows = 0;
msk->pm.rm_id = 0;
msk->pm.rm_list_tx.nr = 0;
msk->pm.rm_list_rx.nr = 0;
WRITE_ONCE(msk->pm.work_pending, false);
WRITE_ONCE(msk->pm.addr_signal, 0);
WRITE_ONCE(msk->pm.accept_addr, false);
Expand Down
Loading

0 comments on commit 7c67882

Please sign in to comment.