mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'mptcp-pm-drop-tcp-ts-with-add_addrv6-port'
Matthieu Baerts says: ==================== mptcp: pm: drop TCP TS with ADD_ADDRv6 + port Up to this series, it was possible to add a "signal" MPTCP endpoint with an IPv6 address and a port, or to directly request to send an ADD_ADDR with a v6 address and a port, but the expected ADD_ADDR wasn't sent when TCP timestamps was used for the connection. In fact, such signalling option cannot be sent when TCP timestamps is used due to a lack of option space: the limit is at 40 bytes, and, with padding, TCP timestamps is taking 12 bytes, while an ADD_ADDR IPv6 + port is taking 30 bytes. The selected solution here is to simply drop the TCP timestamps option when such ADD_ADDR of 30 bytes needs to be sent. - Patches 1-3: small cleanups to avoid computing ADD/RM_ADDR twice. - Patches 4-7: the new feature, controlled by a new sysctl knob. - Patch 8: extra checks in the MPTCP Join selftests. - Patches 9-15: A bunch of refactoring: renamed confusing helpers and variables, and prevent future misused functions. ==================== Link: https://patch.msgid.link/20260605-net-next-mptcp-add-addr6-port-ts-v2-0-758e7ca73f4d@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
3fbbb5a628
|
|
@ -21,6 +21,19 @@ add_addr_timeout - INTEGER (seconds)
|
|||
|
||||
Default: 120
|
||||
|
||||
add_addr_v6_port_drop_ts - BOOLEAN
|
||||
Control whether preparing an ADD_ADDR with an IPv6 address and a port
|
||||
should drop the TCP timestamps option to have enough option space to
|
||||
send the signal.
|
||||
|
||||
If there is not enough option space, and the TCP timestamps option
|
||||
cannot be dropped, the signal cannot be sent. Note that dropping the TCP
|
||||
timestamps option for one packet of the connection could disrupt some
|
||||
middleboxes: even if it should be unlikely, they could drop the packet
|
||||
or block the connection. This is a per-namespace sysctl.
|
||||
|
||||
Default: 1 (enabled)
|
||||
|
||||
allow_join_initial_addr_port - BOOLEAN
|
||||
Allow peers to send join requests to the IP address and port number used
|
||||
by the initial subflow if the value is 1. This controls a flag that is
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ struct mptcp_out_options {
|
|||
u8 reset_reason:4,
|
||||
reset_transient:1,
|
||||
csum_reqd:1,
|
||||
allow_join_id0:1;
|
||||
allow_join_id0:1,
|
||||
drop_ts:1;
|
||||
union {
|
||||
struct {
|
||||
u64 sndr_key;
|
||||
|
|
@ -153,7 +154,7 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
|
|||
bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
|
||||
struct mptcp_out_options *opts);
|
||||
int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
||||
unsigned int remaining,
|
||||
unsigned int remaining, bool has_ts,
|
||||
struct mptcp_out_options *opts);
|
||||
bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb);
|
||||
|
||||
|
|
@ -269,14 +270,6 @@ static inline bool mptcp_synack_options(const struct request_sock *req,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int mptcp_established_options(struct sock *sk,
|
||||
struct sk_buff *skb,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool mptcp_incoming_options(struct sock *sk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1175,6 +1175,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
|
|||
size += TCPOLEN_TSTAMP_ALIGNED;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
/* MPTCP options have precedence over SACK for the limited TCP
|
||||
* option space because a MPTCP connection would be forced to
|
||||
* fall back to regular TCP if a required multipath option is
|
||||
|
|
@ -1183,15 +1184,22 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
|
|||
*/
|
||||
if (sk_is_mptcp(sk)) {
|
||||
unsigned int remaining = MAX_TCP_OPTION_SPACE - size;
|
||||
bool has_ts = opts->options & OPTION_TS;
|
||||
int opt_size;
|
||||
|
||||
opt_size = mptcp_established_options(sk, skb, remaining,
|
||||
opts->mptcp.drop_ts = 0;
|
||||
|
||||
opt_size = mptcp_established_options(sk, skb, remaining, has_ts,
|
||||
&opts->mptcp);
|
||||
if (opt_size >= 0) {
|
||||
opts->options |= OPTION_MPTCP;
|
||||
size += opt_size;
|
||||
|
||||
if (opts->mptcp.drop_ts)
|
||||
opts->options &= ~OPTION_TS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack;
|
||||
if (unlikely(eff_sacks)) {
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ struct mptcp_pernet {
|
|||
unsigned int close_timeout;
|
||||
unsigned int stale_loss_cnt;
|
||||
atomic_t active_disable_times;
|
||||
u8 syn_retrans_before_tcp_fallback;
|
||||
unsigned long active_disable_stamp;
|
||||
u8 syn_retrans_before_tcp_fallback;
|
||||
u8 mptcp_enabled;
|
||||
u8 checksum_enabled;
|
||||
u8 allow_join_initial_addr_port;
|
||||
u8 pm_type;
|
||||
u8 add_addr_v6_port_drop_ts;
|
||||
char scheduler[MPTCP_SCHED_NAME_MAX];
|
||||
char path_manager[MPTCP_PM_NAME_MAX];
|
||||
};
|
||||
|
|
@ -94,6 +95,11 @@ const char *mptcp_get_scheduler(const struct net *net)
|
|||
return mptcp_get_pernet(net)->scheduler;
|
||||
}
|
||||
|
||||
unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net)
|
||||
{
|
||||
return READ_ONCE(mptcp_get_pernet(net)->add_addr_v6_port_drop_ts);
|
||||
}
|
||||
|
||||
static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
||||
{
|
||||
pernet->mptcp_enabled = 1;
|
||||
|
|
@ -108,6 +114,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
|||
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
|
||||
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
|
||||
strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager));
|
||||
pernet->add_addr_v6_port_drop_ts = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
|
@ -362,6 +369,14 @@ static struct ctl_table mptcp_sysctl_table[] = {
|
|||
.mode = 0444,
|
||||
.proc_handler = proc_available_path_managers,
|
||||
},
|
||||
{
|
||||
.procname = "add_addr_v6_port_drop_ts",
|
||||
.maxlen = sizeof(u8),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dou8vec_minmax,
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra2 = SYSCTL_ONE
|
||||
},
|
||||
};
|
||||
|
||||
static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
|
||||
|
|
@ -389,6 +404,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
|
|||
table[10].data = &pernet->syn_retrans_before_tcp_fallback;
|
||||
table[11].data = &pernet->path_manager;
|
||||
/* table[12] is for available_path_managers which is read-only info */
|
||||
table[13].data = &pernet->add_addr_v6_port_drop_ts;
|
||||
|
||||
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
|
||||
ARRAY_SIZE(mptcp_sysctl_table));
|
||||
|
|
|
|||
|
|
@ -447,8 +447,7 @@ static void clear_3rdack_retransmission(struct sock *sk)
|
|||
}
|
||||
|
||||
static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
|
||||
bool snd_data_fin_enable,
|
||||
unsigned int *size,
|
||||
bool snd_data_fin_enable, int *size,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
|
|
@ -560,8 +559,7 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
|
|||
}
|
||||
|
||||
static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
||||
bool snd_data_fin_enable,
|
||||
unsigned int *size,
|
||||
bool snd_data_fin_enable, int *size,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
|
|
@ -658,17 +656,17 @@ static u64 add_addr_generate_hmac(u64 key1, u64 key2,
|
|||
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
|
||||
}
|
||||
|
||||
static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb,
|
||||
unsigned int *size,
|
||||
static bool mptcp_established_options_add_addr(struct sock *sk,
|
||||
struct sk_buff *skb, int *size,
|
||||
unsigned int remaining,
|
||||
bool has_ts,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||
unsigned int opt_size = *size;
|
||||
struct mptcp_addr_info addr;
|
||||
bool drop_ts = has_ts;
|
||||
bool echo;
|
||||
int len;
|
||||
|
||||
/* add addr will strip the existing options, be sure to avoid breaking
|
||||
* MPC/MPJ handshakes
|
||||
|
|
@ -676,21 +674,14 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
|
|||
if (!mptcp_pm_should_add_signal(msk) ||
|
||||
(opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) ||
|
||||
!skb || !skb_is_tcp_pure_ack(skb) ||
|
||||
!mptcp_pm_add_addr_signal(msk, opt_size, remaining, &addr, &echo))
|
||||
!mptcp_pm_add_addr_signal(msk, size, remaining, &addr, &echo,
|
||||
&drop_ts))
|
||||
return false;
|
||||
|
||||
remaining += opt_size;
|
||||
|
||||
len = mptcp_add_addr_len(addr.family, echo, !!addr.port);
|
||||
if (remaining < len)
|
||||
return false;
|
||||
|
||||
*size = len;
|
||||
pr_debug("drop other suboptions\n");
|
||||
opts->suboptions = 0;
|
||||
*size -= opt_size;
|
||||
opts->suboptions = OPTION_MPTCP_ADD_ADDR;
|
||||
opts->drop_ts = drop_ts;
|
||||
opts->addr = addr;
|
||||
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
|
||||
if (!echo) {
|
||||
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX);
|
||||
opts->ahmac = add_addr_generate_hmac(READ_ONCE(msk->local_key),
|
||||
|
|
@ -706,27 +697,19 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mptcp_established_options_rm_addr(struct sock *sk,
|
||||
unsigned int *size,
|
||||
static bool mptcp_established_options_rm_addr(struct sock *sk, int *size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||
struct mptcp_rm_list rm_list;
|
||||
int i, len;
|
||||
int i;
|
||||
|
||||
if (!mptcp_pm_should_rm_signal(msk) ||
|
||||
!(mptcp_pm_rm_addr_signal(msk, remaining, &rm_list)))
|
||||
!(mptcp_pm_rm_addr_signal(msk, remaining, &rm_list, size)))
|
||||
return false;
|
||||
|
||||
len = mptcp_rm_addr_len(&rm_list);
|
||||
if (len < 0)
|
||||
return false;
|
||||
if (remaining < len)
|
||||
return false;
|
||||
|
||||
*size = len;
|
||||
opts->suboptions |= OPTION_MPTCP_RM_ADDR;
|
||||
opts->rm_list = rm_list;
|
||||
|
||||
|
|
@ -736,8 +719,7 @@ static bool mptcp_established_options_rm_addr(struct sock *sk,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mptcp_established_options_mp_prio(struct sock *sk,
|
||||
unsigned int *size,
|
||||
static bool mptcp_established_options_mp_prio(struct sock *sk, int *size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
|
|
@ -762,8 +744,8 @@ static bool mptcp_established_options_mp_prio(struct sock *sk,
|
|||
return true;
|
||||
}
|
||||
|
||||
static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb,
|
||||
unsigned int *size,
|
||||
static noinline bool mptcp_established_options_rst(struct sock *sk,
|
||||
int *size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
|
|
@ -781,8 +763,7 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mptcp_established_options_fastclose(struct sock *sk,
|
||||
unsigned int *size,
|
||||
static bool mptcp_established_options_fastclose(struct sock *sk, int *size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
|
|
@ -804,8 +785,7 @@ static bool mptcp_established_options_fastclose(struct sock *sk,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mptcp_established_options_mp_fail(struct sock *sk,
|
||||
unsigned int *size,
|
||||
static bool mptcp_established_options_mp_fail(struct sock *sk, int *size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
|
|
@ -828,15 +808,15 @@ static bool mptcp_established_options_mp_fail(struct sock *sk,
|
|||
}
|
||||
|
||||
int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
||||
unsigned int remaining,
|
||||
unsigned int remaining, bool has_ts,
|
||||
struct mptcp_out_options *opts)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||
unsigned int opt_size = 0;
|
||||
int total_size = 0;
|
||||
bool snd_data_fin;
|
||||
bool ret = false;
|
||||
int opt_size = 0;
|
||||
|
||||
opts->suboptions = 0;
|
||||
|
||||
|
|
@ -853,7 +833,7 @@ int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
|||
remaining -= opt_size;
|
||||
}
|
||||
/* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */
|
||||
if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) {
|
||||
if (mptcp_established_options_rst(sk, &opt_size, remaining, opts)) {
|
||||
total_size += opt_size;
|
||||
remaining -= opt_size;
|
||||
}
|
||||
|
|
@ -864,7 +844,7 @@ int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
|||
if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, opts))
|
||||
ret = true;
|
||||
else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, opts)) {
|
||||
unsigned int mp_fail_size;
|
||||
int mp_fail_size;
|
||||
|
||||
ret = true;
|
||||
if (mptcp_established_options_mp_fail(sk, &mp_fail_size,
|
||||
|
|
@ -883,7 +863,8 @@ int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
|||
|
||||
total_size += opt_size;
|
||||
remaining -= opt_size;
|
||||
if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, opts)) {
|
||||
if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining,
|
||||
has_ts, opts)) {
|
||||
total_size += opt_size;
|
||||
remaining -= opt_size;
|
||||
ret = true;
|
||||
|
|
@ -1202,7 +1183,6 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
|
|||
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
|
||||
} else {
|
||||
mptcp_pm_add_addr_echoed(msk, &mp_opt.addr);
|
||||
mptcp_pm_del_add_timer(msk, &mp_opt.addr, true);
|
||||
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
|
||||
}
|
||||
|
||||
|
|
|
|||
191
net/mptcp/pm.c
191
net/mptcp/pm.c
|
|
@ -12,12 +12,12 @@
|
|||
|
||||
#define ADD_ADDR_RETRANS_MAX 3
|
||||
|
||||
struct mptcp_pm_add_entry {
|
||||
struct mptcp_pm_add_addr {
|
||||
struct list_head list;
|
||||
struct mptcp_addr_info addr;
|
||||
u8 retrans_times;
|
||||
bool timer_done;
|
||||
struct timer_list add_timer;
|
||||
struct timer_list timer;
|
||||
struct mptcp_sock *sock;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
|
@ -115,14 +115,14 @@ static bool mptcp_pm_is_init_remote_addr(struct mptcp_sock *msk,
|
|||
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)
|
||||
bool mptcp_pm_has_subflow_saddr(const struct mptcp_sock *msk,
|
||||
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) {
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
|
||||
|
||||
mptcp_local_address(skc, &cur);
|
||||
|
|
@ -133,11 +133,11 @@ bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
|||
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)
|
||||
static struct mptcp_pm_add_addr *
|
||||
mptcp_pm_announced_lookup(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
struct mptcp_pm_add_addr *entry;
|
||||
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
|
|
@ -149,26 +149,60 @@ mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
static struct mptcp_pm_add_addr *
|
||||
mptcp_pm_announced_del_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 mptcp_pm_add_addr *entry;
|
||||
bool stop_timer = false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
entry = mptcp_pm_announced_lookup(msk, addr);
|
||||
if (entry && (!check_id || entry->addr.id == addr->id)) {
|
||||
entry->retrans_times = ADD_ADDR_RETRANS_MAX;
|
||||
stop_timer = true;
|
||||
}
|
||||
if (!check_id && entry)
|
||||
list_del(&entry->list);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
/* Note: entry might have been removed by another thread.
|
||||
* We hold rcu_read_lock() to ensure it is not freed under us.
|
||||
*/
|
||||
if (stop_timer) {
|
||||
if (check_id)
|
||||
sk_stop_timer(sk, &entry->timer);
|
||||
else
|
||||
sk_stop_timer_sync(sk, &entry->timer);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool mptcp_pm_announced_remove(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_addr *entry;
|
||||
bool ret;
|
||||
|
||||
entry = mptcp_pm_del_add_timer(msk, addr, false);
|
||||
entry = mptcp_pm_announced_del_timer(msk, addr, false);
|
||||
ret = entry;
|
||||
kfree_rcu(entry, rcu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk)
|
||||
bool mptcp_pm_announced_has_ssk(struct mptcp_sock *msk, const struct sock *ssk)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry;
|
||||
struct mptcp_pm_add_addr *entry;
|
||||
struct mptcp_addr_info saddr;
|
||||
bool ret = false;
|
||||
|
||||
mptcp_local_address((struct sock_common *)sk, &saddr);
|
||||
mptcp_local_address((struct sock_common *)ssk, &saddr);
|
||||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
||||
|
|
@ -226,6 +260,7 @@ static bool subflow_in_rm_list(const struct mptcp_subflow_context *subflow,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
|
||||
static void
|
||||
mptcp_pm_addr_send_ack_avoid_list(struct mptcp_sock *msk,
|
||||
const struct mptcp_rm_list *rm_list)
|
||||
|
|
@ -338,10 +373,10 @@ static unsigned int mptcp_adjust_add_addr_timeout(struct mptcp_sock *msk)
|
|||
return rto;
|
||||
}
|
||||
|
||||
static void mptcp_pm_add_timer(struct timer_list *timer)
|
||||
static void mptcp_pm_add_addr_timer(struct timer_list *timer)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry = timer_container_of(entry, timer,
|
||||
add_timer);
|
||||
struct mptcp_pm_add_addr *entry = timer_container_of(entry, timer,
|
||||
timer);
|
||||
struct mptcp_sock *msk = entry->sock;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
unsigned int timeout = 0;
|
||||
|
|
@ -364,7 +399,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
|
|||
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
/* The cancel path (mptcp_pm_del_add_timer()) can race with this
|
||||
/* The cancel path (mptcp_pm_announced_del_timer()) can race with this
|
||||
* callback. Once cancel updates retrans_times to MAX, suppress further
|
||||
* retransmissions here. If this callback acquires pm.lock first, one
|
||||
* final transmit attempt is still possible.
|
||||
|
|
@ -397,51 +432,16 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
|
|||
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;
|
||||
bool stop_timer = false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
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;
|
||||
stop_timer = true;
|
||||
}
|
||||
if (!check_id && entry)
|
||||
list_del(&entry->list);
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
/* Note: entry might have been removed by another thread.
|
||||
* We hold rcu_read_lock() to ensure it is not freed under us.
|
||||
*/
|
||||
if (stop_timer) {
|
||||
if (check_id)
|
||||
sk_stop_timer(sk, &entry->add_timer);
|
||||
else
|
||||
sk_stop_timer_sync(sk, &entry->add_timer);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
||||
bool mptcp_pm_announced_alloc(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_add_entry *add_entry = NULL;
|
||||
struct mptcp_pm_add_addr *add_entry = NULL;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
unsigned int timeout;
|
||||
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
||||
|
||||
add_entry = mptcp_pm_announced_lookup(msk, addr);
|
||||
if (add_entry) {
|
||||
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
||||
return false;
|
||||
|
|
@ -459,19 +459,19 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
|||
add_entry->sock = msk;
|
||||
add_entry->retrans_times = 0;
|
||||
|
||||
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
|
||||
timer_setup(&add_entry->timer, mptcp_pm_add_addr_timer, 0);
|
||||
reset_timer:
|
||||
add_entry->timer_done = false;
|
||||
timeout = mptcp_adjust_add_addr_timeout(msk);
|
||||
if (timeout)
|
||||
sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
|
||||
sk_reset_timer(sk, &add_entry->timer, jiffies + timeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
|
||||
static void mptcp_pm_free_announced_list(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_pm_add_entry *entry, *tmp;
|
||||
struct mptcp_pm_add_addr *entry, *tmp;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
LIST_HEAD(free_list);
|
||||
|
||||
|
|
@ -483,7 +483,7 @@ static void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
|
|||
|
||||
list_for_each_entry_safe(entry, tmp, &free_list, list) {
|
||||
if (!entry->timer_done)
|
||||
sk_stop_timer_sync(sk, &entry->add_timer);
|
||||
sk_stop_timer_sync(sk, &entry->timer);
|
||||
kfree_rcu(entry, rcu);
|
||||
}
|
||||
}
|
||||
|
|
@ -730,21 +730,25 @@ void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
|
|||
const struct mptcp_addr_info *addr)
|
||||
{
|
||||
struct mptcp_pm_data *pm = &msk->pm;
|
||||
struct mptcp_pm_add_addr *entry;
|
||||
|
||||
pr_debug("msk=%p\n", msk);
|
||||
|
||||
if (!READ_ONCE(pm->work_pending))
|
||||
entry = mptcp_pm_announced_del_timer(msk, addr, true);
|
||||
|
||||
if (!entry || !READ_ONCE(pm->work_pending))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&pm->lock);
|
||||
|
||||
if (mptcp_lookup_anno_list_by_saddr(msk, addr) && READ_ONCE(pm->work_pending))
|
||||
if (READ_ONCE(pm->work_pending))
|
||||
mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
|
||||
|
||||
spin_unlock_bh(&pm->lock);
|
||||
}
|
||||
|
||||
void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
|
||||
/* To be called while pm->lock is held */
|
||||
static void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk)
|
||||
{
|
||||
if (!mptcp_pm_should_add_signal(msk))
|
||||
return;
|
||||
|
|
@ -887,13 +891,29 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq)
|
|||
}
|
||||
}
|
||||
|
||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_addr_info *addr, bool *echo)
|
||||
static int mptcp_add_addr_len(int family, bool echo, bool port)
|
||||
{
|
||||
int len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
|
||||
|
||||
if (family == AF_INET6)
|
||||
len = TCPOLEN_MPTCP_ADD_ADDR6_BASE;
|
||||
if (!echo)
|
||||
len += MPTCPOPT_THMAC_LEN;
|
||||
/* account for 2 trailing 'nop' options */
|
||||
if (port)
|
||||
len += TCPOLEN_MPTCP_PORT_LEN + TCPOLEN_MPTCP_PORT_ALIGN;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining,
|
||||
struct mptcp_addr_info *addr, bool *echo,
|
||||
bool *drop_ts)
|
||||
{
|
||||
bool skip_add_addr = false;
|
||||
int ret = false;
|
||||
bool ret = false;
|
||||
u8 add_addr;
|
||||
int len = 0;
|
||||
u8 family;
|
||||
bool port;
|
||||
|
||||
|
|
@ -907,7 +927,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
|||
* plain dup-ack from TCP perspective. The other MPTCP-relevant info,
|
||||
* if any, will be carried by the 'original' TCP ack
|
||||
*/
|
||||
remaining += opt_size;
|
||||
len -= *size;
|
||||
|
||||
*echo = mptcp_pm_should_add_signal_echo(msk);
|
||||
if (*echo) {
|
||||
|
|
@ -922,9 +942,17 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
|||
family = msk->pm.local.family;
|
||||
}
|
||||
|
||||
if (remaining < mptcp_add_addr_len(family, *echo, port)) {
|
||||
len += mptcp_add_addr_len(family, *echo, port);
|
||||
if (len > remaining) {
|
||||
struct net *net = sock_net((struct sock *)msk);
|
||||
|
||||
if (*drop_ts && mptcp_add_addr_v6_port_drop_ts(net)) {
|
||||
/* OK without TCP Timestamps? */
|
||||
len -= TCPOLEN_TSTAMP_ALIGNED;
|
||||
if (len <= remaining)
|
||||
goto enough_space;
|
||||
}
|
||||
|
||||
if (*echo) {
|
||||
MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP);
|
||||
} else {
|
||||
|
|
@ -934,7 +962,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
|||
goto drop_signal_mark;
|
||||
}
|
||||
|
||||
*drop_ts = false;
|
||||
|
||||
enough_space:
|
||||
ret = true;
|
||||
*size = len;
|
||||
|
||||
drop_signal_mark:
|
||||
WRITE_ONCE(msk->pm.addr_signal, add_addr);
|
||||
|
|
@ -947,14 +979,22 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
|||
* let the PM state machine progress.
|
||||
*/
|
||||
if (skip_add_addr) {
|
||||
mptcp_pm_del_add_timer(msk, addr, true);
|
||||
mptcp_pm_announced_del_timer(msk, addr, true);
|
||||
mptcp_pm_subflow_established(msk);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mptcp_rm_addr_len(const struct mptcp_rm_list *rm_list)
|
||||
{
|
||||
if (rm_list->nr == 0 || rm_list->nr > MPTCP_RM_IDS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return TCPOLEN_MPTCP_RM_ADDR_BASE + roundup(rm_list->nr - 1, 4) + 1;
|
||||
}
|
||||
|
||||
bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
||||
struct mptcp_rm_list *rm_list)
|
||||
struct mptcp_rm_list *rm_list, int *size)
|
||||
{
|
||||
int ret = false, len;
|
||||
u8 rm_addr;
|
||||
|
|
@ -974,6 +1014,7 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
|||
if (remaining < len)
|
||||
goto out_unlock;
|
||||
|
||||
*size = len;
|
||||
*rm_list = msk->pm.rm_list_tx;
|
||||
WRITE_ONCE(msk->pm.addr_signal, rm_addr);
|
||||
ret = true;
|
||||
|
|
@ -1102,7 +1143,7 @@ void mptcp_pm_worker(struct mptcp_sock *msk)
|
|||
|
||||
void mptcp_pm_destroy(struct mptcp_sock *msk)
|
||||
{
|
||||
mptcp_pm_free_anno_list(msk);
|
||||
mptcp_pm_free_announced_list(msk);
|
||||
|
||||
if (mptcp_pm_is_userspace(msk))
|
||||
mptcp_userspace_pm_free_local_addr_list(msk);
|
||||
|
|
|
|||
|
|
@ -96,13 +96,13 @@ u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mptcp_pm_get_limit_extra_subflows);
|
||||
|
||||
static bool lookup_subflow_by_daddr(const struct list_head *list,
|
||||
const struct mptcp_addr_info *daddr)
|
||||
static bool has_subflow_daddr(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *daddr)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_addr_info cur;
|
||||
|
||||
list_for_each_entry(subflow, list, node) {
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
|
||||
if (!((1 << inet_sk_state_load(ssk)) &
|
||||
|
|
@ -374,7 +374,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
|||
/* If the alloc fails, we are on memory pressure, not worth
|
||||
* continuing, and trying to create subflows.
|
||||
*/
|
||||
if (!mptcp_pm_alloc_anno_list(msk, &local.addr))
|
||||
if (!mptcp_pm_announced_alloc(msk, &local.addr))
|
||||
return;
|
||||
|
||||
__clear_bit(endp_id, msk->pm.id_avail_bitmap);
|
||||
|
|
@ -673,7 +673,7 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
|
|||
mptcp_pm_addr_send_ack(msk);
|
||||
mptcp_mpc_endpoint_setup(msk);
|
||||
|
||||
if (lookup_subflow_by_daddr(&msk->conn_list, &remote))
|
||||
if (has_subflow_daddr(msk, &remote))
|
||||
return;
|
||||
|
||||
/* pick id 0 port, if none is provided the remote address */
|
||||
|
|
@ -1053,7 +1053,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
|
||||
static void mptcp_pm_remove_announced(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr,
|
||||
bool force)
|
||||
{
|
||||
|
|
@ -1062,7 +1062,7 @@ static void mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
|
|||
|
||||
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
|
||||
|
||||
announced = mptcp_remove_anno_list_by_saddr(msk, addr);
|
||||
announced = mptcp_pm_announced_remove(msk, addr);
|
||||
if (announced || force) {
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
if (announced)
|
||||
|
|
@ -1098,8 +1098,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
|
|||
goto next;
|
||||
|
||||
lock_sock(sk);
|
||||
remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, addr);
|
||||
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
|
||||
remove_subflow = mptcp_pm_has_subflow_saddr(msk, addr);
|
||||
mptcp_pm_remove_announced(msk, addr, remove_subflow &&
|
||||
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
|
||||
|
||||
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
|
||||
|
|
@ -1236,10 +1236,10 @@ static void mptcp_pm_flush_addrs_and_subflows(struct mptcp_sock *msk,
|
|||
|
||||
entry = list_prepare_entry(entry, rm_list, list);
|
||||
list_for_each_entry_continue(entry, rm_list, list) {
|
||||
if (mptcp_lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
|
||||
if (mptcp_pm_has_subflow_saddr(msk, &entry->addr))
|
||||
slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
|
||||
|
||||
if (mptcp_remove_anno_list_by_saddr(msk, &entry->addr))
|
||||
if (mptcp_pm_announced_remove(msk, &entry->addr))
|
||||
alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
|
||||
|
||||
if (slist.nr == MPTCP_RM_IDS_MAX ||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
lock_sock(sk);
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) {
|
||||
if (mptcp_pm_announced_alloc(msk, &addr_val.addr)) {
|
||||
msk->pm.add_addr_signaled++;
|
||||
mptcp_pm_announce_addr(msk, &addr_val.addr, false);
|
||||
mptcp_pm_addr_send_ack(msk);
|
||||
|
|
@ -281,9 +281,9 @@ void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
|
|||
int anno_nr = 0;
|
||||
|
||||
/* only delete if either announced or matching a subflow */
|
||||
if (mptcp_remove_anno_list_by_saddr(msk, &entry->addr))
|
||||
if (mptcp_pm_announced_remove(msk, &entry->addr))
|
||||
anno_nr++;
|
||||
else if (!mptcp_lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
|
||||
else if (!mptcp_pm_has_subflow_saddr(msk, &entry->addr))
|
||||
return;
|
||||
|
||||
alist.ids[alist.nr++] = entry->addr.id;
|
||||
|
|
|
|||
|
|
@ -798,6 +798,7 @@ unsigned int mptcp_close_timeout(const struct sock *sk);
|
|||
int mptcp_get_pm_type(const struct net *net);
|
||||
const char *mptcp_get_path_manager(const struct net *net);
|
||||
const char *mptcp_get_scheduler(const struct net *net);
|
||||
unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net);
|
||||
|
||||
void mptcp_active_disable(struct sock *sk);
|
||||
bool mptcp_active_should_disable(struct sock *ssk);
|
||||
|
|
@ -1113,7 +1114,6 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
|
|||
const struct mptcp_addr_info *addr);
|
||||
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);
|
||||
void mptcp_pm_send_ack(struct mptcp_sock *msk,
|
||||
struct mptcp_subflow_context *subflow,
|
||||
bool prio, bool backup);
|
||||
|
|
@ -1129,16 +1129,13 @@ 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,
|
||||
bool mptcp_pm_announced_alloc(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
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);
|
||||
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,
|
||||
const struct mptcp_addr_info *addr);
|
||||
bool mptcp_pm_announced_remove(struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *addr);
|
||||
bool mptcp_pm_announced_has_ssk(struct mptcp_sock *msk, const struct sock *ssk);
|
||||
bool mptcp_pm_has_subflow_saddr(const struct mptcp_sock *msk,
|
||||
const struct mptcp_addr_info *saddr);
|
||||
int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
struct genl_info *info);
|
||||
int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_entry *local,
|
||||
|
|
@ -1206,34 +1203,11 @@ static inline bool mptcp_pm_is_kernel(const struct mptcp_sock *msk)
|
|||
return READ_ONCE(msk->pm.pm_type) == MPTCP_PM_TYPE_KERNEL;
|
||||
}
|
||||
|
||||
static inline unsigned int mptcp_add_addr_len(int family, bool echo, bool port)
|
||||
{
|
||||
u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
|
||||
|
||||
if (family == AF_INET6)
|
||||
len = TCPOLEN_MPTCP_ADD_ADDR6_BASE;
|
||||
if (!echo)
|
||||
len += MPTCPOPT_THMAC_LEN;
|
||||
/* account for 2 trailing 'nop' options */
|
||||
if (port)
|
||||
len += TCPOLEN_MPTCP_PORT_LEN + TCPOLEN_MPTCP_PORT_ALIGN;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline int mptcp_rm_addr_len(const struct mptcp_rm_list *rm_list)
|
||||
{
|
||||
if (rm_list->nr == 0 || rm_list->nr > MPTCP_RM_IDS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return TCPOLEN_MPTCP_RM_ADDR_BASE + roundup(rm_list->nr - 1, 4) + 1;
|
||||
}
|
||||
|
||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
||||
unsigned int remaining,
|
||||
struct mptcp_addr_info *addr, bool *echo);
|
||||
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining,
|
||||
struct mptcp_addr_info *addr, bool *echo,
|
||||
bool *drop_ts);
|
||||
bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
||||
struct mptcp_rm_list *rm_list);
|
||||
struct mptcp_rm_list *rm_list, int *len);
|
||||
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_pm_addr_entry *skc);
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ static int subflow_check_req(struct request_sock *req,
|
|||
pr_debug("syn inet_sport=%d %d\n",
|
||||
ntohs(inet_sk(sk_listener)->inet_sport),
|
||||
ntohs(inet_sk((struct sock *)subflow_req->msk)->inet_sport));
|
||||
if (!mptcp_pm_sport_in_anno_list(subflow_req->msk, sk_listener)) {
|
||||
if (!mptcp_pm_announced_has_ssk(subflow_req->msk, sk_listener)) {
|
||||
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTSYNRX);
|
||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||
return -EPERM;
|
||||
|
|
@ -926,7 +926,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
|
|||
pr_debug("ack inet_sport=%d %d\n",
|
||||
ntohs(inet_sk(sk)->inet_sport),
|
||||
ntohs(inet_sk((struct sock *)owner)->inet_sport));
|
||||
if (!mptcp_pm_sport_in_anno_list(owner, sk)) {
|
||||
if (!mptcp_pm_announced_has_ssk(owner, sk)) {
|
||||
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTACKRX);
|
||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||
goto dispose_child;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,10 @@ unset fb_mpc_data
|
|||
unset fb_md5_sig
|
||||
unset fb_dss
|
||||
|
||||
unset add_addr_tx_nr
|
||||
unset add_addr_echo_tx_nr
|
||||
unset add_addr_drop_tx_nr
|
||||
|
||||
# generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x30) ||
|
||||
# (ip6 && (ip6[74] & 0xf0) == 0x30)'"
|
||||
CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
|
||||
|
|
@ -1710,6 +1714,9 @@ chk_add_nr()
|
|||
local ack_nr=$port_nr
|
||||
local mis_syn_nr=0
|
||||
local mis_ack_nr=0
|
||||
local add_tx_nr=${add_addr_tx_nr:-${add_nr}}
|
||||
local echo_tx_nr=${add_addr_echo_tx_nr:-${echo_nr}}
|
||||
local drop_tx_nr=${add_addr_drop_tx_nr:-0}
|
||||
local ns_tx=$ns1
|
||||
local ns_rx=$ns2
|
||||
local tx=""
|
||||
|
|
@ -1811,50 +1818,25 @@ chk_add_nr()
|
|||
print_ok
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
chk_add_tx_nr()
|
||||
{
|
||||
local add_tx_nr=$1
|
||||
local echo_tx_nr=$2
|
||||
local count
|
||||
|
||||
print_check "add addr tx"
|
||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtAddAddrTx")
|
||||
if [ -z "$count" ]; then
|
||||
print_skip
|
||||
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtAddAddrTx")
|
||||
# Tolerate more ADD_ADDR then expected (if any), due to retransmissions
|
||||
elif [ "$count" != "$add_tx_nr" ] &&
|
||||
{ [ "$add_tx_nr" -eq 0 ] || [ "$count" -lt "$add_tx_nr" ]; }; then
|
||||
if [ -n "$count" ] && [ "$count" != "$add_tx_nr" ] &&
|
||||
{ [ "$add_tx_nr" -eq 0 ] || [ "$count" -lt "$add_tx_nr" ]; }; then
|
||||
print_check "add addr tx"
|
||||
fail_test "got $count ADD_ADDR[s] TX, expected $add_tx_nr"
|
||||
else
|
||||
print_ok
|
||||
fi
|
||||
|
||||
print_check "add addr echo tx"
|
||||
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtEchoAddTx")
|
||||
if [ -z "$count" ]; then
|
||||
print_skip
|
||||
elif [ "$count" != "$echo_tx_nr" ]; then
|
||||
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtEchoAddTx")
|
||||
if [ -n "$count" ] && [ "$count" != "$echo_tx_nr" ]; then
|
||||
print_check "add addr echo tx"
|
||||
fail_test "got $count ADD_ADDR echo[s] TX, expected $echo_tx_nr"
|
||||
else
|
||||
print_ok
|
||||
fi
|
||||
}
|
||||
|
||||
chk_add_drop_tx_nr()
|
||||
{
|
||||
local drop_tx_nr=$1
|
||||
local count
|
||||
|
||||
print_check "add addr tx drop"
|
||||
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtAddAddrTxDrop")
|
||||
if [ -z "$count" ]; then
|
||||
print_skip
|
||||
elif [ "$count" != "$drop_tx_nr" ]; then
|
||||
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtAddAddrTxDrop")
|
||||
if [ -n "$count" ] && [ "$count" != "$drop_tx_nr" ]; then
|
||||
print_check "add addr tx drop"
|
||||
fail_test "got $count ADD_ADDR drop[s] TX, expected $drop_tx_nr"
|
||||
else
|
||||
print_ok
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -2267,7 +2249,6 @@ signal_address_tests()
|
|||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 0 0 0
|
||||
chk_add_tx_nr 1 1
|
||||
chk_add_nr 1 1
|
||||
fi
|
||||
|
||||
|
|
@ -2545,8 +2526,8 @@ add_addr_timeout_tests()
|
|||
speed=slow \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 1 1 1
|
||||
chk_add_tx_nr 4 4
|
||||
chk_add_nr 4 0
|
||||
add_addr_echo_tx_nr=4 \
|
||||
chk_add_nr 4 0
|
||||
fi
|
||||
|
||||
# add_addr timeout IPv6
|
||||
|
|
@ -2557,7 +2538,8 @@ add_addr_timeout_tests()
|
|||
speed=slow \
|
||||
run_tests $ns1 $ns2 dead:beef:1::1
|
||||
chk_join_nr 1 1 1
|
||||
chk_add_nr 4 0
|
||||
add_addr_echo_tx_nr=4 \
|
||||
chk_add_nr 4 0
|
||||
fi
|
||||
|
||||
# signal addresses timeout
|
||||
|
|
@ -2569,7 +2551,8 @@ add_addr_timeout_tests()
|
|||
speed=10 \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 2 2 2
|
||||
chk_add_nr 8 0
|
||||
add_addr_echo_tx_nr=8 \
|
||||
chk_add_nr 8 0
|
||||
fi
|
||||
|
||||
# signal invalid addresses timeout
|
||||
|
|
@ -2582,7 +2565,8 @@ add_addr_timeout_tests()
|
|||
run_tests $ns1 $ns2 10.0.1.1
|
||||
join_syn_tx=2 \
|
||||
chk_join_nr 1 1 1
|
||||
chk_add_nr 8 0
|
||||
add_addr_echo_tx_nr=7 \
|
||||
chk_add_nr 8 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -3214,6 +3198,17 @@ add_addr_ports_tests()
|
|||
chk_add_nr 1 1 1
|
||||
fi
|
||||
|
||||
# signal address v6 with port
|
||||
if reset "signal address v6 with port" &&
|
||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/add_addr_v6_port_drop_ts'; then
|
||||
pm_nl_set_limits $ns1 0 1
|
||||
pm_nl_set_limits $ns2 1 1
|
||||
pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal port 10100
|
||||
run_tests $ns1 $ns2 dead:beef:1::1
|
||||
chk_join_nr 1 1 1
|
||||
chk_add_nr 1 1 1
|
||||
fi
|
||||
|
||||
# subflow and signal with port
|
||||
if reset "subflow and signal with port"; then
|
||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
|
||||
|
|
@ -3313,15 +3308,15 @@ add_addr_ports_tests()
|
|||
if reset "signal addr list progresses after tx drop"; then
|
||||
pm_nl_set_limits $ns1 0 2
|
||||
pm_nl_set_limits $ns2 1 0
|
||||
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_v6_port_drop_ts=0 2>/dev/null || true
|
||||
ip netns exec $ns1 sysctl -q net.ipv4.tcp_timestamps=1
|
||||
ip netns exec $ns2 sysctl -q net.ipv4.tcp_timestamps=1
|
||||
|
||||
pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal port 10100
|
||||
pm_nl_add_endpoint $ns1 dead:beef:3::1 flags signal
|
||||
run_tests $ns1 $ns2 dead:beef:1::1
|
||||
chk_add_drop_tx_nr 1
|
||||
chk_add_tx_nr 1 1
|
||||
chk_add_nr 1 1 0
|
||||
add_addr_drop_tx_nr=1 \
|
||||
chk_add_nr 1 1 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user