Skip to content

Commit

Permalink
mptcp: send out dedicated ADD_ADDR packet
Browse files Browse the repository at this point in the history
When ADD_ADDR suboption includes an IPv6 address, the size is 28 octets.
It will not fit when other MPTCP suboptions are included in this packet,
e.g. DSS. So here we send out an ADD_ADDR dedicated packet to carry only
ADD_ADDR suboption, no other MPTCP suboptions.

In mptcp_pm_announce_addr, we check whether this is an IPv6 ADD_ADDR.
If it is, we set the flag MPTCP_ADD_ADDR_IPV6 to true. Then we call
mptcp_pm_check_send_dedicated_add_addr_packet to sent out a new pure
ACK packet.

In mptcp_established_options_add_addr, we check whether this is a pure
ACK packet for ADD_ADDR. If it is, we drop all other MPTCP suboptions
in this packet, only put ADD_ADDR suboption in it.

Suggested-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
  • Loading branch information
geliangtang authored and jenkins-tessares committed Oct 24, 2020
1 parent d887378 commit 4178518
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 6 deletions.
25 changes: 22 additions & 3 deletions net/mptcp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ static void mptcp_parse_option(const struct sk_buff *skb,

mp_opt->add_addr = 1;
mp_opt->addr_id = *ptr++;
pr_debug("ADD_ADDR: id=%d, echo=%d", mp_opt->addr_id, mp_opt->echo);
pr_debug("ADD_ADDR%s: id=%d, echo=%d",
(mp_opt->family == MPTCP_ADDR_IPVERSION_6) ? "6" : "",
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;
Expand Down Expand Up @@ -573,17 +575,27 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
}
#endif

static bool mptcp_established_options_add_addr(struct sock *sk,
static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb,
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);
bool drop_other_suboptions = false;
unsigned int opt_size = *size;
struct mptcp_addr_info saddr;
bool echo;
int len;

if (READ_ONCE(msk->pm.add_addr_signal) & BIT(MPTCP_ADD_ADDR_IPV6) &&
skb && skb_is_tcp_pure_ack(skb)) {
pr_debug("drop other suboptions");
opts->suboptions = 0;
remaining += opt_size;
drop_other_suboptions = true;
}

if (!mptcp_pm_should_add_signal(msk) ||
!(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo)))
return false;
Expand All @@ -593,6 +605,8 @@ static bool mptcp_established_options_add_addr(struct sock *sk,
return false;

*size = len;
if (drop_other_suboptions)
*size -= opt_size;
opts->addr_id = saddr.id;
if (saddr.family == AF_INET) {
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
Expand Down Expand Up @@ -678,7 +692,7 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,

*size += opt_size;
remaining -= opt_size;
if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, opts)) {
*size += opt_size;
remaining -= opt_size;
ret = true;
Expand Down Expand Up @@ -759,6 +773,11 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
goto fully_established;
}

if (mp_opt->add_addr) {
WRITE_ONCE(msk->fully_established, true);
return true;
}

/* If the first established packet does not contain MP_CAPABLE + data
* then fallback to TCP. Fallback scenarios requires a reset for
* MP_JOIN subflows.
Expand Down
8 changes: 6 additions & 2 deletions net/mptcp/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
add_addr |= BIT(MPTCP_ADD_ADDR_SIGNAL);
if (echo)
add_addr |= BIT(MPTCP_ADD_ADDR_ECHO);
if (addr->family == AF_INET6)
add_addr |= BIT(MPTCP_ADD_ADDR_IPV6);
WRITE_ONCE(msk->pm.add_addr_signal, add_addr);
return 0;
}
Expand Down Expand Up @@ -153,10 +155,12 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk,

spin_lock_bh(&pm->lock);

if (!READ_ONCE(pm->accept_addr))
if (!READ_ONCE(pm->accept_addr)) {
mptcp_pm_announce_addr(msk, addr, true);
else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED))
mptcp_pm_check_send_dedicated_add_addr_packet(msk);
} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
pm->remote = *addr;
}

spin_unlock_bh(&pm->lock);
}
Expand Down
27 changes: 27 additions & 0 deletions net/mptcp/pm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
if (!mptcp_pm_should_add_signal(msk)) {
pr_debug("retransmit ADD_ADDR id=%d", entry->addr.id);
mptcp_pm_announce_addr(msk, &entry->addr, false);
mptcp_pm_check_send_dedicated_add_addr_packet(msk);
entry->retrans_times++;
}

Expand Down Expand Up @@ -306,6 +307,30 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
}
}

void mptcp_pm_check_send_dedicated_add_addr_packet(struct mptcp_sock *msk)
{
struct mptcp_subflow_context *subflow;

if (!(READ_ONCE(msk->pm.add_addr_signal) & BIT(MPTCP_ADD_ADDR_IPV6)))
return;

__mptcp_flush_join_list(msk);
subflow = list_first_entry_or_null(&msk->conn_list, typeof(*subflow), node);
if (subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
u8 add_addr;

spin_unlock_bh(&msk->pm.lock);
pr_debug("send ack for add_addr6");
tcp_send_ack(ssk);
spin_lock_bh(&msk->pm.lock);

add_addr = READ_ONCE(msk->pm.add_addr_signal);
add_addr &= ~BIT(MPTCP_ADD_ADDR_IPV6);
WRITE_ONCE(msk->pm.add_addr_signal, add_addr);
}
}

static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
{
struct mptcp_addr_info remote = { 0 };
Expand All @@ -329,6 +354,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
if (mptcp_pm_alloc_anno_list(msk, local)) {
msk->pm.add_addr_signaled++;
mptcp_pm_announce_addr(msk, &local->addr, false);
mptcp_pm_check_send_dedicated_add_addr_packet(msk);
}
} else {
/* pick failed, avoid fourther attempts later */
Expand Down Expand Up @@ -399,6 +425,7 @@ void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
spin_lock_bh(&msk->pm.lock);

mptcp_pm_announce_addr(msk, &remote, true);
mptcp_pm_check_send_dedicated_add_addr_packet(msk);
}

void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
Expand Down
2 changes: 1 addition & 1 deletion net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
sk->sk_data_ready(sk);
}

static void __mptcp_flush_join_list(struct mptcp_sock *msk)
void __mptcp_flush_join_list(struct mptcp_sock *msk)
{
if (likely(list_empty(&msk->join_list)))
return;
Expand Down
3 changes: 3 additions & 0 deletions net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ enum mptcp_pm_status {
enum mptcp_add_addr_status {
MPTCP_ADD_ADDR_SIGNAL,
MPTCP_ADD_ADDR_ECHO,
MPTCP_ADD_ADDR_IPV6,
};

struct mptcp_pm_data {
Expand Down Expand Up @@ -467,6 +468,7 @@ bool mptcp_schedule_work(struct sock *sk);
void mptcp_data_acked(struct sock *sk);
void mptcp_subflow_eof(struct sock *sk);
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
void __mptcp_flush_join_list(struct mptcp_sock *msk);
static inline bool mptcp_data_fin_enabled(const struct mptcp_sock *msk)
{
return READ_ONCE(msk->snd_data_fin_enable) &&
Expand Down Expand Up @@ -516,6 +518,7 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
int mptcp_pm_announce_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr,
bool echo);
void mptcp_pm_check_send_dedicated_add_addr_packet(struct mptcp_sock *msk);
int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id);

Expand Down

0 comments on commit 4178518

Please sign in to comment.