mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
79 lines
1.9 KiB
C
79 lines
1.9 KiB
C
![]() |
// SPDX-License-Identifier: GPL-2.0
|
||
|
/* Multipath TCP
|
||
|
*
|
||
|
* Copyright (c) 2022, Intel Corporation.
|
||
|
*/
|
||
|
|
||
|
#include "protocol.h"
|
||
|
|
||
|
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
|
||
|
{
|
||
|
struct mptcp_pm_addr_entry *entry, *tmp;
|
||
|
struct sock *sk = (struct sock *)msk;
|
||
|
LIST_HEAD(free_list);
|
||
|
|
||
|
if (!mptcp_pm_is_userspace(msk))
|
||
|
return;
|
||
|
|
||
|
spin_lock_bh(&msk->pm.lock);
|
||
|
list_splice_init(&msk->pm.userspace_pm_local_addr_list, &free_list);
|
||
|
spin_unlock_bh(&msk->pm.lock);
|
||
|
|
||
|
list_for_each_entry_safe(entry, tmp, &free_list, list) {
|
||
|
sock_kfree_s(sk, entry, sizeof(*entry));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
|
||
|
struct mptcp_pm_addr_entry *entry)
|
||
|
{
|
||
|
DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
||
|
struct mptcp_pm_addr_entry *match = NULL;
|
||
|
struct sock *sk = (struct sock *)msk;
|
||
|
struct mptcp_pm_addr_entry *e;
|
||
|
bool addr_match = false;
|
||
|
bool id_match = false;
|
||
|
int ret = -EINVAL;
|
||
|
|
||
|
bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
||
|
|
||
|
spin_lock_bh(&msk->pm.lock);
|
||
|
list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
|
||
|
addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true);
|
||
|
if (addr_match && entry->addr.id == 0)
|
||
|
entry->addr.id = e->addr.id;
|
||
|
id_match = (e->addr.id == entry->addr.id);
|
||
|
if (addr_match && id_match) {
|
||
|
match = e;
|
||
|
break;
|
||
|
} else if (addr_match || id_match) {
|
||
|
break;
|
||
|
}
|
||
|
__set_bit(e->addr.id, id_bitmap);
|
||
|
}
|
||
|
|
||
|
if (!match && !addr_match && !id_match) {
|
||
|
/* Memory for the entry is allocated from the
|
||
|
* sock option buffer.
|
||
|
*/
|
||
|
e = sock_kmalloc(sk, sizeof(*e), GFP_ATOMIC);
|
||
|
if (!e) {
|
||
|
spin_unlock_bh(&msk->pm.lock);
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
*e = *entry;
|
||
|
if (!e->addr.id)
|
||
|
e->addr.id = find_next_zero_bit(id_bitmap,
|
||
|
MPTCP_PM_MAX_ADDR_ID + 1,
|
||
|
1);
|
||
|
list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
|
||
|
ret = e->addr.id;
|
||
|
} else if (match) {
|
||
|
ret = entry->addr.id;
|
||
|
}
|
||
|
|
||
|
spin_unlock_bh(&msk->pm.lock);
|
||
|
return ret;
|
||
|
}
|