Commit 87b5896f authored by Matthieu Baerts (NGI0)'s avatar Matthieu Baerts (NGI0) Committed by Paolo Abeni

mptcp: pm: fix RM_ADDR ID for the initial subflow

The initial subflow has a special local ID: 0. When an endpoint is being
deleted, it is then important to check if its address is not linked to
the initial subflow to send the right ID.

If there was an endpoint linked to the initial subflow, msk's
mpc_endpoint_id field will be set. We can then use this info when an
endpoint is being removed to see if it is linked to the initial subflow.

So now, the correct IDs are passed to mptcp_pm_nl_rm_addr_or_subflow(),
it is no longer needed to use mptcp_local_id_match().

Fixes: 3ad14f54 ("mptcp: more accurate MPC endpoint tracking")
Cc: stable@vger.kernel.org
Reviewed-by: default avatarMat Martineau <martineau@kernel.org>
Signed-off-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8b8ed1b4
...@@ -800,11 +800,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, ...@@ -800,11 +800,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
return -EINVAL; return -EINVAL;
} }
static bool mptcp_local_id_match(const struct mptcp_sock *msk, u8 local_id, u8 id)
{
return local_id == id || (!local_id && msk->mpc_endpoint_id == id);
}
static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list, const struct mptcp_rm_list *rm_list,
enum linux_mptcp_mib_field rm_type) enum linux_mptcp_mib_field rm_type)
...@@ -839,7 +834,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, ...@@ -839,7 +834,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id) if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
continue; continue;
if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id)) if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
continue; continue;
pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n", pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
...@@ -1448,6 +1443,12 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk, ...@@ -1448,6 +1443,12 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
return false; return false;
} }
static u8 mptcp_endp_get_local_id(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr)
{
return msk->mpc_endpoint_id == addr->id ? 0 : addr->id;
}
static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr, const struct mptcp_addr_info *addr,
bool force) bool force)
...@@ -1455,7 +1456,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, ...@@ -1455,7 +1456,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 0 };
bool ret; bool ret;
list.ids[list.nr++] = addr->id; list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
ret = remove_anno_list_by_saddr(msk, addr); ret = remove_anno_list_by_saddr(msk, addr);
if (ret || force) { if (ret || force) {
...@@ -1482,14 +1483,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, ...@@ -1482,14 +1483,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
const struct mptcp_pm_addr_entry *entry) const struct mptcp_pm_addr_entry *entry)
{ {
const struct mptcp_addr_info *addr = &entry->addr; const struct mptcp_addr_info *addr = &entry->addr;
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 1 };
long s_slot = 0, s_num = 0; long s_slot = 0, s_num = 0;
struct mptcp_sock *msk; struct mptcp_sock *msk;
pr_debug("remove_id=%d\n", addr->id); pr_debug("remove_id=%d\n", addr->id);
list.ids[list.nr++] = addr->id;
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) { while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
bool remove_subflow; bool remove_subflow;
...@@ -1507,6 +1506,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, ...@@ -1507,6 +1506,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow && mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT)); !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
if (remove_subflow) { if (remove_subflow) {
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
mptcp_pm_nl_rm_subflow_received(msk, &list); mptcp_pm_nl_rm_subflow_received(msk, &list);
...@@ -1613,6 +1613,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info) ...@@ -1613,6 +1613,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info)
return ret; return ret;
} }
/* Called from the userspace PM only */
void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list) void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
{ {
struct mptcp_rm_list alist = { .nr = 0 }; struct mptcp_rm_list alist = { .nr = 0 };
...@@ -1641,6 +1642,7 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list) ...@@ -1641,6 +1642,7 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
} }
} }
/* Called from the in-kernel PM only */
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list) struct list_head *rm_list)
{ {
...@@ -1650,11 +1652,11 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, ...@@ -1650,11 +1652,11 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
list_for_each_entry(entry, rm_list, list) { list_for_each_entry(entry, rm_list, list) {
if (slist.nr < MPTCP_RM_IDS_MAX && if (slist.nr < MPTCP_RM_IDS_MAX &&
lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
slist.ids[slist.nr++] = entry->addr.id; slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
if (alist.nr < MPTCP_RM_IDS_MAX && if (alist.nr < MPTCP_RM_IDS_MAX &&
remove_anno_list_by_saddr(msk, &entry->addr)) remove_anno_list_by_saddr(msk, &entry->addr))
alist.ids[alist.nr++] = entry->addr.id; alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
} }
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
...@@ -1951,7 +1953,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, ...@@ -1951,7 +1953,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
{ {
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 0 };
list.ids[list.nr++] = addr->id; list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
mptcp_pm_nl_rm_subflow_received(msk, &list); mptcp_pm_nl_rm_subflow_received(msk, &list);
......
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