mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
Merge branch 'mptcp-pm-code-reorganisation'
Matthieu Baerts says:
====================
mptcp: pm: code reorganisation
Before this series, the PM code was dispersed in different places:
- pm.c had common code for all PMs.
- pm_netlink.c was initially only about the in-kernel PM, but ended up
also getting exported common helpers, callbacks used by the different
PMs, NL events for PM userspace daemon, etc. quite confusing.
- pm_userspace.c had userspace PM only code, but it was using "specific"
in-kernel PM helpers according to their names.
To clarify the code, a reorganisation is suggested here, only by moving
code around, and small helper renaming to avoid confusions:
- pm_netlink.c now only contains common PM generic Netlink code:
- PM events: this code was already there
- shared helpers around Netlink code that were already there as well
- shared Netlink commands code from pm.c
- pm_kernel.c now contains only code that is specific to the in-kernel
PM. Now all functions are either called from:
- pm.c: events coming from the core, when this PM is being used
- pm_netlink.c: for shared Netlink commands
- mptcp_pm_gen.c: for Netlink commands specific to the in-kernel PM
- sockopt.c: for the exported counters per netns
- pm.c got many code from pm_netlink.c:
- helpers used from both PMs and not linked to Netlink
- callbacks used by different PMs, e.g. ADD_ADDR management
- some helpers have been renamed to remove the '_nl' prefix, and some
have been marked as 'static'.
- protocol.h has been updated accordingly:
- some helpers no longer need to be exported
- new ones needed to be exported: they have been prefixed if needed.
The code around the PM is now less confusing, which should help for the
maintenance in the long term, and the introduction of a PM Ops.
This will certainly impact future backports, but because other cleanups
have already done recently, and more are coming to ease the addition of
a new path-manager controlled with BPF (struct_ops), doing that now
seems to be a good time. Also, many issues around the PM have been fixed
a few months ago while increasing the code coverage in the selftests, so
such big reorganisation can be done with more confidence now.
Note that checkpatch, when used with --max-line-length=80, will complain
about lines being over the 80 limits, but these warnings were already
there before moving the code around.
Also, patch 1 is not directly related to the code reorganisation, but it
was a remaining cleanup that we didn't upstream before, because it was
conflicting with another patch that has been sent for inclusion to the
net tree.
====================
Link: https://patch.msgid.link/20250307-net-next-mptcp-pm-reorg-v1-0-abef20ada03b@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
71ca3561c2
|
|
@ -3,7 +3,7 @@ obj-$(CONFIG_MPTCP) += mptcp.o
|
|||
|
||||
mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o pm.o diag.o \
|
||||
mib.o pm_netlink.o sockopt.o pm_userspace.o fastopen.o sched.o \
|
||||
mptcp_pm_gen.o
|
||||
mptcp_pm_gen.o pm_kernel.o
|
||||
|
||||
obj-$(CONFIG_SYN_COOKIES) += syncookies.o
|
||||
obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o
|
||||
|
|
|
|||
653
net/mptcp/pm.c
653
net/mptcp/pm.c
|
|
@ -5,12 +5,384 @@
|
|||
*/
|
||||
#define pr_fmt(fmt) "MPTCP: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <net/mptcp.h>
|
||||
#include "protocol.h"
|
||||
|
||||
#include "mib.h"
|
||||
#include "mptcp_pm_gen.h"
|
||||
|
||||
#define ADD_ADDR_RETRANS_MAX 3
|
||||
|
||||
struct mptcp_pm_add_entry {
|
||||
struct list_head list;
|
||||
struct mptcp_addr_info addr;
|
||||
u8 retrans_times;
|
||||
struct timer_list add_timer;
|
||||
struct mptcp_sock *sock;
|
||||
};
|
||||
|
||||
/* path manager helpers */
|
||||
|
||||
/* if sk is ipv4 or ipv6_only allows only same-family local and remote addresses,
|
||||
* otherwise allow any matching local/remote pair
|
||||
*/
|
||||
bool mptcp_pm_addr_families_match(const struct sock *sk,
|
||||
const struct mptcp_addr_info *loc,
|
||||
const struct mptcp_addr_info *rem)
|
||||
{
|
||||
bool mptcp_is_v4 = sk->sk_family == AF_INET;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
bool loc_is_v4 = loc->family == AF_INET || ipv6_addr_v4mapped(&loc->addr6);
|
||||
bool rem_is_v4 = rem->family == AF_INET || ipv6_addr_v4mapped(&rem->addr6);
|
||||
|
||||
if (mptcp_is_v4)
|
||||
return loc_is_v4 && rem_is_v4;
|
||||
|
||||
if (ipv6_only_sock(sk))
|
||||
return !loc_is_v4 && !rem_is_v4;
|
||||
|
||||
return loc_is_v4 == rem_is_v4;
|
||||
#else
|
||||
return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
|
||||
const struct mptcp_addr_info *b, bool use_port)
|
||||
{
|
||||
bool addr_equals = false;
|
||||
|
||||
if (a->family == b->family) {
|
||||
if (a->family == AF_INET)
|
||||
addr_equals = a->addr.s_addr == b->addr.s_addr;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
else
|
||||
addr_equals = ipv6_addr_equal(&a->addr6, &b->addr6);
|
||||
} else if (a->family == AF_INET) {
|
||||
if (ipv6_addr_v4mapped(&b->addr6))
|
||||
addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
|
||||
} else if (b->family == AF_INET) {
|
||||
if (ipv6_addr_v4mapped(&a->addr6))
|
||||
addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!addr_equals)
|
||||
return false;
|
||||
if (!use_port)
|
||||
return true;
|
||||
|
||||
return a->port == b->port;
|
||||
}
|
||||
|
||||
void mptcp_local_address(const struct sock_common *skc,
|
||||
struct mptcp_addr_info *addr)
|
||||
{
|
||||
addr->family = skc->skc_family;
|
||||
addr->port = htons(skc->skc_num);
|
||||
if (addr->family == AF_INET)
|
||||
addr->addr.s_addr = skc->skc_rcv_saddr;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
else if (addr->family == AF_INET6)
|
||||
addr->addr6 = skc->skc_v6_rcv_saddr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mptcp_remote_address(const struct sock_common *skc,
|
||||
struct mptcp_addr_info *addr)
|
||||
{
|
||||
addr->family = skc->skc_family;
|
||||
addr->port = skc->skc_dport;
|
||||
if (addr->family == AF_INET)
|
||||
addr->addr.s_addr = skc->skc_daddr;
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
else if (addr->family == AF_INET6)
|
||||
addr->addr6 = skc->skc_v6_daddr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool mptcp_pm_is_init_remote_addr(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *remote)
|
||||
{
|
||||
struct mptcp_addr_info mpc_remote;
|
||||
|
||||
mptcp_remote_address((struct sock_common *)msk, &mpc_remote);
|
||||
return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
|
||||
}
|
||||
|
||||
bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
||||
const struct mptcp_addr_info *saddr)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_addr_info cur;
|
||||
struct sock_common *skc;
|
||||
|
||||
list_for_each_entry(subflow, list, node) {
|
||||
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
|
||||
|
||||
mptcp_local_address(skc, &cur);
|
||||
if (mptcp_addresses_equal(&cur, saddr, saddr->port))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct mptcp_pm_add_entry *
|
||||
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
||||
if (mptcp_addresses_equal(&entry->addr, addr, true))
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
|
||||
entry = mptcp_pm_del_add_timer(msk, addr, false);
|
||||
kfree(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
struct mptcp_addr_info saddr;
|
||||
bool ret = false;
|
||||
|
||||
mptcp_local_address((struct sock_common *)sk, &saddr);
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
||||
if (mptcp_addresses_equal(&entry->addr, &saddr, true)) {
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __mptcp_pm_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow,
|
||||
bool prio, bool backup)
|
||||
{
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
bool slow;
|
||||
|
||||
pr_debug("send ack for %s\n",
|
||||
prio ? "mp_prio" :
|
||||
(mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr"));
|
||||
|
||||
slow = lock_sock_fast(ssk);
|
||||
if (prio) {
|
||||
subflow->send_mp_prio = 1;
|
||||
subflow->request_bkup = backup;
|
||||
}
|
||||
|
||||
__mptcp_subflow_send_ack(ssk);
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
|
||||
void mptcp_pm_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow,
|
||||
bool prio, bool backup)
|
||||
{
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
__mptcp_pm_send_ack(msk, subflow, prio, backup);
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
}
|
||||
|
||||
void mptcp_pm_addr_send_ack(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow, *alt = NULL;
|
||||
|
||||
msk_owned_by_me(msk);
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
if (!mptcp_pm_should_add_signal(msk) &&
|
||||
!mptcp_pm_should_rm_signal(msk))
|
||||
return;
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
if (__mptcp_subflow_active(subflow)) {
|
||||
if (!subflow->stale) {
|
||||
mptcp_pm_send_ack(msk, subflow, false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!alt)
|
||||
alt = subflow;
|
||||
}
|
||||
}
|
||||
|
||||
if (alt)
|
||||
mptcp_pm_send_ack(msk, alt, false, false);
|
||||
}
|
||||
|
||||
int mptcp_pm_mp_prio_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *addr,
|
||||
struct mptcp_addr_info *rem,
|
||||
u8 bkup)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
|
||||
pr_debug("bkup=%d\n", bkup);
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
struct mptcp_addr_info local, remote;
|
||||
|
||||
mptcp_local_address((struct sock_common *)ssk, &local);
|
||||
if (!mptcp_addresses_equal(&local, addr, addr->port))
|
||||
continue;
|
||||
|
||||
if (rem && rem->family != AF_UNSPEC) {
|
||||
mptcp_remote_address((struct sock_common *)ssk, &remote);
|
||||
if (!mptcp_addresses_equal(&remote, rem, rem->port))
|
||||
continue;
|
||||
}
|
||||
|
||||
__mptcp_pm_send_ack(msk, subflow, true, bkup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void mptcp_pm_add_timer(struct timer_list *timer)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry = from_timer(entry, timer, add_timer);
|
||||
struct mptcp_sock *msk = entry->sock;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
|
||||
pr_debug("msk=%p\n", msk);
|
||||
|
||||
if (!msk)
|
||||
return;
|
||||
|
||||
if (inet_sk_state_load(sk) == TCP_CLOSE)
|
||||
return;
|
||||
|
||||
if (!entry->addr.id)
|
||||
return;
|
||||
|
||||
if (mptcp_pm_should_add_signal_addr(msk)) {
|
||||
sk_reset_timer(sk, timer, jiffies + TCP_RTO_MAX / 8);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
if (!mptcp_pm_should_add_signal_addr(msk)) {
|
||||
pr_debug("retransmit ADD_ADDR id=%d\n", entry->addr.id);
|
||||
mptcp_pm_announce_addr(msk, &entry->addr, false);
|
||||
mptcp_pm_add_addr_send_ack(msk);
|
||||
entry->retrans_times++;
|
||||
}
|
||||
|
||||
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
|
||||
sk_reset_timer(sk, timer,
|
||||
jiffies + mptcp_get_add_addr_timeout(sock_net(sk)));
|
||||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
if (entry->retrans_times == ADD_ADDR_RETRANS_MAX)
|
||||
mptcp_pm_subflow_established(msk);
|
||||
|
||||
out:
|
||||
__sock_put(sk);
|
||||
}
|
||||
|
||||
struct mptcp_pm_add_entry *
|
||||
mptcp_pm_del_add_timer(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr, bool check_id)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct timer_list *add_timer = NULL;
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
||||
if (entry && (!check_id || entry->addr.id == addr->id)) {
|
||||
entry->retrans_times = ADD_ADDR_RETRANS_MAX;
|
||||
add_timer = &entry->add_timer;
|
||||
}
|
||||
if (!check_id && entry)
|
||||
list_del(&entry->list);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
/* no lock, because sk_stop_timer_sync() is calling del_timer_sync() */
|
||||
if (add_timer)
|
||||
sk_stop_timer_sync(sk, add_timer);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_entry *add_entry = NULL;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct net *net = sock_net(sk);
|
||||
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
||||
|
||||
if (add_entry) {
|
||||
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
||||
return false;
|
||||
|
||||
sk_reset_timer(sk, &add_entry->add_timer,
|
||||
jiffies + mptcp_get_add_addr_timeout(net));
|
||||
return true;
|
||||
}
|
||||
|
||||
add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC);
|
||||
if (!add_entry)
|
||||
return false;
|
||||
|
||||
list_add(&add_entry->list, &msk->pm.anno_list);
|
||||
|
||||
add_entry->addr = *addr;
|
||||
add_entry->sock = msk;
|
||||
add_entry->retrans_times = 0;
|
||||
|
||||
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
|
||||
sk_reset_timer(sk, &add_entry->add_timer,
|
||||
jiffies + mptcp_get_add_addr_timeout(net));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry, *tmp;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
LIST_HEAD(free_list);
|
||||
|
||||
pr_debug("msk=%p\n", msk);
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
list_splice_init(&msk->pm.anno_list, &free_list);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &free_list, list) {
|
||||
sk_stop_timer_sync(sk, &entry->add_timer);
|
||||
kfree(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* path manager command handlers */
|
||||
|
||||
|
|
@ -57,7 +429,7 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_
|
|||
msk->pm.rm_list_tx = *rm_list;
|
||||
rm_addr |= BIT(MPTCP_RM_ADDR_SIGNAL);
|
||||
WRITE_ONCE(msk->pm.addr_signal, rm_addr);
|
||||
mptcp_pm_nl_addr_send_ack(msk);
|
||||
mptcp_pm_addr_send_ack(msk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +603,7 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
|
|||
__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
|
||||
}
|
||||
/* id0 should not have a different address */
|
||||
} else if ((addr->id == 0 && !mptcp_pm_nl_is_init_remote_addr(msk, addr)) ||
|
||||
} else if ((addr->id == 0 && !mptcp_pm_is_init_remote_addr(msk, addr)) ||
|
||||
(addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
|
||||
mptcp_pm_announce_addr(msk, addr, true);
|
||||
mptcp_pm_add_addr_send_ack(msk);
|
||||
|
|
@ -270,6 +642,80 @@ void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
|
|||
mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_SEND_ACK);
|
||||
}
|
||||
|
||||
static void mptcp_pm_rm_addr_or_subflow(struct mptcp_sock *msk,
|
||||
const struct mptcp_rm_list *rm_list,
|
||||
enum linux_mptcp_mib_field rm_type)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow, *tmp;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
u8 i;
|
||||
|
||||
pr_debug("%s rm_list_nr %d\n",
|
||||
rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow", rm_list->nr);
|
||||
|
||||
msk_owned_by_me(msk);
|
||||
|
||||
if (sk->sk_state == TCP_LISTEN)
|
||||
return;
|
||||
|
||||
if (!rm_list->nr)
|
||||
return;
|
||||
|
||||
if (list_empty(&msk->conn_list))
|
||||
return;
|
||||
|
||||
for (i = 0; i < rm_list->nr; i++) {
|
||||
u8 rm_id = rm_list->ids[i];
|
||||
bool removed = false;
|
||||
|
||||
mptcp_for_each_subflow_safe(msk, subflow, tmp) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
u8 remote_id = READ_ONCE(subflow->remote_id);
|
||||
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
|
||||
u8 id = subflow_get_local_id(subflow);
|
||||
|
||||
if ((1 << inet_sk_state_load(ssk)) &
|
||||
(TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING | TCPF_CLOSE))
|
||||
continue;
|
||||
if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
|
||||
continue;
|
||||
if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
|
||||
continue;
|
||||
|
||||
pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
|
||||
rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
|
||||
i, rm_id, id, remote_id, msk->mpc_endpoint_id);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
mptcp_subflow_shutdown(sk, ssk, how);
|
||||
removed |= subflow->request_join;
|
||||
|
||||
/* the following takes care of updating the subflows counter */
|
||||
mptcp_close_ssk(sk, ssk, subflow);
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
if (rm_type == MPTCP_MIB_RMSUBFLOW)
|
||||
__MPTCP_INC_STATS(sock_net(sk), rm_type);
|
||||
}
|
||||
|
||||
if (rm_type == MPTCP_MIB_RMADDR) {
|
||||
__MPTCP_INC_STATS(sock_net(sk), rm_type);
|
||||
if (removed && mptcp_pm_is_kernel(msk))
|
||||
mptcp_pm_nl_rm_addr(msk, rm_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mptcp_pm_rm_addr_recv(struct mptcp_sock *msk)
|
||||
{
|
||||
mptcp_pm_rm_addr_or_subflow(msk, &msk->pm.rm_list_rx, MPTCP_MIB_RMADDR);
|
||||
}
|
||||
|
||||
void mptcp_pm_rm_subflow(struct mptcp_sock *msk,
|
||||
const struct mptcp_rm_list *rm_list)
|
||||
{
|
||||
mptcp_pm_rm_addr_or_subflow(msk, rm_list, MPTCP_MIB_RMSUBFLOW);
|
||||
}
|
||||
|
||||
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
|
||||
const struct mptcp_rm_list *rm_list)
|
||||
{
|
||||
|
|
@ -325,8 +771,6 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
|
|||
}
|
||||
}
|
||||
|
||||
/* path manager helpers */
|
||||
|
||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, const struct sk_buff *skb,
|
||||
unsigned int opt_size, unsigned int remaining,
|
||||
struct mptcp_addr_info *addr, bool *echo,
|
||||
|
|
@ -406,7 +850,7 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
|||
|
||||
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
|
||||
{
|
||||
struct mptcp_addr_info skc_local;
|
||||
struct mptcp_pm_addr_entry skc_local = { 0 };
|
||||
struct mptcp_addr_info msk_local;
|
||||
|
||||
if (WARN_ON_ONCE(!msk))
|
||||
|
|
@ -416,10 +860,13 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
|
|||
* addr
|
||||
*/
|
||||
mptcp_local_address((struct sock_common *)msk, &msk_local);
|
||||
mptcp_local_address((struct sock_common *)skc, &skc_local);
|
||||
if (mptcp_addresses_equal(&msk_local, &skc_local, false))
|
||||
mptcp_local_address((struct sock_common *)skc, &skc_local.addr);
|
||||
if (mptcp_addresses_equal(&msk_local, &skc_local.addr, false))
|
||||
return 0;
|
||||
|
||||
skc_local.addr.id = 0;
|
||||
skc_local.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
|
||||
|
||||
if (mptcp_pm_is_userspace(msk))
|
||||
return mptcp_userspace_pm_get_local_id(msk, &skc_local);
|
||||
return mptcp_pm_nl_get_local_id(msk, &skc_local);
|
||||
|
|
@ -437,119 +884,41 @@ bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc)
|
|||
return mptcp_pm_nl_is_backup(msk, &skc_local);
|
||||
}
|
||||
|
||||
static int mptcp_pm_get_addr(u8 id, struct mptcp_pm_addr_entry *addr,
|
||||
struct genl_info *info)
|
||||
static void mptcp_pm_subflows_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
|
||||
{
|
||||
if (info->attrs[MPTCP_PM_ATTR_TOKEN])
|
||||
return mptcp_userspace_pm_get_addr(id, addr, info);
|
||||
return mptcp_pm_nl_get_addr(id, addr, info);
|
||||
}
|
||||
struct mptcp_subflow_context *iter, *subflow = mptcp_subflow_ctx(ssk);
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
unsigned int active_max_loss_cnt;
|
||||
struct net *net = sock_net(sk);
|
||||
unsigned int stale_loss_cnt;
|
||||
bool slow;
|
||||
|
||||
int mptcp_pm_nl_get_addr_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct mptcp_pm_addr_entry addr;
|
||||
struct nlattr *attr;
|
||||
struct sk_buff *msg;
|
||||
void *reply;
|
||||
int ret;
|
||||
stale_loss_cnt = mptcp_stale_loss_cnt(net);
|
||||
if (subflow->stale || !stale_loss_cnt || subflow->stale_count <= stale_loss_cnt)
|
||||
return;
|
||||
|
||||
if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ENDPOINT_ADDR))
|
||||
return -EINVAL;
|
||||
/* look for another available subflow not in loss state */
|
||||
active_max_loss_cnt = max_t(int, stale_loss_cnt - 1, 1);
|
||||
mptcp_for_each_subflow(msk, iter) {
|
||||
if (iter != subflow && mptcp_subflow_active(iter) &&
|
||||
iter->stale_count < active_max_loss_cnt) {
|
||||
/* we have some alternatives, try to mark this subflow as idle ...*/
|
||||
slow = lock_sock_fast(ssk);
|
||||
if (!tcp_rtx_and_write_queues_empty(ssk)) {
|
||||
subflow->stale = 1;
|
||||
__mptcp_retransmit_pending_data(sk);
|
||||
MPTCP_INC_STATS(net, MPTCP_MIB_SUBFLOWSTALE);
|
||||
}
|
||||
unlock_sock_fast(ssk, slow);
|
||||
|
||||
attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
|
||||
ret = mptcp_pm_parse_entry(attr, info, false, &addr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
|
||||
info->genlhdr->cmd);
|
||||
if (!reply) {
|
||||
GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
|
||||
ret = -EMSGSIZE;
|
||||
goto fail;
|
||||
/* always try to push the pending data regardless of re-injections:
|
||||
* we can possibly use backup subflows now, and subflow selection
|
||||
* is cheap under the msk socket lock
|
||||
*/
|
||||
__mptcp_push_pending(sk, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mptcp_pm_get_addr(addr.addr.id, &addr, info);
|
||||
if (ret) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack, attr, "address not found");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = mptcp_nl_fill_addr(msg, &addr);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
genlmsg_end(msg, reply);
|
||||
ret = genlmsg_reply(msg, info);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb,
|
||||
struct mptcp_pm_addr_entry *entry)
|
||||
{
|
||||
void *hdr;
|
||||
|
||||
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, &mptcp_genl_family,
|
||||
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
|
||||
if (mptcp_nl_fill_addr(msg, entry) < 0) {
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mptcp_pm_dump_addr(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
|
||||
if (info->attrs[MPTCP_PM_ATTR_TOKEN])
|
||||
return mptcp_userspace_pm_dump_addr(msg, cb);
|
||||
return mptcp_pm_nl_dump_addr(msg, cb);
|
||||
}
|
||||
|
||||
int mptcp_pm_nl_get_addr_dumpit(struct sk_buff *msg,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
return mptcp_pm_dump_addr(msg, cb);
|
||||
}
|
||||
|
||||
static int mptcp_pm_set_flags(struct genl_info *info)
|
||||
{
|
||||
struct mptcp_pm_addr_entry loc = { .addr = { .family = AF_UNSPEC }, };
|
||||
struct nlattr *attr_loc;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (GENL_REQ_ATTR_CHECK(info, MPTCP_PM_ATTR_ADDR))
|
||||
return ret;
|
||||
|
||||
attr_loc = info->attrs[MPTCP_PM_ATTR_ADDR];
|
||||
ret = mptcp_pm_parse_entry(attr_loc, info, false, &loc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (info->attrs[MPTCP_PM_ATTR_TOKEN])
|
||||
return mptcp_userspace_pm_set_flags(&loc, info);
|
||||
return mptcp_pm_nl_set_flags(&loc, info);
|
||||
}
|
||||
|
||||
int mptcp_pm_nl_set_flags_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
return mptcp_pm_set_flags(info);
|
||||
}
|
||||
|
||||
void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
|
||||
|
|
@ -564,36 +933,44 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
|
|||
} else if (subflow->stale_rcv_tstamp == rcv_tstamp) {
|
||||
if (subflow->stale_count < U8_MAX)
|
||||
subflow->stale_count++;
|
||||
mptcp_pm_nl_subflow_chk_stale(msk, ssk);
|
||||
mptcp_pm_subflows_chk_stale(msk, ssk);
|
||||
} else {
|
||||
subflow->stale_count = 0;
|
||||
mptcp_subflow_set_active(subflow);
|
||||
}
|
||||
}
|
||||
|
||||
/* if sk is ipv4 or ipv6_only allows only same-family local and remote addresses,
|
||||
* otherwise allow any matching local/remote pair
|
||||
*/
|
||||
bool mptcp_pm_addr_families_match(const struct sock *sk,
|
||||
const struct mptcp_addr_info *loc,
|
||||
const struct mptcp_addr_info *rem)
|
||||
void mptcp_pm_worker(struct mptcp_sock *msk)
|
||||
{
|
||||
bool mptcp_is_v4 = sk->sk_family == AF_INET;
|
||||
struct mptcp_pm_data *pm = &msk->pm;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
||||
bool loc_is_v4 = loc->family == AF_INET || ipv6_addr_v4mapped(&loc->addr6);
|
||||
bool rem_is_v4 = rem->family == AF_INET || ipv6_addr_v4mapped(&rem->addr6);
|
||||
msk_owned_by_me(msk);
|
||||
|
||||
if (mptcp_is_v4)
|
||||
return loc_is_v4 && rem_is_v4;
|
||||
if (!(pm->status & MPTCP_PM_WORK_MASK))
|
||||
return;
|
||||
|
||||
if (ipv6_only_sock(sk))
|
||||
return !loc_is_v4 && !rem_is_v4;
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
return loc_is_v4 == rem_is_v4;
|
||||
#else
|
||||
return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET;
|
||||
#endif
|
||||
pr_debug("msk=%p status=%x\n", msk, pm->status);
|
||||
if (pm->status & BIT(MPTCP_PM_ADD_ADDR_SEND_ACK)) {
|
||||
pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_SEND_ACK);
|
||||
mptcp_pm_addr_send_ack(msk);
|
||||
}
|
||||
if (pm->status & BIT(MPTCP_PM_RM_ADDR_RECEIVED)) {
|
||||
pm->status &= ~BIT(MPTCP_PM_RM_ADDR_RECEIVED);
|
||||
mptcp_pm_rm_addr_recv(msk);
|
||||
}
|
||||
__mptcp_pm_kernel_worker(msk);
|
||||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
}
|
||||
|
||||
void mptcp_pm_destroy(struct mptcp_sock *msk)
|
||||
{
|
||||
mptcp_pm_free_anno_list(msk);
|
||||
|
||||
if (mptcp_pm_is_userspace(msk))
|
||||
mptcp_userspace_pm_free_local_addr_list(msk);
|
||||
}
|
||||
|
||||
void mptcp_pm_data_reset(struct mptcp_sock *msk)
|
||||
|
|
|
|||
1410
net/mptcp/pm_kernel.c
Normal file
1410
net/mptcp/pm_kernel.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -12,15 +12,12 @@
|
|||
list_for_each_entry(__entry, \
|
||||
&((__msk)->pm.userspace_pm_local_addr_list), list)
|
||||
|
||||
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
|
||||
void mptcp_userspace_pm_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);
|
||||
|
|
@ -130,27 +127,22 @@ mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
|
|||
}
|
||||
|
||||
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *skc)
|
||||
struct mptcp_pm_addr_entry *skc)
|
||||
{
|
||||
struct mptcp_pm_addr_entry *entry = NULL, new_entry;
|
||||
__be16 msk_sport = ((struct inet_sock *)
|
||||
inet_sk((struct sock *)msk))->inet_sport;
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
entry = mptcp_userspace_pm_lookup_addr(msk, skc);
|
||||
entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
if (entry)
|
||||
return entry->addr.id;
|
||||
|
||||
memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
|
||||
new_entry.addr = *skc;
|
||||
new_entry.addr.id = 0;
|
||||
new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
|
||||
if (skc->addr.port == msk_sport)
|
||||
skc->addr.port = 0;
|
||||
|
||||
if (new_entry.addr.port == msk_sport)
|
||||
new_entry.addr.port = 0;
|
||||
|
||||
return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true);
|
||||
return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
|
||||
}
|
||||
|
||||
bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
|
||||
|
|
@ -239,7 +231,7 @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) {
|
||||
msk->pm.add_addr_signaled++;
|
||||
mptcp_pm_announce_addr(msk, &addr_val.addr, false);
|
||||
mptcp_pm_nl_addr_send_ack(msk);
|
||||
mptcp_pm_addr_send_ack(msk);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
|
@ -610,10 +602,10 @@ int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_entry *local,
|
|||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
lock_sock(sk);
|
||||
ret = mptcp_pm_nl_mp_prio_send_ack(msk, &local->addr, &rem, bkup);
|
||||
ret = mptcp_pm_mp_prio_send_ack(msk, &local->addr, &rem, bkup);
|
||||
release_sock(sk);
|
||||
|
||||
/* mptcp_pm_nl_mp_prio_send_ack() only fails in one case */
|
||||
/* mptcp_pm_mp_prio_send_ack() only fails in one case */
|
||||
if (ret < 0)
|
||||
GENL_SET_ERR_MSG(info, "subflow not found");
|
||||
|
||||
|
|
|
|||
|
|
@ -2681,7 +2681,7 @@ static void mptcp_worker(struct work_struct *work)
|
|||
|
||||
mptcp_check_fastclose(msk);
|
||||
|
||||
mptcp_pm_nl_work(msk);
|
||||
mptcp_pm_worker(msk);
|
||||
|
||||
mptcp_check_send_data_fin(sk);
|
||||
mptcp_check_data_fin_ack(sk);
|
||||
|
|
@ -3302,8 +3302,7 @@ void mptcp_destroy_common(struct mptcp_sock *msk, unsigned int flags)
|
|||
* inet_sock_destruct() will dispose it
|
||||
*/
|
||||
mptcp_token_destroy(msk);
|
||||
mptcp_pm_free_anno_list(msk);
|
||||
mptcp_free_local_addr_list(msk);
|
||||
mptcp_pm_destroy(msk);
|
||||
}
|
||||
|
||||
static void mptcp_destroy(struct sock *sk)
|
||||
|
|
|
|||
|
|
@ -724,7 +724,10 @@ void mptcp_set_state(struct sock *sk, int state);
|
|||
|
||||
bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
|
||||
const struct mptcp_addr_info *b, bool use_port);
|
||||
void mptcp_local_address(const struct sock_common *skc, struct mptcp_addr_info *addr);
|
||||
void mptcp_local_address(const struct sock_common *skc,
|
||||
struct mptcp_addr_info *addr);
|
||||
void mptcp_remote_address(const struct sock_common *skc,
|
||||
struct mptcp_addr_info *addr);
|
||||
|
||||
/* called with sk socket lock held */
|
||||
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,
|
||||
|
|
@ -983,6 +986,7 @@ __sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum su
|
|||
void __init mptcp_pm_init(void);
|
||||
void mptcp_pm_data_init(struct mptcp_sock *msk);
|
||||
void mptcp_pm_data_reset(struct mptcp_sock *msk);
|
||||
void mptcp_pm_destroy(struct mptcp_sock *msk);
|
||||
int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
|
||||
struct mptcp_addr_info *addr);
|
||||
int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
|
||||
|
|
@ -992,7 +996,6 @@ bool mptcp_pm_addr_families_match(const struct sock *sk,
|
|||
const struct mptcp_addr_info *loc,
|
||||
const struct mptcp_addr_info *rem);
|
||||
void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
|
||||
void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
|
||||
void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side);
|
||||
void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk);
|
||||
bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk);
|
||||
|
|
@ -1006,27 +1009,27 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
|
|||
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
|
||||
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *remote);
|
||||
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk);
|
||||
void mptcp_pm_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow,
|
||||
bool prio, bool backup);
|
||||
void mptcp_pm_addr_send_ack(struct mptcp_sock *msk);
|
||||
void mptcp_pm_nl_rm_addr(struct mptcp_sock *msk, u8 rm_id);
|
||||
void mptcp_pm_rm_subflow(struct mptcp_sock *msk,
|
||||
const struct mptcp_rm_list *rm_list);
|
||||
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);
|
||||
void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq);
|
||||
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *addr,
|
||||
struct mptcp_addr_info *rem,
|
||||
u8 bkup);
|
||||
int mptcp_pm_mp_prio_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_addr_info *addr,
|
||||
struct mptcp_addr_info *rem,
|
||||
u8 bkup);
|
||||
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
|
||||
bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk);
|
||||
struct mptcp_pm_add_entry *
|
||||
mptcp_pm_del_add_timer(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr, bool check_id);
|
||||
struct mptcp_pm_add_entry *
|
||||
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
||||
const struct mptcp_addr_info *saddr);
|
||||
bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
||||
|
|
@ -1042,7 +1045,7 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_
|
|||
void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
|
||||
void mptcp_free_local_addr_list(struct mptcp_sock *msk);
|
||||
void mptcp_userspace_pm_free_local_addr_list(struct mptcp_sock *msk);
|
||||
|
||||
void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
|
||||
const struct sock *ssk, gfp_t gfp);
|
||||
|
|
@ -1054,8 +1057,6 @@ bool mptcp_userspace_pm_active(const struct mptcp_sock *msk);
|
|||
|
||||
void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow,
|
||||
struct request_sock *req);
|
||||
int mptcp_nl_fill_addr(struct sk_buff *skb,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
int mptcp_pm_genl_fill_addr(struct sk_buff *msg,
|
||||
struct netlink_callback *cb,
|
||||
struct mptcp_pm_addr_entry *entry);
|
||||
|
|
@ -1121,8 +1122,10 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, const struct sk_buff *skb,
|
|||
bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
||||
struct mptcp_rm_list *rm_list);
|
||||
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
|
||||
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *skc);
|
||||
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
|
||||
struct mptcp_pm_addr_entry *skc);
|
||||
bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc);
|
||||
bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
|
||||
|
|
@ -1145,7 +1148,8 @@ static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflo
|
|||
}
|
||||
|
||||
void __init mptcp_pm_nl_init(void);
|
||||
void mptcp_pm_nl_work(struct mptcp_sock *msk);
|
||||
void mptcp_pm_worker(struct mptcp_sock *msk);
|
||||
void __mptcp_pm_kernel_worker(struct mptcp_sock *msk);
|
||||
unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk);
|
||||
unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk);
|
||||
unsigned int mptcp_pm_get_subflows_max(const struct mptcp_sock *msk);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user