Merge branch 'mptcp-small-improvements-fix-and-clean-ups'
Mat Martineau says: ==================== mptcp: small improvements, fix and clean-ups This series contain mostly unrelated patches: - The two first patches can be seen as "fixes". They are part of this series for -next because it looks like the last batch of fixes for v6.9 has already been sent. These fixes are not urgent, so they can wait if an unlikely v6.9-rc8 is published. About the two patches: - Patch 1 fixes getsockopt(SO_KEEPALIVE) support on MPTCP sockets - Patch 2 makes sure the full TCP keep-alive feature is supported, not just SO_KEEPALIVE. - Patch 3 is a small optimisation when getsockopt(MPTCP_INFO) is used without buffer, just to check if MPTCP is still being used: no fallback to TCP. - Patch 4 adds net.mptcp.available_schedulers sysctl knob to list packet schedulers, similar to net.ipv4.tcp_available_congestion_control. - Patch 5 and 6 fix CheckPatch warnings: "prefer strscpy over strcpy" and "else is not generally useful after a break or return". - Patch 7 and 8 remove and add header includes to avoid unused ones, and add missing ones to be self-contained. ==================== Link: https://lore.kernel.org/r/20240514011335.176158-1-martineau@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
95125152dc
@ -97,6 +97,9 @@ struct mptcp_out_options {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MPTCP_SCHED_NAME_MAX 16
|
#define MPTCP_SCHED_NAME_MAX 16
|
||||||
|
#define MPTCP_SCHED_MAX 128
|
||||||
|
#define MPTCP_SCHED_BUF_MAX (MPTCP_SCHED_NAME_MAX * MPTCP_SCHED_MAX)
|
||||||
|
|
||||||
#define MPTCP_SUBFLOWS_MAX 8
|
#define MPTCP_SUBFLOWS_MAX 8
|
||||||
|
|
||||||
struct mptcp_sched_data {
|
struct mptcp_sched_data {
|
||||||
|
@ -92,7 +92,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
|||||||
pernet->allow_join_initial_addr_port = 1;
|
pernet->allow_join_initial_addr_port = 1;
|
||||||
pernet->stale_loss_cnt = 4;
|
pernet->stale_loss_cnt = 4;
|
||||||
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
|
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
|
||||||
strcpy(pernet->scheduler, "default");
|
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
@ -133,6 +133,24 @@ static int proc_scheduler(struct ctl_table *ctl, int write,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int proc_available_schedulers(struct ctl_table *ctl,
|
||||||
|
int write, void *buffer,
|
||||||
|
size_t *lenp, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ctl_table tbl = { .maxlen = MPTCP_SCHED_BUF_MAX, };
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tbl.data = kmalloc(tbl.maxlen, GFP_USER);
|
||||||
|
if (!tbl.data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mptcp_get_available_schedulers(tbl.data, MPTCP_SCHED_BUF_MAX);
|
||||||
|
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
|
||||||
|
kfree(tbl.data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ctl_table mptcp_sysctl_table[] = {
|
static struct ctl_table mptcp_sysctl_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "enabled",
|
.procname = "enabled",
|
||||||
@ -187,6 +205,12 @@ static struct ctl_table mptcp_sysctl_table[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_scheduler,
|
.proc_handler = proc_scheduler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.procname = "available_schedulers",
|
||||||
|
.maxlen = MPTCP_SCHED_BUF_MAX,
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_available_schedulers,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.procname = "close_timeout",
|
.procname = "close_timeout",
|
||||||
.maxlen = sizeof(unsigned int),
|
.maxlen = sizeof(unsigned int),
|
||||||
@ -214,7 +238,8 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
|
|||||||
table[4].data = &pernet->stale_loss_cnt;
|
table[4].data = &pernet->stale_loss_cnt;
|
||||||
table[5].data = &pernet->pm_type;
|
table[5].data = &pernet->pm_type;
|
||||||
table[6].data = &pernet->scheduler;
|
table[6].data = &pernet->scheduler;
|
||||||
table[7].data = &pernet->close_timeout;
|
/* table[7] is for available_schedulers which is read-only info */
|
||||||
|
table[8].data = &pernet->close_timeout;
|
||||||
|
|
||||||
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
|
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
|
||||||
ARRAY_SIZE(mptcp_sysctl_table));
|
ARRAY_SIZE(mptcp_sysctl_table));
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include <net/inet_common.h>
|
||||||
|
|
||||||
enum linux_mptcp_mib_field {
|
enum linux_mptcp_mib_field {
|
||||||
MPTCP_MIB_NUM = 0,
|
MPTCP_MIB_NUM = 0,
|
||||||
MPTCP_MIB_MPCAPABLEPASSIVE, /* Received SYN with MP_CAPABLE */
|
MPTCP_MIB_MPCAPABLEPASSIVE, /* Received SYN with MP_CAPABLE */
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "mib.h"
|
#include "mib.h"
|
||||||
|
#include "mptcp_pm_gen.h"
|
||||||
|
|
||||||
static int pm_nl_pernet_id;
|
static int pm_nl_pernet_id;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "mib.h"
|
#include "mib.h"
|
||||||
|
#include "mptcp_pm_gen.h"
|
||||||
|
|
||||||
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
|
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
|
||||||
{
|
{
|
||||||
|
@ -2814,7 +2814,8 @@ static void mptcp_ca_reset(struct sock *sk)
|
|||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
|
|
||||||
tcp_assign_congestion_control(sk);
|
tcp_assign_congestion_control(sk);
|
||||||
strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name);
|
strscpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name,
|
||||||
|
sizeof(mptcp_sk(sk)->ca_name));
|
||||||
|
|
||||||
/* no need to keep a reference to the ops, the name will suffice */
|
/* no need to keep a reference to the ops, the name will suffice */
|
||||||
tcp_cleanup_congestion_control(sk);
|
tcp_cleanup_congestion_control(sk);
|
||||||
@ -4169,7 +4170,7 @@ int __init mptcp_proto_v6_init(void)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
mptcp_v6_prot = mptcp_prot;
|
mptcp_v6_prot = mptcp_prot;
|
||||||
strcpy(mptcp_v6_prot.name, "MPTCPv6");
|
strscpy(mptcp_v6_prot.name, "MPTCPv6", sizeof(mptcp_v6_prot.name));
|
||||||
mptcp_v6_prot.slab = NULL;
|
mptcp_v6_prot.slab = NULL;
|
||||||
mptcp_v6_prot.obj_size = sizeof(struct mptcp6_sock);
|
mptcp_v6_prot.obj_size = sizeof(struct mptcp6_sock);
|
||||||
mptcp_v6_prot.ipv6_pinfo_offset = offsetof(struct mptcp6_sock, np);
|
mptcp_v6_prot.ipv6_pinfo_offset = offsetof(struct mptcp6_sock, np);
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#include <net/genetlink.h>
|
#include <net/genetlink.h>
|
||||||
#include <net/rstreason.h>
|
#include <net/rstreason.h>
|
||||||
|
|
||||||
#include "mptcp_pm_gen.h"
|
|
||||||
|
|
||||||
#define MPTCP_SUPPORTED_VERSION 1
|
#define MPTCP_SUPPORTED_VERSION 1
|
||||||
|
|
||||||
/* MPTCP option bits */
|
/* MPTCP option bits */
|
||||||
@ -312,6 +310,9 @@ struct mptcp_sock {
|
|||||||
free_first:1,
|
free_first:1,
|
||||||
rcvspace_init:1;
|
rcvspace_init:1;
|
||||||
u32 notsent_lowat;
|
u32 notsent_lowat;
|
||||||
|
int keepalive_cnt;
|
||||||
|
int keepalive_idle;
|
||||||
|
int keepalive_intvl;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
struct sk_buff *ooo_last_skb;
|
struct sk_buff *ooo_last_skb;
|
||||||
struct rb_root out_of_order_queue;
|
struct rb_root out_of_order_queue;
|
||||||
@ -683,6 +684,7 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net);
|
|||||||
unsigned int mptcp_close_timeout(const struct sock *sk);
|
unsigned int mptcp_close_timeout(const struct sock *sk);
|
||||||
int mptcp_get_pm_type(const struct net *net);
|
int mptcp_get_pm_type(const struct net *net);
|
||||||
const char *mptcp_get_scheduler(const struct net *net);
|
const char *mptcp_get_scheduler(const struct net *net);
|
||||||
|
void mptcp_get_available_schedulers(char *buf, size_t maxlen);
|
||||||
void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
|
void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
|
||||||
struct mptcp_subflow_context *subflow,
|
struct mptcp_subflow_context *subflow,
|
||||||
const struct mptcp_options_received *mp_opt);
|
const struct mptcp_options_received *mp_opt);
|
||||||
|
@ -51,6 +51,28 @@ struct mptcp_sched_ops *mptcp_sched_find(const char *name)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build string with list of available scheduler values.
|
||||||
|
* Similar to tcp_get_available_congestion_control()
|
||||||
|
*/
|
||||||
|
void mptcp_get_available_schedulers(char *buf, size_t maxlen)
|
||||||
|
{
|
||||||
|
struct mptcp_sched_ops *sched;
|
||||||
|
size_t offs = 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
spin_lock(&mptcp_sched_list_lock);
|
||||||
|
list_for_each_entry_rcu(sched, &mptcp_sched_list, list) {
|
||||||
|
offs += snprintf(buf + offs, maxlen - offs,
|
||||||
|
"%s%s",
|
||||||
|
offs == 0 ? "" : " ", sched->name);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(offs >= maxlen))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock(&mptcp_sched_list_lock);
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
int mptcp_register_scheduler(struct mptcp_sched_ops *sched)
|
int mptcp_register_scheduler(struct mptcp_sched_ops *sched)
|
||||||
{
|
{
|
||||||
if (!sched->get_subflow)
|
if (!sched->get_subflow)
|
||||||
|
@ -181,8 +181,6 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
|
|||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case SO_KEEPALIVE:
|
case SO_KEEPALIVE:
|
||||||
mptcp_sol_socket_sync_intval(msk, optname, val);
|
|
||||||
return 0;
|
|
||||||
case SO_DEBUG:
|
case SO_DEBUG:
|
||||||
case SO_MARK:
|
case SO_MARK:
|
||||||
case SO_PRIORITY:
|
case SO_PRIORITY:
|
||||||
@ -618,12 +616,37 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
strcpy(msk->ca_name, name);
|
strscpy(msk->ca_name, name, sizeof(msk->ca_name));
|
||||||
|
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __mptcp_setsockopt_set_val(struct mptcp_sock *msk, int max,
|
||||||
|
int (*set_val)(struct sock *, int),
|
||||||
|
int *msk_val, int val)
|
||||||
|
{
|
||||||
|
struct mptcp_subflow_context *subflow;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
mptcp_for_each_subflow(msk, subflow) {
|
||||||
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lock_sock(ssk);
|
||||||
|
ret = set_val(ssk, val);
|
||||||
|
err = err ? : ret;
|
||||||
|
release_sock(ssk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
*msk_val = val;
|
||||||
|
sockopt_seq_inc(msk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val)
|
static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow;
|
struct mptcp_subflow_context *subflow;
|
||||||
@ -820,6 +843,22 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
|
|||||||
case TCP_NODELAY:
|
case TCP_NODELAY:
|
||||||
ret = __mptcp_setsockopt_sol_tcp_nodelay(msk, val);
|
ret = __mptcp_setsockopt_sol_tcp_nodelay(msk, val);
|
||||||
break;
|
break;
|
||||||
|
case TCP_KEEPIDLE:
|
||||||
|
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPIDLE,
|
||||||
|
&tcp_sock_set_keepidle_locked,
|
||||||
|
&msk->keepalive_idle, val);
|
||||||
|
break;
|
||||||
|
case TCP_KEEPINTVL:
|
||||||
|
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPINTVL,
|
||||||
|
&tcp_sock_set_keepintvl,
|
||||||
|
&msk->keepalive_intvl, val);
|
||||||
|
break;
|
||||||
|
case TCP_KEEPCNT:
|
||||||
|
ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPCNT,
|
||||||
|
&tcp_sock_set_keepcnt,
|
||||||
|
&msk->keepalive_cnt,
|
||||||
|
val);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENOPROTOOPT;
|
ret = -ENOPROTOOPT;
|
||||||
}
|
}
|
||||||
@ -960,6 +999,10 @@ static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, in
|
|||||||
if (get_user(len, optlen))
|
if (get_user(len, optlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
/* When used only to check if a fallback to TCP happened. */
|
||||||
|
if (len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
len = min_t(unsigned int, len, sizeof(struct mptcp_info));
|
len = min_t(unsigned int, len, sizeof(struct mptcp_info));
|
||||||
|
|
||||||
mptcp_diag_fill_info(msk, &m_info);
|
mptcp_diag_fill_info(msk, &m_info);
|
||||||
@ -1328,6 +1371,8 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
|
|||||||
static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
|
static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
|
||||||
char __user *optval, int __user *optlen)
|
char __user *optval, int __user *optlen)
|
||||||
{
|
{
|
||||||
|
struct sock *sk = (void *)msk;
|
||||||
|
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
case TCP_ULP:
|
case TCP_ULP:
|
||||||
case TCP_CONGESTION:
|
case TCP_CONGESTION:
|
||||||
@ -1346,6 +1391,18 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
|
|||||||
return mptcp_put_int_option(msk, optval, optlen, msk->cork);
|
return mptcp_put_int_option(msk, optval, optlen, msk->cork);
|
||||||
case TCP_NODELAY:
|
case TCP_NODELAY:
|
||||||
return mptcp_put_int_option(msk, optval, optlen, msk->nodelay);
|
return mptcp_put_int_option(msk, optval, optlen, msk->nodelay);
|
||||||
|
case TCP_KEEPIDLE:
|
||||||
|
return mptcp_put_int_option(msk, optval, optlen,
|
||||||
|
msk->keepalive_idle ? :
|
||||||
|
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_time) / HZ);
|
||||||
|
case TCP_KEEPINTVL:
|
||||||
|
return mptcp_put_int_option(msk, optval, optlen,
|
||||||
|
msk->keepalive_intvl ? :
|
||||||
|
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_intvl) / HZ);
|
||||||
|
case TCP_KEEPCNT:
|
||||||
|
return mptcp_put_int_option(msk, optval, optlen,
|
||||||
|
msk->keepalive_cnt ? :
|
||||||
|
READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes));
|
||||||
case TCP_NOTSENT_LOWAT:
|
case TCP_NOTSENT_LOWAT:
|
||||||
return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
|
return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
|
||||||
case TCP_IS_MPTCP:
|
case TCP_IS_MPTCP:
|
||||||
@ -1465,6 +1522,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
|
|||||||
tcp_set_congestion_control(ssk, msk->ca_name, false, true);
|
tcp_set_congestion_control(ssk, msk->ca_name, false, true);
|
||||||
__tcp_sock_set_cork(ssk, !!msk->cork);
|
__tcp_sock_set_cork(ssk, !!msk->cork);
|
||||||
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
|
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);
|
||||||
|
tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle);
|
||||||
|
tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl);
|
||||||
|
tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt);
|
||||||
|
|
||||||
inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
|
inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
|
||||||
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
|
||||||
|
@ -1119,6 +1119,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mpext->data_fin == 1) {
|
if (mpext->data_fin == 1) {
|
||||||
|
u64 data_fin_seq;
|
||||||
|
|
||||||
if (data_len == 1) {
|
if (data_len == 1) {
|
||||||
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
|
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
|
||||||
mpext->dsn64);
|
mpext->dsn64);
|
||||||
@ -1131,26 +1133,26 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
|
|||||||
*/
|
*/
|
||||||
skb_ext_del(skb, SKB_EXT_MPTCP);
|
skb_ext_del(skb, SKB_EXT_MPTCP);
|
||||||
return MAPPING_OK;
|
return MAPPING_OK;
|
||||||
} else {
|
|
||||||
if (updated)
|
|
||||||
mptcp_schedule_work((struct sock *)msk);
|
|
||||||
|
|
||||||
return MAPPING_DATA_FIN;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
u64 data_fin_seq = mpext->data_seq + data_len - 1;
|
|
||||||
|
|
||||||
/* If mpext->data_seq is a 32-bit value, data_fin_seq
|
if (updated)
|
||||||
* must also be limited to 32 bits.
|
mptcp_schedule_work((struct sock *)msk);
|
||||||
*/
|
|
||||||
if (!mpext->dsn64)
|
|
||||||
data_fin_seq &= GENMASK_ULL(31, 0);
|
|
||||||
|
|
||||||
mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
|
return MAPPING_DATA_FIN;
|
||||||
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
|
|
||||||
data_fin_seq, mpext->dsn64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data_fin_seq = mpext->data_seq + data_len - 1;
|
||||||
|
|
||||||
|
/* If mpext->data_seq is a 32-bit value, data_fin_seq must also
|
||||||
|
* be limited to 32 bits.
|
||||||
|
*/
|
||||||
|
if (!mpext->dsn64)
|
||||||
|
data_fin_seq &= GENMASK_ULL(31, 0);
|
||||||
|
|
||||||
|
mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
|
||||||
|
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
|
||||||
|
data_fin_seq, mpext->dsn64);
|
||||||
|
|
||||||
/* Adjust for DATA_FIN using 1 byte of sequence space */
|
/* Adjust for DATA_FIN using 1 byte of sequence space */
|
||||||
data_len--;
|
data_len--;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user