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
11 files changed
+248
-228
No files matched your search
@@ -21,6 +21,19 @@ add_addr_timeout - INTEGER (seconds)
|
|||||||
|
|
||||||
Default: 120
|
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_join_initial_addr_port - BOOLEAN
|
||||||
Allow peers to send join requests to the IP address and port number used
|
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
|
by the initial subflow if the value is 1. This controls a flag that is
|
||||||
|
|||||||
+3
-10
@@ -72,7 +72,8 @@ struct mptcp_out_options {
|
|||||||
u8 reset_reason:4,
|
u8 reset_reason:4,
|
||||||
reset_transient:1,
|
reset_transient:1,
|
||||||
csum_reqd:1,
|
csum_reqd:1,
|
||||||
allow_join_id0:1;
|
allow_join_id0:1,
|
||||||
|
drop_ts:1;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
u64 sndr_key;
|
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,
|
bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
|
||||||
struct mptcp_out_options *opts);
|
struct mptcp_out_options *opts);
|
||||||
int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
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_out_options *opts);
|
||||||
bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb);
|
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;
|
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,
|
static inline bool mptcp_incoming_options(struct sock *sk,
|
||||||
struct sk_buff *skb)
|
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;
|
size += TCPOLEN_TSTAMP_ALIGNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_MPTCP)
|
||||||
/* MPTCP options have precedence over SACK for the limited TCP
|
/* MPTCP options have precedence over SACK for the limited TCP
|
||||||
* option space because a MPTCP connection would be forced to
|
* option space because a MPTCP connection would be forced to
|
||||||
* fall back to regular TCP if a required multipath option is
|
* 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)) {
|
if (sk_is_mptcp(sk)) {
|
||||||
unsigned int remaining = MAX_TCP_OPTION_SPACE - size;
|
unsigned int remaining = MAX_TCP_OPTION_SPACE - size;
|
||||||
|
bool has_ts = opts->options & OPTION_TS;
|
||||||
int opt_size;
|
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);
|
&opts->mptcp);
|
||||||
if (opt_size >= 0) {
|
if (opt_size >= 0) {
|
||||||
opts->options |= OPTION_MPTCP;
|
opts->options |= OPTION_MPTCP;
|
||||||
size += opt_size;
|
size += opt_size;
|
||||||
|
|
||||||
|
if (opts->mptcp.drop_ts)
|
||||||
|
opts->options &= ~OPTION_TS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack;
|
eff_sacks = tp->rx_opt.num_sacks + tp->rx_opt.dsack;
|
||||||
if (unlikely(eff_sacks)) {
|
if (unlikely(eff_sacks)) {
|
||||||
|
|||||||
+17
-1
@@ -32,12 +32,13 @@ struct mptcp_pernet {
|
|||||||
unsigned int close_timeout;
|
unsigned int close_timeout;
|
||||||
unsigned int stale_loss_cnt;
|
unsigned int stale_loss_cnt;
|
||||||
atomic_t active_disable_times;
|
atomic_t active_disable_times;
|
||||||
u8 syn_retrans_before_tcp_fallback;
|
|
||||||
unsigned long active_disable_stamp;
|
unsigned long active_disable_stamp;
|
||||||
|
u8 syn_retrans_before_tcp_fallback;
|
||||||
u8 mptcp_enabled;
|
u8 mptcp_enabled;
|
||||||
u8 checksum_enabled;
|
u8 checksum_enabled;
|
||||||
u8 allow_join_initial_addr_port;
|
u8 allow_join_initial_addr_port;
|
||||||
u8 pm_type;
|
u8 pm_type;
|
||||||
|
u8 add_addr_v6_port_drop_ts;
|
||||||
char scheduler[MPTCP_SCHED_NAME_MAX];
|
char scheduler[MPTCP_SCHED_NAME_MAX];
|
||||||
char path_manager[MPTCP_PM_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;
|
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)
|
static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
||||||
{
|
{
|
||||||
pernet->mptcp_enabled = 1;
|
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;
|
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
|
||||||
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
|
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
|
||||||
strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager));
|
strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager));
|
||||||
|
pernet->add_addr_v6_port_drop_ts = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
@@ -362,6 +369,14 @@ static struct ctl_table mptcp_sysctl_table[] = {
|
|||||||
.mode = 0444,
|
.mode = 0444,
|
||||||
.proc_handler = proc_available_path_managers,
|
.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)
|
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[10].data = &pernet->syn_retrans_before_tcp_fallback;
|
||||||
table[11].data = &pernet->path_manager;
|
table[11].data = &pernet->path_manager;
|
||||||
/* table[12] is for available_path_managers which is read-only info */
|
/* 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,
|
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
|
||||||
ARRAY_SIZE(mptcp_sysctl_table));
|
ARRAY_SIZE(mptcp_sysctl_table));
|
||||||
|
|||||||
+24
-44
@@ -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,
|
static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
|
||||||
bool snd_data_fin_enable,
|
bool snd_data_fin_enable, int *size,
|
||||||
unsigned int *size,
|
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
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,
|
static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
||||||
bool snd_data_fin_enable,
|
bool snd_data_fin_enable, int *size,
|
||||||
unsigned int *size,
|
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
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)]);
|
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb,
|
static bool mptcp_established_options_add_addr(struct sock *sk,
|
||||||
unsigned int *size,
|
struct sk_buff *skb, int *size,
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
|
bool has_ts,
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||||
unsigned int opt_size = *size;
|
|
||||||
struct mptcp_addr_info addr;
|
struct mptcp_addr_info addr;
|
||||||
|
bool drop_ts = has_ts;
|
||||||
bool echo;
|
bool echo;
|
||||||
int len;
|
|
||||||
|
|
||||||
/* add addr will strip the existing options, be sure to avoid breaking
|
/* add addr will strip the existing options, be sure to avoid breaking
|
||||||
* MPC/MPJ handshakes
|
* 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) ||
|
if (!mptcp_pm_should_add_signal(msk) ||
|
||||||
(opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) ||
|
(opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) ||
|
||||||
!skb || !skb_is_tcp_pure_ack(skb) ||
|
!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;
|
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");
|
pr_debug("drop other suboptions\n");
|
||||||
opts->suboptions = 0;
|
opts->suboptions = OPTION_MPTCP_ADD_ADDR;
|
||||||
*size -= opt_size;
|
opts->drop_ts = drop_ts;
|
||||||
opts->addr = addr;
|
opts->addr = addr;
|
||||||
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
|
|
||||||
if (!echo) {
|
if (!echo) {
|
||||||
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX);
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX);
|
||||||
opts->ahmac = add_addr_generate_hmac(READ_ONCE(msk->local_key),
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mptcp_established_options_rm_addr(struct sock *sk,
|
static bool mptcp_established_options_rm_addr(struct sock *sk, int *size,
|
||||||
unsigned int *size,
|
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||||
struct mptcp_rm_list rm_list;
|
struct mptcp_rm_list rm_list;
|
||||||
int i, len;
|
int i;
|
||||||
|
|
||||||
if (!mptcp_pm_should_rm_signal(msk) ||
|
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;
|
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->suboptions |= OPTION_MPTCP_RM_ADDR;
|
||||||
opts->rm_list = rm_list;
|
opts->rm_list = rm_list;
|
||||||
|
|
||||||
@@ -736,8 +719,7 @@ static bool mptcp_established_options_rm_addr(struct sock *sk,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mptcp_established_options_mp_prio(struct sock *sk,
|
static bool mptcp_established_options_mp_prio(struct sock *sk, int *size,
|
||||||
unsigned int *size,
|
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
@@ -762,8 +744,8 @@ static bool mptcp_established_options_mp_prio(struct sock *sk,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb,
|
static noinline bool mptcp_established_options_rst(struct sock *sk,
|
||||||
unsigned int *size,
|
int *size,
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
@@ -781,8 +763,7 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mptcp_established_options_fastclose(struct sock *sk,
|
static bool mptcp_established_options_fastclose(struct sock *sk, int *size,
|
||||||
unsigned int *size,
|
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
struct mptcp_out_options *opts)
|
struct mptcp_out_options *opts)
|
||||||
{
|
{
|
||||||
@@ -804,8 +785,7 @@ static bool mptcp_established_options_fastclose(struct sock *sk,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mptcp_established_options_mp_fail(struct sock *sk,
|
static bool mptcp_established_options_mp_fail(struct sock *sk, int *size,
|
||||||
unsigned int *size,
|
|
||||||
unsigned int remaining,
|
unsigned int remaining,
|
||||||
struct mptcp_out_options *opts)
|
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,
|
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_out_options *opts)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||||
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
||||||
unsigned int opt_size = 0;
|
|
||||||
int total_size = 0;
|
int total_size = 0;
|
||||||
bool snd_data_fin;
|
bool snd_data_fin;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
int opt_size = 0;
|
||||||
|
|
||||||
opts->suboptions = 0;
|
opts->suboptions = 0;
|
||||||
|
|
||||||
@@ -853,7 +833,7 @@ int mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
|||||||
remaining -= opt_size;
|
remaining -= opt_size;
|
||||||
}
|
}
|
||||||
/* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */
|
/* 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;
|
total_size += opt_size;
|
||||||
remaining -= 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))
|
if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, opts))
|
||||||
ret = true;
|
ret = true;
|
||||||
else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, opts)) {
|
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;
|
ret = true;
|
||||||
if (mptcp_established_options_mp_fail(sk, &mp_fail_size,
|
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;
|
total_size += opt_size;
|
||||||
remaining -= 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;
|
total_size += opt_size;
|
||||||
remaining -= opt_size;
|
remaining -= opt_size;
|
||||||
ret = true;
|
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);
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
|
||||||
} else {
|
} else {
|
||||||
mptcp_pm_add_addr_echoed(msk, &mp_opt.addr);
|
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);
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+116
-75
@@ -12,12 +12,12 @@
|
|||||||
|
|
||||||
#define ADD_ADDR_RETRANS_MAX 3
|
#define ADD_ADDR_RETRANS_MAX 3
|
||||||
|
|
||||||
struct mptcp_pm_add_entry {
|
struct mptcp_pm_add_addr {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct mptcp_addr_info addr;
|
struct mptcp_addr_info addr;
|
||||||
u8 retrans_times;
|
u8 retrans_times;
|
||||||
bool timer_done;
|
bool timer_done;
|
||||||
struct timer_list add_timer;
|
struct timer_list timer;
|
||||||
struct mptcp_sock *sock;
|
struct mptcp_sock *sock;
|
||||||
struct rcu_head rcu;
|
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);
|
return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
bool mptcp_pm_has_subflow_saddr(const struct mptcp_sock *msk,
|
||||||
const struct mptcp_addr_info *saddr)
|
const struct mptcp_addr_info *saddr)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow;
|
struct mptcp_subflow_context *subflow;
|
||||||
struct mptcp_addr_info cur;
|
struct mptcp_addr_info cur;
|
||||||
struct sock_common *skc;
|
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);
|
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
|
||||||
|
|
||||||
mptcp_local_address(skc, &cur);
|
mptcp_local_address(skc, &cur);
|
||||||
@@ -133,11 +133,11 @@ bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mptcp_pm_add_entry *
|
static struct mptcp_pm_add_addr *
|
||||||
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
mptcp_pm_announced_lookup(const struct mptcp_sock *msk,
|
||||||
const struct mptcp_addr_info *addr)
|
const struct mptcp_addr_info *addr)
|
||||||
{
|
{
|
||||||
struct mptcp_pm_add_entry *entry;
|
struct mptcp_pm_add_addr *entry;
|
||||||
|
|
||||||
lockdep_assert_held(&msk->pm.lock);
|
lockdep_assert_held(&msk->pm.lock);
|
||||||
|
|
||||||
@@ -149,26 +149,60 @@ mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
static struct mptcp_pm_add_addr *
|
||||||
const struct mptcp_addr_info *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;
|
bool ret;
|
||||||
|
|
||||||
entry = mptcp_pm_del_add_timer(msk, addr, false);
|
entry = mptcp_pm_announced_del_timer(msk, addr, false);
|
||||||
ret = entry;
|
ret = entry;
|
||||||
kfree_rcu(entry, rcu);
|
kfree_rcu(entry, rcu);
|
||||||
|
|
||||||
return ret;
|
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;
|
struct mptcp_addr_info saddr;
|
||||||
bool ret = false;
|
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);
|
spin_lock_bh(&msk->pm.lock);
|
||||||
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
|
||||||
static void
|
static void
|
||||||
mptcp_pm_addr_send_ack_avoid_list(struct mptcp_sock *msk,
|
mptcp_pm_addr_send_ack_avoid_list(struct mptcp_sock *msk,
|
||||||
const struct mptcp_rm_list *rm_list)
|
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;
|
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,
|
struct mptcp_pm_add_addr *entry = timer_container_of(entry, timer,
|
||||||
add_timer);
|
timer);
|
||||||
struct mptcp_sock *msk = entry->sock;
|
struct mptcp_sock *msk = entry->sock;
|
||||||
struct sock *sk = (struct sock *)msk;
|
struct sock *sk = (struct sock *)msk;
|
||||||
unsigned int timeout = 0;
|
unsigned int timeout = 0;
|
||||||
@@ -364,7 +399,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
|
|||||||
|
|
||||||
spin_lock_bh(&msk->pm.lock);
|
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
|
* callback. Once cancel updates retrans_times to MAX, suppress further
|
||||||
* retransmissions here. If this callback acquires pm.lock first, one
|
* retransmissions here. If this callback acquires pm.lock first, one
|
||||||
* final transmit attempt is still possible.
|
* final transmit attempt is still possible.
|
||||||
@@ -397,51 +432,16 @@ out:
|
|||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mptcp_pm_add_entry *
|
bool mptcp_pm_announced_alloc(struct mptcp_sock *msk,
|
||||||
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,
|
|
||||||
const struct mptcp_addr_info *addr)
|
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;
|
struct sock *sk = (struct sock *)msk;
|
||||||
unsigned int timeout;
|
unsigned int timeout;
|
||||||
|
|
||||||
lockdep_assert_held(&msk->pm.lock);
|
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 (add_entry) {
|
||||||
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
||||||
return false;
|
return false;
|
||||||
@@ -459,19 +459,19 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
|||||||
add_entry->sock = msk;
|
add_entry->sock = msk;
|
||||||
add_entry->retrans_times = 0;
|
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:
|
reset_timer:
|
||||||
add_entry->timer_done = false;
|
add_entry->timer_done = false;
|
||||||
timeout = mptcp_adjust_add_addr_timeout(msk);
|
timeout = mptcp_adjust_add_addr_timeout(msk);
|
||||||
if (timeout)
|
if (timeout)
|
||||||
sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
|
sk_reset_timer(sk, &add_entry->timer, jiffies + timeout);
|
||||||
|
|
||||||
return true;
|
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;
|
struct sock *sk = (struct sock *)msk;
|
||||||
LIST_HEAD(free_list);
|
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) {
|
list_for_each_entry_safe(entry, tmp, &free_list, list) {
|
||||||
if (!entry->timer_done)
|
if (!entry->timer_done)
|
||||||
sk_stop_timer_sync(sk, &entry->add_timer);
|
sk_stop_timer_sync(sk, &entry->timer);
|
||||||
kfree_rcu(entry, rcu);
|
kfree_rcu(entry, rcu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -730,21 +730,25 @@ void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
|
|||||||
const struct mptcp_addr_info *addr)
|
const struct mptcp_addr_info *addr)
|
||||||
{
|
{
|
||||||
struct mptcp_pm_data *pm = &msk->pm;
|
struct mptcp_pm_data *pm = &msk->pm;
|
||||||
|
struct mptcp_pm_add_addr *entry;
|
||||||
|
|
||||||
pr_debug("msk=%p\n", msk);
|
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;
|
return;
|
||||||
|
|
||||||
spin_lock_bh(&pm->lock);
|
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);
|
mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
|
||||||
|
|
||||||
spin_unlock_bh(&pm->lock);
|
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))
|
if (!mptcp_pm_should_add_signal(msk))
|
||||||
return;
|
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,
|
static int mptcp_add_addr_len(int family, bool echo, bool port)
|
||||||
unsigned int remaining,
|
{
|
||||||
struct mptcp_addr_info *addr, bool *echo)
|
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;
|
bool skip_add_addr = false;
|
||||||
int ret = false;
|
bool ret = false;
|
||||||
u8 add_addr;
|
u8 add_addr;
|
||||||
|
int len = 0;
|
||||||
u8 family;
|
u8 family;
|
||||||
bool port;
|
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,
|
* plain dup-ack from TCP perspective. The other MPTCP-relevant info,
|
||||||
* if any, will be carried by the 'original' TCP ack
|
* if any, will be carried by the 'original' TCP ack
|
||||||
*/
|
*/
|
||||||
remaining += opt_size;
|
len -= *size;
|
||||||
|
|
||||||
*echo = mptcp_pm_should_add_signal_echo(msk);
|
*echo = mptcp_pm_should_add_signal_echo(msk);
|
||||||
if (*echo) {
|
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;
|
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);
|
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) {
|
if (*echo) {
|
||||||
MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP);
|
MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP);
|
||||||
} else {
|
} else {
|
||||||
@@ -934,7 +962,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
|
|||||||
goto drop_signal_mark;
|
goto drop_signal_mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*drop_ts = false;
|
||||||
|
|
||||||
|
enough_space:
|
||||||
ret = true;
|
ret = true;
|
||||||
|
*size = len;
|
||||||
|
|
||||||
drop_signal_mark:
|
drop_signal_mark:
|
||||||
WRITE_ONCE(msk->pm.addr_signal, add_addr);
|
WRITE_ONCE(msk->pm.addr_signal, add_addr);
|
||||||
@@ -947,14 +979,22 @@ out_unlock:
|
|||||||
* let the PM state machine progress.
|
* let the PM state machine progress.
|
||||||
*/
|
*/
|
||||||
if (skip_add_addr) {
|
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);
|
mptcp_pm_subflow_established(msk);
|
||||||
}
|
}
|
||||||
return ret;
|
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,
|
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;
|
int ret = false, len;
|
||||||
u8 rm_addr;
|
u8 rm_addr;
|
||||||
@@ -974,6 +1014,7 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
|||||||
if (remaining < len)
|
if (remaining < len)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
*size = len;
|
||||||
*rm_list = msk->pm.rm_list_tx;
|
*rm_list = msk->pm.rm_list_tx;
|
||||||
WRITE_ONCE(msk->pm.addr_signal, rm_addr);
|
WRITE_ONCE(msk->pm.addr_signal, rm_addr);
|
||||||
ret = true;
|
ret = true;
|
||||||
@@ -1102,7 +1143,7 @@ void mptcp_pm_worker(struct mptcp_sock *msk)
|
|||||||
|
|
||||||
void mptcp_pm_destroy(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))
|
if (mptcp_pm_is_userspace(msk))
|
||||||
mptcp_userspace_pm_free_local_addr_list(msk);
|
mptcp_userspace_pm_free_local_addr_list(msk);
|
||||||
|
|||||||
+11
-11
@@ -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);
|
EXPORT_SYMBOL_GPL(mptcp_pm_get_limit_extra_subflows);
|
||||||
|
|
||||||
static bool lookup_subflow_by_daddr(const struct list_head *list,
|
static bool has_subflow_daddr(const struct mptcp_sock *msk,
|
||||||
const struct mptcp_addr_info *daddr)
|
const struct mptcp_addr_info *daddr)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow;
|
struct mptcp_subflow_context *subflow;
|
||||||
struct mptcp_addr_info cur;
|
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);
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||||
|
|
||||||
if (!((1 << inet_sk_state_load(ssk)) &
|
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
|
/* If the alloc fails, we are on memory pressure, not worth
|
||||||
* continuing, and trying to create subflows.
|
* continuing, and trying to create subflows.
|
||||||
*/
|
*/
|
||||||
if (!mptcp_pm_alloc_anno_list(msk, &local.addr))
|
if (!mptcp_pm_announced_alloc(msk, &local.addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__clear_bit(endp_id, msk->pm.id_avail_bitmap);
|
__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_pm_addr_send_ack(msk);
|
||||||
mptcp_mpc_endpoint_setup(msk);
|
mptcp_mpc_endpoint_setup(msk);
|
||||||
|
|
||||||
if (lookup_subflow_by_daddr(&msk->conn_list, &remote))
|
if (has_subflow_daddr(msk, &remote))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* pick id 0 port, if none is provided the remote address */
|
/* pick id 0 port, if none is provided the remote address */
|
||||||
@@ -1053,7 +1053,7 @@ out_free:
|
|||||||
return ret;
|
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,
|
const struct mptcp_addr_info *addr,
|
||||||
bool force)
|
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);
|
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) {
|
if (announced || force) {
|
||||||
spin_lock_bh(&msk->pm.lock);
|
spin_lock_bh(&msk->pm.lock);
|
||||||
if (announced)
|
if (announced)
|
||||||
@@ -1098,8 +1098,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
|
|||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, addr);
|
remove_subflow = mptcp_pm_has_subflow_saddr(msk, addr);
|
||||||
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
|
mptcp_pm_remove_announced(msk, addr, remove_subflow &&
|
||||||
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
|
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
|
||||||
|
|
||||||
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
|
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
|
||||||
@@ -1236,10 +1236,10 @@ again:
|
|||||||
|
|
||||||
entry = list_prepare_entry(entry, rm_list, list);
|
entry = list_prepare_entry(entry, rm_list, list);
|
||||||
list_for_each_entry_continue(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);
|
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);
|
alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
|
||||||
|
|
||||||
if (slist.nr == MPTCP_RM_IDS_MAX ||
|
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);
|
lock_sock(sk);
|
||||||
spin_lock_bh(&msk->pm.lock);
|
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++;
|
msk->pm.add_addr_signaled++;
|
||||||
mptcp_pm_announce_addr(msk, &addr_val.addr, false);
|
mptcp_pm_announce_addr(msk, &addr_val.addr, false);
|
||||||
mptcp_pm_addr_send_ack(msk);
|
mptcp_pm_addr_send_ack(msk);
|
||||||
@@ -281,9 +281,9 @@ void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
|
|||||||
int anno_nr = 0;
|
int anno_nr = 0;
|
||||||
|
|
||||||
/* only delete if either announced or matching a subflow */
|
/* 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++;
|
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;
|
return;
|
||||||
|
|
||||||
alist.ids[alist.nr++] = entry->addr.id;
|
alist.ids[alist.nr++] = entry->addr.id;
|
||||||
|
|||||||
+11
-37
@@ -798,6 +798,7 @@ 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_path_manager(const struct net *net);
|
const char *mptcp_get_path_manager(const struct net *net);
|
||||||
const char *mptcp_get_scheduler(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);
|
void mptcp_active_disable(struct sock *sk);
|
||||||
bool mptcp_active_should_disable(struct sock *ssk);
|
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);
|
const struct mptcp_addr_info *addr);
|
||||||
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
|
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
|
||||||
const struct mptcp_addr_info *addr);
|
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,
|
void mptcp_pm_send_ack(struct mptcp_sock *msk,
|
||||||
struct mptcp_subflow_context *subflow,
|
struct mptcp_subflow_context *subflow,
|
||||||
bool prio, bool backup);
|
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 *addr,
|
||||||
struct mptcp_addr_info *rem,
|
struct mptcp_addr_info *rem,
|
||||||
u8 bkup);
|
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);
|
const struct mptcp_addr_info *addr);
|
||||||
bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk);
|
bool mptcp_pm_announced_remove(struct mptcp_sock *msk,
|
||||||
struct mptcp_pm_add_entry *
|
const struct mptcp_addr_info *addr);
|
||||||
mptcp_pm_del_add_timer(struct mptcp_sock *msk,
|
bool mptcp_pm_announced_has_ssk(struct mptcp_sock *msk, const struct sock *ssk);
|
||||||
const struct mptcp_addr_info *addr, bool check_id);
|
bool mptcp_pm_has_subflow_saddr(const struct mptcp_sock *msk,
|
||||||
bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
|
const struct mptcp_addr_info *saddr);
|
||||||
const struct mptcp_addr_info *saddr);
|
|
||||||
bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
|
||||||
const struct mptcp_addr_info *addr);
|
|
||||||
int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
|
||||||
struct genl_info *info);
|
struct genl_info *info);
|
||||||
int mptcp_userspace_pm_set_flags(struct mptcp_pm_addr_entry *local,
|
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;
|
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)
|
bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining,
|
||||||
{
|
struct mptcp_addr_info *addr, bool *echo,
|
||||||
u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
|
bool *drop_ts);
|
||||||
|
|
||||||
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_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
|
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_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
|
||||||
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
|
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
|
||||||
struct mptcp_pm_addr_entry *skc);
|
struct mptcp_pm_addr_entry *skc);
|
||||||
|
|||||||
+2
-2
@@ -235,7 +235,7 @@ again:
|
|||||||
pr_debug("syn inet_sport=%d %d\n",
|
pr_debug("syn inet_sport=%d %d\n",
|
||||||
ntohs(inet_sk(sk_listener)->inet_sport),
|
ntohs(inet_sk(sk_listener)->inet_sport),
|
||||||
ntohs(inet_sk((struct sock *)subflow_req->msk)->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_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTSYNRX);
|
||||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@@ -926,7 +926,7 @@ create_child:
|
|||||||
pr_debug("ack inet_sport=%d %d\n",
|
pr_debug("ack inet_sport=%d %d\n",
|
||||||
ntohs(inet_sk(sk)->inet_sport),
|
ntohs(inet_sk(sk)->inet_sport),
|
||||||
ntohs(inet_sk((struct sock *)owner)->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_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTACKRX);
|
||||||
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
||||||
goto dispose_child;
|
goto dispose_child;
|
||||||
|
|||||||
@@ -87,6 +87,10 @@ unset fb_mpc_data
|
|||||||
unset fb_md5_sig
|
unset fb_md5_sig
|
||||||
unset fb_dss
|
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) ||
|
# generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x30) ||
|
||||||
# (ip6 && (ip6[74] & 0xf0) == 0x30)'"
|
# (ip6 && (ip6[74] & 0xf0) == 0x30)'"
|
||||||
CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
|
CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
|
||||||
@@ -1710,6 +1714,9 @@ chk_add_nr()
|
|||||||
local ack_nr=$port_nr
|
local ack_nr=$port_nr
|
||||||
local mis_syn_nr=0
|
local mis_syn_nr=0
|
||||||
local mis_ack_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_tx=$ns1
|
||||||
local ns_rx=$ns2
|
local ns_rx=$ns2
|
||||||
local tx=""
|
local tx=""
|
||||||
@@ -1811,50 +1818,25 @@ chk_add_nr()
|
|||||||
print_ok
|
print_ok
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
chk_add_tx_nr()
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtAddAddrTx")
|
||||||
{
|
|
||||||
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
|
|
||||||
# Tolerate more ADD_ADDR then expected (if any), due to retransmissions
|
# Tolerate more ADD_ADDR then expected (if any), due to retransmissions
|
||||||
elif [ "$count" != "$add_tx_nr" ] &&
|
if [ -n "$count" ] && [ "$count" != "$add_tx_nr" ] &&
|
||||||
{ [ "$add_tx_nr" -eq 0 ] || [ "$count" -lt "$add_tx_nr" ]; }; then
|
{ [ "$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"
|
fail_test "got $count ADD_ADDR[s] TX, expected $add_tx_nr"
|
||||||
else
|
|
||||||
print_ok
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
print_check "add addr echo tx"
|
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtEchoAddTx")
|
||||||
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtEchoAddTx")
|
if [ -n "$count" ] && [ "$count" != "$echo_tx_nr" ]; then
|
||||||
if [ -z "$count" ]; then
|
print_check "add addr echo tx"
|
||||||
print_skip
|
|
||||||
elif [ "$count" != "$echo_tx_nr" ]; then
|
|
||||||
fail_test "got $count ADD_ADDR echo[s] TX, expected $echo_tx_nr"
|
fail_test "got $count ADD_ADDR echo[s] TX, expected $echo_tx_nr"
|
||||||
else
|
|
||||||
print_ok
|
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
chk_add_drop_tx_nr()
|
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtAddAddrTxDrop")
|
||||||
{
|
if [ -n "$count" ] && [ "$count" != "$drop_tx_nr" ]; then
|
||||||
local drop_tx_nr=$1
|
print_check "add addr tx drop"
|
||||||
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
|
|
||||||
fail_test "got $count ADD_ADDR drop[s] TX, expected $drop_tx_nr"
|
fail_test "got $count ADD_ADDR drop[s] TX, expected $drop_tx_nr"
|
||||||
else
|
|
||||||
print_ok
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2267,7 +2249,6 @@ signal_address_tests()
|
|||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 0 0 0
|
chk_join_nr 0 0 0
|
||||||
chk_add_tx_nr 1 1
|
|
||||||
chk_add_nr 1 1
|
chk_add_nr 1 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -2545,8 +2526,8 @@ add_addr_timeout_tests()
|
|||||||
speed=slow \
|
speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 1 1 1
|
chk_join_nr 1 1 1
|
||||||
chk_add_tx_nr 4 4
|
add_addr_echo_tx_nr=4 \
|
||||||
chk_add_nr 4 0
|
chk_add_nr 4 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# add_addr timeout IPv6
|
# add_addr timeout IPv6
|
||||||
@@ -2557,7 +2538,8 @@ add_addr_timeout_tests()
|
|||||||
speed=slow \
|
speed=slow \
|
||||||
run_tests $ns1 $ns2 dead:beef:1::1
|
run_tests $ns1 $ns2 dead:beef:1::1
|
||||||
chk_join_nr 1 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
|
fi
|
||||||
|
|
||||||
# signal addresses timeout
|
# signal addresses timeout
|
||||||
@@ -2569,7 +2551,8 @@ add_addr_timeout_tests()
|
|||||||
speed=10 \
|
speed=10 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 2 2 2
|
chk_join_nr 2 2 2
|
||||||
chk_add_nr 8 0
|
add_addr_echo_tx_nr=8 \
|
||||||
|
chk_add_nr 8 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# signal invalid addresses timeout
|
# signal invalid addresses timeout
|
||||||
@@ -2582,7 +2565,8 @@ add_addr_timeout_tests()
|
|||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
join_syn_tx=2 \
|
join_syn_tx=2 \
|
||||||
chk_join_nr 1 1 1
|
chk_join_nr 1 1 1
|
||||||
chk_add_nr 8 0
|
add_addr_echo_tx_nr=7 \
|
||||||
|
chk_add_nr 8 0
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3214,6 +3198,17 @@ add_addr_ports_tests()
|
|||||||
chk_add_nr 1 1 1
|
chk_add_nr 1 1 1
|
||||||
fi
|
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
|
# subflow and signal with port
|
||||||
if reset "subflow and signal with port"; then
|
if reset "subflow and signal with port"; then
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
|
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
|
if reset "signal addr list progresses after tx drop"; then
|
||||||
pm_nl_set_limits $ns1 0 2
|
pm_nl_set_limits $ns1 0 2
|
||||||
pm_nl_set_limits $ns2 1 0
|
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 $ns1 sysctl -q net.ipv4.tcp_timestamps=1
|
||||||
ip netns exec $ns2 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:2::1 flags signal port 10100
|
||||||
pm_nl_add_endpoint $ns1 dead:beef:3::1 flags signal
|
pm_nl_add_endpoint $ns1 dead:beef:3::1 flags signal
|
||||||
run_tests $ns1 $ns2 dead:beef:1::1
|
run_tests $ns1 $ns2 dead:beef:1::1
|
||||||
chk_add_drop_tx_nr 1
|
add_addr_drop_tx_nr=1 \
|
||||||
chk_add_tx_nr 1 1
|
chk_add_nr 1 1 0
|
||||||
chk_add_nr 1 1 0
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user