mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 08:46:46 +00:00
Merge branch 'mptcp-addr-adv-fixes'
Mat Martineau says: ==================== mptcp: Fixes for address advertisement Patches 1 and 2 allow address advertisements to be removed without affecting current connected subflows, and updates associated self tests. Patches 3 and 4 correctly track (and allow removal of) addresses that were implicitly announced as part of subflow creation. Also updates associated self tests. Patch 5 makes subflow and address announcement counters work consistently between the userspace and in-kernel path managers. ==================== Signed-off-by: Mat Martineau <martineau@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fb928170e3
5 changed files with 95 additions and 6 deletions
|
@ -87,8 +87,15 @@ bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk)
|
|||
unsigned int subflows_max;
|
||||
int ret = 0;
|
||||
|
||||
if (mptcp_pm_is_userspace(msk))
|
||||
return mptcp_userspace_pm_active(msk);
|
||||
if (mptcp_pm_is_userspace(msk)) {
|
||||
if (mptcp_userspace_pm_active(msk)) {
|
||||
spin_lock_bh(&pm->lock);
|
||||
pm->subflows++;
|
||||
spin_unlock_bh(&pm->lock);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
subflows_max = mptcp_pm_get_subflows_max(msk);
|
||||
|
||||
|
@ -181,8 +188,16 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, const struct sock *ssk,
|
|||
struct mptcp_pm_data *pm = &msk->pm;
|
||||
bool update_subflows;
|
||||
|
||||
update_subflows = (subflow->request_join || subflow->mp_join) &&
|
||||
mptcp_pm_is_kernel(msk);
|
||||
update_subflows = subflow->request_join || subflow->mp_join;
|
||||
if (mptcp_pm_is_userspace(msk)) {
|
||||
if (update_subflows) {
|
||||
spin_lock_bh(&pm->lock);
|
||||
pm->subflows--;
|
||||
spin_unlock_bh(&pm->lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!READ_ONCE(pm->work_pending) && !update_subflows)
|
||||
return;
|
||||
|
||||
|
|
|
@ -1558,6 +1558,24 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
|
||||
{
|
||||
struct mptcp_rm_list alist = { .nr = 0 };
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
|
||||
list_for_each_entry(entry, rm_list, list) {
|
||||
remove_anno_list_by_saddr(msk, &entry->addr);
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
|
||||
void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
|
||||
struct list_head *rm_list)
|
||||
{
|
||||
|
|
|
@ -69,6 +69,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
|||
MPTCP_PM_MAX_ADDR_ID + 1,
|
||||
1);
|
||||
list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
|
||||
msk->pm.local_addr_used++;
|
||||
ret = e->addr.id;
|
||||
} else if (match) {
|
||||
ret = entry->addr.id;
|
||||
|
@ -79,6 +80,31 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* If the subflow is closed from the other peer (not via a
|
||||
* subflow destroy command then), we want to keep the entry
|
||||
* not to assign the same ID to another address and to be
|
||||
* able to send RM_ADDR after the removal of the subflow.
|
||||
*/
|
||||
static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *addr)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *entry, *tmp;
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) {
|
||||
if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) {
|
||||
/* TODO: a refcount is needed because the entry can
|
||||
* be used multiple times (e.g. fullmesh mode).
|
||||
*/
|
||||
list_del_rcu(&entry->list);
|
||||
kfree(entry);
|
||||
msk->pm.local_addr_used--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
|
||||
unsigned int id,
|
||||
u8 *flags, int *ifindex)
|
||||
|
@ -171,6 +197,7 @@ int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info)
|
|||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
if (mptcp_pm_alloc_anno_list(msk, &addr_val)) {
|
||||
msk->pm.add_addr_signaled++;
|
||||
mptcp_pm_announce_addr(msk, &addr_val.addr, false);
|
||||
mptcp_pm_nl_addr_send_ack(msk);
|
||||
}
|
||||
|
@ -232,7 +259,7 @@ int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
list_move(&match->list, &free_list);
|
||||
|
||||
mptcp_pm_remove_addrs_and_subflows(msk, &free_list);
|
||||
mptcp_pm_remove_addrs(msk, &free_list);
|
||||
|
||||
release_sock((struct sock *)msk);
|
||||
|
||||
|
@ -251,6 +278,7 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
|
|||
struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
|
||||
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
|
||||
struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
||||
struct mptcp_pm_addr_entry local = { 0 };
|
||||
struct mptcp_addr_info addr_r;
|
||||
struct mptcp_addr_info addr_l;
|
||||
struct mptcp_sock *msk;
|
||||
|
@ -302,12 +330,26 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
|
|||
goto create_err;
|
||||
}
|
||||
|
||||
local.addr = addr_l;
|
||||
err = mptcp_userspace_pm_append_new_local_addr(msk, &local);
|
||||
if (err < 0) {
|
||||
GENL_SET_ERR_MSG(info, "did not match address and id");
|
||||
goto create_err;
|
||||
}
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
err = __mptcp_subflow_connect(sk, &addr_l, &addr_r);
|
||||
|
||||
release_sock(sk);
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
if (err)
|
||||
mptcp_userspace_pm_delete_local_addr(msk, &local);
|
||||
else
|
||||
msk->pm.subflows++;
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
create_err:
|
||||
sock_put((struct sock *)msk);
|
||||
return err;
|
||||
|
@ -420,7 +462,11 @@ int mptcp_nl_cmd_sf_destroy(struct sk_buff *skb, struct genl_info *info)
|
|||
ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r);
|
||||
if (ssk) {
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
||||
struct mptcp_pm_addr_entry entry = { .addr = addr_l };
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
mptcp_userspace_pm_delete_local_addr(msk, &entry);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
|
||||
mptcp_close_ssk(sk, ssk, subflow);
|
||||
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
|
||||
|
|
|
@ -832,6 +832,7 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
|
|||
bool echo);
|
||||
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_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list);
|
||||
void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
|
||||
struct list_head *rm_list);
|
||||
|
||||
|
|
|
@ -862,7 +862,15 @@ do_transfer()
|
|||
sed -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q')
|
||||
ip netns exec ${listener_ns} ./pm_nl_ctl ann $addr token $tk id $id
|
||||
sleep 1
|
||||
sp=$(grep "type:10" "$evts_ns1" |
|
||||
sed -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
|
||||
da=$(grep "type:10" "$evts_ns1" |
|
||||
sed -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q')
|
||||
dp=$(grep "type:10" "$evts_ns1" |
|
||||
sed -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q')
|
||||
ip netns exec ${listener_ns} ./pm_nl_ctl rem token $tk id $id
|
||||
ip netns exec ${listener_ns} ./pm_nl_ctl dsf lip "::ffff:$addr" \
|
||||
lport $sp rip $da rport $dp token $tk
|
||||
fi
|
||||
|
||||
counter=$((counter + 1))
|
||||
|
@ -928,6 +936,7 @@ do_transfer()
|
|||
sleep 1
|
||||
sp=$(grep "type:10" "$evts_ns2" |
|
||||
sed -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
|
||||
ip netns exec ${connector_ns} ./pm_nl_ctl rem token $tk id $id
|
||||
ip netns exec ${connector_ns} ./pm_nl_ctl dsf lip $addr lport $sp \
|
||||
rip $da rport $dp token $tk
|
||||
fi
|
||||
|
@ -3142,7 +3151,7 @@ userspace_tests()
|
|||
pm_nl_set_limits $ns1 0 1
|
||||
run_tests $ns1 $ns2 10.0.1.1 0 0 userspace_1 slow
|
||||
chk_join_nr 1 1 1
|
||||
chk_rm_nr 0 1
|
||||
chk_rm_nr 1 1
|
||||
kill_events_pids
|
||||
fi
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue