Commit 7c678829 authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-Include-multiple-address-ids-in-RM_ADDR'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents e9e90a70 d2c4333a
......@@ -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;
......@@ -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;
......
......@@ -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:
......@@ -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:
......@@ -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;
}
......@@ -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;
}
......@@ -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) {
......
......@@ -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;
}
......@@ -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);
}
......@@ -258,9 +261,9 @@ 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);
......@@ -268,10 +271,15 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
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;
......@@ -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);
......
......@@ -575,36 +575,40 @@ static void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
{
struct mptcp_subflow_context *subflow, *tmp;
struct sock *sk = (struct sock *)msk;
u8 i;
pr_debug("address rm_id %d", msk->pm.rm_id);
pr_debug("address rm_list_nr %d", msk->pm.rm_list_rx.nr);
msk_owned_by_me(msk);
if (!msk->pm.rm_id)
if (!msk->pm.rm_list_rx.nr)
return;
if (list_empty(&msk->conn_list))
return;
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
for (i = 0; i < msk->pm.rm_list_rx.nr; i++) {
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
if (msk->pm.rm_id != subflow->remote_id)
continue;
if (msk->pm.rm_list_rx.ids[i] != subflow->remote_id)
continue;
spin_unlock_bh(&msk->pm.lock);
mptcp_subflow_shutdown(sk, ssk, how);
mptcp_close_ssk(sk, ssk, subflow);
spin_lock_bh(&msk->pm.lock);
pr_debug(" -> address rm_list_ids[%d]=%u", i, msk->pm.rm_list_rx.ids[i]);
spin_unlock_bh(&msk->pm.lock);
mptcp_subflow_shutdown(sk, ssk, how);
mptcp_close_ssk(sk, ssk, subflow);
spin_lock_bh(&msk->pm.lock);
msk->pm.add_addr_accepted--;
msk->pm.subflows--;
WRITE_ONCE(msk->pm.accept_addr, true);
msk->pm.add_addr_accepted--;
msk->pm.subflows--;
WRITE_ONCE(msk->pm.accept_addr, true);
__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMADDR);
__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMADDR);
break;
break;
}
}
}
......@@ -641,39 +645,44 @@ void mptcp_pm_nl_work(struct mptcp_sock *msk)
spin_unlock_bh(&msk->pm.lock);
}
void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id)
void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list)
{
struct mptcp_subflow_context *subflow, *tmp;
struct sock *sk = (struct sock *)msk;
u8 i;
pr_debug("subflow rm_id %d", rm_id);
pr_debug("subflow rm_list_nr %d", rm_list->nr);
msk_owned_by_me(msk);
if (!rm_id)
if (!rm_list->nr)
return;
if (list_empty(&msk->conn_list))
return;
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
for (i = 0; i < rm_list->nr; i++) {
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
if (rm_id != subflow->local_id)
continue;
if (rm_list->ids[i] != subflow->local_id)
continue;
spin_unlock_bh(&msk->pm.lock);
mptcp_subflow_shutdown(sk, ssk, how);
mptcp_close_ssk(sk, ssk, subflow);
spin_lock_bh(&msk->pm.lock);
pr_debug(" -> subflow rm_list_ids[%d]=%u", i, rm_list->ids[i]);
spin_unlock_bh(&msk->pm.lock);
mptcp_subflow_shutdown(sk, ssk, how);
mptcp_close_ssk(sk, ssk, subflow);
spin_lock_bh(&msk->pm.lock);
msk->pm.local_addr_used--;
msk->pm.subflows--;
msk->pm.local_addr_used--;
msk->pm.subflows--;
__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
__MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
break;
break;
}
}
}
......@@ -1071,12 +1080,15 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
struct mptcp_addr_info *addr,
bool force)
{
struct mptcp_rm_list list = { .nr = 0 };
bool ret;
list.ids[list.nr++] = addr->id;
ret = remove_anno_list_by_saddr(msk, addr);
if (ret || force) {
spin_lock_bh(&msk->pm.lock);
mptcp_pm_remove_addr(msk, addr->id);
mptcp_pm_remove_addr(msk, &list);
spin_unlock_bh(&msk->pm.lock);
}
return ret;
......@@ -1087,9 +1099,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
{
struct mptcp_sock *msk;
long s_slot = 0, s_num = 0;
struct mptcp_rm_list list = { .nr = 0 };
pr_debug("remove_id=%d", addr->id);
list.ids[list.nr++] = addr->id;
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk;
bool remove_subflow;
......@@ -1103,7 +1118,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow);
if (remove_subflow)
mptcp_pm_remove_subflow(msk, addr->id);
mptcp_pm_remove_subflow(msk, &list);
release_sock(sk);
next:
......@@ -1185,14 +1200,61 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
return ret;
}
static void __flush_addrs(struct net *net, struct list_head *list)
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list)
{
struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 };
struct mptcp_pm_addr_entry *entry;
list_for_each_entry(entry, rm_list, list) {
if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
alist.nr < MPTCP_RM_IDS_MAX &&
slist.nr < MPTCP_RM_IDS_MAX) {
alist.ids[alist.nr++] = entry->addr.id;
slist.ids[slist.nr++] = entry->addr.id;
} else if (remove_anno_list_by_saddr(msk, &entry->addr) &&
alist.nr < MPTCP_RM_IDS_MAX) {
alist.ids[alist.nr++] = entry->addr.id;
}
}
if (alist.nr) {
spin_lock_bh(&msk->pm.lock);
mptcp_pm_remove_addr(msk, &alist);
spin_unlock_bh(&msk->pm.lock);
}
if (slist.nr)
mptcp_pm_remove_subflow(msk, &slist);
}
static void mptcp_nl_remove_addrs_list(struct net *net,
struct list_head *rm_list)
{
long s_slot = 0, s_num = 0;
struct mptcp_sock *msk;
if (list_empty(rm_list))
return;
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk;
lock_sock(sk);
mptcp_pm_remove_addrs_and_subflows(msk, rm_list);
release_sock(sk);
sock_put(sk);
cond_resched();
}
}
static void __flush_addrs(struct list_head *list)
{
while (!list_empty(list)) {
struct mptcp_pm_addr_entry *cur;
cur = list_entry(list->next,
struct mptcp_pm_addr_entry, list);
mptcp_nl_remove_subflow_and_signal_addr(net, &cur->addr);
list_del_rcu(&cur->list);
mptcp_pm_free_addr_entry(cur);
}
......@@ -1217,7 +1279,8 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
pernet->next_id = 1;
bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
spin_unlock_bh(&pernet->lock);
__flush_addrs(sock_net(skb->sk), &free_list);
mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
__flush_addrs(&free_list);
return 0;
}
......@@ -1814,7 +1877,7 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
/* net is removed from namespace list, can't race with
* other modifiers
*/
__flush_addrs(net, &pernet->local_addr_list);
__flush_addrs(&pernet->local_addr_list);
}
}
......
......@@ -61,7 +61,7 @@
#define TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT 22
#define TCPOLEN_MPTCP_PORT_LEN 2
#define TCPOLEN_MPTCP_PORT_ALIGN 2
#define TCPOLEN_MPTCP_RM_ADDR_BASE 4
#define TCPOLEN_MPTCP_RM_ADDR_BASE 3
#define TCPOLEN_MPTCP_PRIO 3
#define TCPOLEN_MPTCP_PRIO_ALIGN 4
#define TCPOLEN_MPTCP_FASTCLOSE 12
......@@ -142,7 +142,7 @@ struct mptcp_options_received {
mpc_map:1,
__unused:2;
u8 addr_id;
u8 rm_id;
struct mptcp_rm_list rm_list;
union {
struct in_addr addr;
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
......@@ -207,7 +207,8 @@ struct mptcp_pm_data {
u8 local_addr_used;
u8 subflows;
u8 status;
u8 rm_id;
struct mptcp_rm_list rm_list_tx;
struct mptcp_rm_list rm_list_rx;
};
struct mptcp_data_frag {
......@@ -647,7 +648,8 @@ void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr);
void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
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);
void mptcp_pm_mp_prio_received(struct sock *sk, u8 bkup);
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
struct mptcp_addr_info *addr,
......@@ -661,8 +663,8 @@ 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, bool port);
int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id);
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 local_id);
int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
const struct sock *ssk, gfp_t gfp);
......@@ -709,16 +711,25 @@ static inline unsigned int mptcp_add_addr_len(int family, bool echo, bool port)
return len;
}
static inline int mptcp_rm_addr_len(const struct mptcp_rm_list *rm_list)
{
if (rm_list->nr == 0 || rm_list->nr > MPTCP_RM_IDS_MAX)
return -EINVAL;
return TCPOLEN_MPTCP_RM_ADDR_BASE + roundup(rm_list->nr - 1, 4) + 1;
}
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
struct mptcp_addr_info *saddr, bool *echo, bool *port);
bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
u8 *rm_id);
struct mptcp_rm_list *rm_list);
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
void __init mptcp_pm_nl_init(void);
void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
void mptcp_pm_nl_work(struct mptcp_sock *msk);
void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, u8 rm_id);
void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list);
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
unsigned int mptcp_pm_get_add_addr_signal_max(struct mptcp_sock *msk);
unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
......
......@@ -284,14 +284,19 @@ do_transfer()
let rm_nr_ns1=-addr_nr_ns1
if [ $rm_nr_ns1 -lt 8 ]; then
counter=1
sleep 1
while [ $counter -le $rm_nr_ns1 ]
do
ip netns exec ${listener_ns} ./pm_nl_ctl del $counter
dump=(`ip netns exec ${listener_ns} ./pm_nl_ctl dump`)
if [ ${#dump[@]} -gt 0 ]; then
id=${dump[1]}
sleep 1
let counter+=1
done
while [ $counter -le $rm_nr_ns1 ]
do
ip netns exec ${listener_ns} ./pm_nl_ctl del $id
sleep 1
let counter+=1
let id+=1
done
fi
else
sleep 1
ip netns exec ${listener_ns} ./pm_nl_ctl flush
......@@ -318,14 +323,19 @@ do_transfer()
let rm_nr_ns2=-addr_nr_ns2
if [ $rm_nr_ns2 -lt 8 ]; then
counter=1
sleep 1
while [ $counter -le $rm_nr_ns2 ]
do
ip netns exec ${connector_ns} ./pm_nl_ctl del $counter
dump=(`ip netns exec ${connector_ns} ./pm_nl_ctl dump`)
if [ ${#dump[@]} -gt 0 ]; then
id=${dump[1]}
sleep 1
let counter+=1
done
while [ $counter -le $rm_nr_ns2 ]
do
ip netns exec ${connector_ns} ./pm_nl_ctl del $id
sleep 1
let counter+=1
let id+=1
done
fi
else
sleep 1
ip netns exec ${connector_ns} ./pm_nl_ctl flush
......@@ -610,11 +620,22 @@ chk_rm_nr()
{
local rm_addr_nr=$1
local rm_subflow_nr=$2
local invert=${3:-""}
local count
local dump_stats
local addr_ns
local subflow_ns
if [ -z $invert ]; then
addr_ns=$ns1
subflow_ns=$ns2
elif [ $invert = "invert" ]; then
addr_ns=$ns2
subflow_ns=$ns1
fi
printf "%-39s %s" " " "rm "
count=`ip netns exec $ns1 nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'`
count=`ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'`
[ -z "$count" ] && count=0
if [ "$count" != "$rm_addr_nr" ]; then
echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
......@@ -625,7 +646,7 @@ chk_rm_nr()
fi
echo -n " - sf "
count=`ip netns exec $ns2 nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
[ -z "$count" ] && count=0
if [ "$count" != "$rm_subflow_nr" ]; then
echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
......@@ -833,7 +854,7 @@ remove_tests()
run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
chk_join_nr "remove single address" 1 1 1
chk_add_nr 1 1
chk_rm_nr 0 0
chk_rm_nr 1 1 invert
# subflow and signal, remove
reset
......@@ -869,6 +890,29 @@ remove_tests()
chk_join_nr "flush subflows and signal" 3 3 3
chk_add_nr 1 1
chk_rm_nr 2 2
# subflows flush
reset
ip netns exec $ns1 ./pm_nl_ctl limits 3 3
ip netns exec $ns2 ./pm_nl_ctl limits 3 3
ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow id 150
ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr "flush subflows" 3 3 3
chk_rm_nr 3 3
# addresses flush
reset
ip netns exec $ns1 ./pm_nl_ctl limits 3 3
ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal id 250
ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
ip netns exec $ns1 ./pm_nl_ctl add 10.0.4.1 flags signal
ip netns exec $ns2 ./pm_nl_ctl limits 3 3
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr "flush addresses" 3 3 3
chk_add_nr 3 3
chk_rm_nr 3 3 invert
}
add_tests()
......@@ -945,7 +989,7 @@ ipv6_tests()
run_tests $ns1 $ns2 dead:beef:1::1 0 -1 0 slow
chk_join_nr "remove single address IPv6" 1 1 1
chk_add_nr 1 1
chk_rm_nr 0 0
chk_rm_nr 1 1 invert
# subflow and signal IPv6, remove
reset
......@@ -1088,7 +1132,7 @@ add_addr_ports_tests()
run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
chk_join_nr "remove single address with port" 1 1 1
chk_add_nr 1 1 1
chk_rm_nr 0 0
chk_rm_nr 1 1 invert
# subflow and signal with port, remove
reset
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment