2020-01-22 00:56:16 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* Multipath TCP
|
|
|
|
*
|
|
|
|
* Copyright (c) 2017 - 2019, Intel Corporation.
|
|
|
|
*/
|
|
|
|
|
2020-04-03 09:14:08 +00:00
|
|
|
#define pr_fmt(fmt) "MPTCP: " fmt
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
#include <linux/kernel.h>
|
2020-11-13 05:20:21 +00:00
|
|
|
#include <crypto/sha2.h>
|
2020-01-22 00:56:16 +00:00
|
|
|
#include <net/tcp.h>
|
|
|
|
#include <net/mptcp.h>
|
|
|
|
#include "protocol.h"
|
2020-09-24 00:29:51 +00:00
|
|
|
#include "mib.h"
|
2020-01-22 00:56:16 +00:00
|
|
|
|
2020-01-22 00:56:30 +00:00
|
|
|
static bool mptcp_cap_flag_sha256(u8 flags)
|
|
|
|
{
|
|
|
|
return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
|
|
|
|
}
|
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
static void mptcp_parse_option(const struct sk_buff *skb,
|
|
|
|
const unsigned char *ptr, int opsize,
|
|
|
|
struct mptcp_options_received *mp_opt)
|
2020-01-22 00:56:16 +00:00
|
|
|
{
|
|
|
|
u8 subtype = *ptr >> 4;
|
2020-01-22 00:56:24 +00:00
|
|
|
int expected_opsize;
|
2020-01-22 00:56:16 +00:00
|
|
|
u8 version;
|
|
|
|
u8 flags;
|
|
|
|
|
|
|
|
switch (subtype) {
|
|
|
|
case MPTCPOPT_MP_CAPABLE:
|
2020-01-22 00:56:31 +00:00
|
|
|
/* strict size checking */
|
|
|
|
if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
|
|
|
|
if (skb->len > tcp_hdr(skb)->doff << 2)
|
|
|
|
expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA;
|
|
|
|
else
|
|
|
|
expected_opsize = TCPOLEN_MPTCP_MPC_ACK;
|
|
|
|
} else {
|
|
|
|
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK)
|
|
|
|
expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK;
|
|
|
|
else
|
|
|
|
expected_opsize = TCPOLEN_MPTCP_MPC_SYN;
|
|
|
|
}
|
|
|
|
if (opsize != expected_opsize)
|
2020-01-22 00:56:16 +00:00
|
|
|
break;
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
/* try to be gentle vs future versions on the initial syn */
|
2020-01-22 00:56:16 +00:00
|
|
|
version = *ptr++ & MPTCP_VERSION_MASK;
|
2020-01-22 00:56:31 +00:00
|
|
|
if (opsize != TCPOLEN_MPTCP_MPC_SYN) {
|
|
|
|
if (version != MPTCP_SUPPORTED_VERSION)
|
|
|
|
break;
|
|
|
|
} else if (version < MPTCP_SUPPORTED_VERSION) {
|
2020-01-22 00:56:16 +00:00
|
|
|
break;
|
2020-01-22 00:56:31 +00:00
|
|
|
}
|
2020-01-22 00:56:16 +00:00
|
|
|
|
|
|
|
flags = *ptr++;
|
2020-01-22 00:56:30 +00:00
|
|
|
if (!mptcp_cap_flag_sha256(flags) ||
|
2020-01-22 00:56:16 +00:00
|
|
|
(flags & MPTCP_CAP_EXTENSIBILITY))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* RFC 6824, Section 3.1:
|
|
|
|
* "For the Checksum Required bit (labeled "A"), if either
|
|
|
|
* host requires the use of checksums, checksums MUST be used.
|
|
|
|
* In other words, the only way for checksums not to be used
|
|
|
|
* is if both hosts in their SYNs set A=0."
|
|
|
|
*
|
|
|
|
* Section 3.3.0:
|
|
|
|
* "If a checksum is not present when its use has been
|
|
|
|
* negotiated, the receiver MUST close the subflow with a RST as
|
|
|
|
* it is considered broken."
|
|
|
|
*
|
|
|
|
* We don't implement DSS checksum - fall back to TCP.
|
|
|
|
*/
|
|
|
|
if (flags & MPTCP_CAP_CHECKSUM_REQD)
|
|
|
|
break;
|
|
|
|
|
|
|
|
mp_opt->mp_capable = 1;
|
2020-01-22 00:56:31 +00:00
|
|
|
if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) {
|
|
|
|
mp_opt->sndr_key = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
}
|
|
|
|
if (opsize >= TCPOLEN_MPTCP_MPC_ACK) {
|
2020-01-22 00:56:16 +00:00
|
|
|
mp_opt->rcvr_key = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
}
|
2020-01-22 00:56:31 +00:00
|
|
|
if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA) {
|
|
|
|
/* Section 3.1.:
|
|
|
|
* "the data parameters in a MP_CAPABLE are semantically
|
|
|
|
* equivalent to those in a DSS option and can be used
|
|
|
|
* interchangeably."
|
|
|
|
*/
|
|
|
|
mp_opt->dss = 1;
|
|
|
|
mp_opt->use_map = 1;
|
|
|
|
mp_opt->mpc_map = 1;
|
|
|
|
mp_opt->data_len = get_unaligned_be16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
|
|
|
pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d",
|
|
|
|
version, flags, opsize, mp_opt->sndr_key,
|
|
|
|
mp_opt->rcvr_key, mp_opt->data_len);
|
2020-01-22 00:56:16 +00:00
|
|
|
break;
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
case MPTCPOPT_MP_JOIN:
|
|
|
|
mp_opt->mp_join = 1;
|
|
|
|
if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
|
|
|
|
mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
|
|
|
|
mp_opt->join_id = *ptr++;
|
|
|
|
mp_opt->token = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
mp_opt->nonce = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
pr_debug("MP_JOIN bkup=%u, id=%u, token=%u, nonce=%u",
|
|
|
|
mp_opt->backup, mp_opt->join_id,
|
|
|
|
mp_opt->token, mp_opt->nonce);
|
|
|
|
} else if (opsize == TCPOLEN_MPTCP_MPJ_SYNACK) {
|
|
|
|
mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
|
|
|
|
mp_opt->join_id = *ptr++;
|
|
|
|
mp_opt->thmac = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
mp_opt->nonce = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
pr_debug("MP_JOIN bkup=%u, id=%u, thmac=%llu, nonce=%u",
|
|
|
|
mp_opt->backup, mp_opt->join_id,
|
|
|
|
mp_opt->thmac, mp_opt->nonce);
|
|
|
|
} else if (opsize == TCPOLEN_MPTCP_MPJ_ACK) {
|
|
|
|
ptr += 2;
|
|
|
|
memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
|
|
|
|
pr_debug("MP_JOIN hmac");
|
|
|
|
} else {
|
|
|
|
pr_warn("MP_JOIN bad option size");
|
|
|
|
mp_opt->mp_join = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
case MPTCPOPT_DSS:
|
|
|
|
pr_debug("DSS");
|
2020-01-22 00:56:24 +00:00
|
|
|
ptr++;
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
/* we must clear 'mpc_map' be able to detect MP_CAPABLE
|
|
|
|
* map vs DSS map in mptcp_incoming_options(), and reconstruct
|
|
|
|
* map info accordingly
|
|
|
|
*/
|
|
|
|
mp_opt->mpc_map = 0;
|
2020-01-22 00:56:24 +00:00
|
|
|
flags = (*ptr++) & MPTCP_DSS_FLAG_MASK;
|
|
|
|
mp_opt->data_fin = (flags & MPTCP_DSS_DATA_FIN) != 0;
|
|
|
|
mp_opt->dsn64 = (flags & MPTCP_DSS_DSN64) != 0;
|
|
|
|
mp_opt->use_map = (flags & MPTCP_DSS_HAS_MAP) != 0;
|
|
|
|
mp_opt->ack64 = (flags & MPTCP_DSS_ACK64) != 0;
|
|
|
|
mp_opt->use_ack = (flags & MPTCP_DSS_HAS_ACK);
|
|
|
|
|
|
|
|
pr_debug("data_fin=%d dsn64=%d use_map=%d ack64=%d use_ack=%d",
|
|
|
|
mp_opt->data_fin, mp_opt->dsn64,
|
|
|
|
mp_opt->use_map, mp_opt->ack64,
|
|
|
|
mp_opt->use_ack);
|
|
|
|
|
|
|
|
expected_opsize = TCPOLEN_MPTCP_DSS_BASE;
|
|
|
|
|
|
|
|
if (mp_opt->use_ack) {
|
|
|
|
if (mp_opt->ack64)
|
|
|
|
expected_opsize += TCPOLEN_MPTCP_DSS_ACK64;
|
|
|
|
else
|
|
|
|
expected_opsize += TCPOLEN_MPTCP_DSS_ACK32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mp_opt->use_map) {
|
|
|
|
if (mp_opt->dsn64)
|
|
|
|
expected_opsize += TCPOLEN_MPTCP_DSS_MAP64;
|
|
|
|
else
|
|
|
|
expected_opsize += TCPOLEN_MPTCP_DSS_MAP32;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* RFC 6824, Section 3.3:
|
|
|
|
* If a checksum is present, but its use had
|
|
|
|
* not been negotiated in the MP_CAPABLE handshake,
|
|
|
|
* the checksum field MUST be ignored.
|
|
|
|
*/
|
|
|
|
if (opsize != expected_opsize &&
|
|
|
|
opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM)
|
|
|
|
break;
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
mp_opt->dss = 1;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
if (mp_opt->use_ack) {
|
|
|
|
if (mp_opt->ack64) {
|
|
|
|
mp_opt->data_ack = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
} else {
|
|
|
|
mp_opt->data_ack = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
pr_debug("data_ack=%llu", mp_opt->data_ack);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mp_opt->use_map) {
|
|
|
|
if (mp_opt->dsn64) {
|
|
|
|
mp_opt->data_seq = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
} else {
|
|
|
|
mp_opt->data_seq = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
mp_opt->subflow_seq = get_unaligned_be32(ptr);
|
|
|
|
ptr += 4;
|
|
|
|
|
|
|
|
mp_opt->data_len = get_unaligned_be16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
|
|
|
|
pr_debug("data_seq=%llu subflow_seq=%u data_len=%u",
|
|
|
|
mp_opt->data_seq, mp_opt->subflow_seq,
|
|
|
|
mp_opt->data_len);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
break;
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
case MPTCPOPT_ADD_ADDR:
|
|
|
|
mp_opt->echo = (*ptr++) & MPTCP_ADDR_ECHO;
|
|
|
|
if (!mp_opt->echo) {
|
|
|
|
if (opsize == TCPOLEN_MPTCP_ADD_ADDR ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT)
|
|
|
|
mp_opt->family = MPTCP_ADDR_IPVERSION_4;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6 ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT)
|
|
|
|
mp_opt->family = MPTCP_ADDR_IPVERSION_6;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT)
|
|
|
|
mp_opt->family = MPTCP_ADDR_IPVERSION_4;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT)
|
|
|
|
mp_opt->family = MPTCP_ADDR_IPVERSION_6;
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
mp_opt->add_addr = 1;
|
|
|
|
mp_opt->addr_id = *ptr++;
|
|
|
|
if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) {
|
|
|
|
memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4);
|
|
|
|
ptr += 4;
|
|
|
|
if (opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT) {
|
|
|
|
mp_opt->port = get_unaligned_be16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else {
|
|
|
|
memcpy(mp_opt->addr6.s6_addr, (u8 *)ptr, 16);
|
|
|
|
ptr += 16;
|
|
|
|
if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT ||
|
|
|
|
opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT) {
|
|
|
|
mp_opt->port = get_unaligned_be16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!mp_opt->echo) {
|
|
|
|
mp_opt->ahmac = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
}
|
2020-12-09 23:51:25 +00:00
|
|
|
pr_debug("ADD_ADDR%s: id=%d, ahmac=%llu, echo=%d, port=%d",
|
|
|
|
(mp_opt->family == MPTCP_ADDR_IPVERSION_6) ? "6" : "",
|
|
|
|
mp_opt->addr_id, mp_opt->ahmac, mp_opt->echo, mp_opt->port);
|
2020-03-27 21:48:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MPTCPOPT_RM_ADDR:
|
|
|
|
if (opsize != TCPOLEN_MPTCP_RM_ADDR_BASE)
|
|
|
|
break;
|
|
|
|
|
2020-06-08 10:47:54 +00:00
|
|
|
ptr++;
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
mp_opt->rm_addr = 1;
|
|
|
|
mp_opt->rm_id = *ptr++;
|
|
|
|
pr_debug("RM_ADDR: id=%d", mp_opt->rm_id);
|
|
|
|
break;
|
|
|
|
|
2020-12-10 22:25:04 +00:00
|
|
|
case MPTCPOPT_MP_FASTCLOSE:
|
|
|
|
if (opsize != TCPOLEN_MPTCP_FASTCLOSE)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ptr += 2;
|
|
|
|
mp_opt->rcvr_key = get_unaligned_be64(ptr);
|
|
|
|
ptr += 8;
|
|
|
|
mp_opt->fastclose = 1;
|
|
|
|
break;
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
void mptcp_get_options(const struct sk_buff *skb,
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
struct mptcp_options_received *mp_opt)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
|
|
|
const struct tcphdr *th = tcp_hdr(skb);
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
const unsigned char *ptr;
|
|
|
|
int length;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
/* initialize option status */
|
|
|
|
mp_opt->mp_capable = 0;
|
|
|
|
mp_opt->mp_join = 0;
|
|
|
|
mp_opt->add_addr = 0;
|
2020-10-19 10:23:15 +00:00
|
|
|
mp_opt->ahmac = 0;
|
2020-12-10 22:25:04 +00:00
|
|
|
mp_opt->fastclose = 0;
|
2020-10-19 10:23:16 +00:00
|
|
|
mp_opt->port = 0;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mp_opt->rm_addr = 0;
|
|
|
|
mp_opt->dss = 0;
|
|
|
|
|
|
|
|
length = (th->doff * 4) - sizeof(struct tcphdr);
|
2020-01-22 00:56:18 +00:00
|
|
|
ptr = (const unsigned char *)(th + 1);
|
|
|
|
|
|
|
|
while (length > 0) {
|
|
|
|
int opcode = *ptr++;
|
|
|
|
int opsize;
|
|
|
|
|
|
|
|
switch (opcode) {
|
|
|
|
case TCPOPT_EOL:
|
|
|
|
return;
|
|
|
|
case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
|
|
|
|
length--;
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
opsize = *ptr++;
|
|
|
|
if (opsize < 2) /* "silly options" */
|
|
|
|
return;
|
|
|
|
if (opsize > length)
|
|
|
|
return; /* don't parse partial options */
|
|
|
|
if (opcode == TCPOPT_MPTCP)
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mptcp_parse_option(skb, ptr, opsize, mp_opt);
|
2020-01-22 00:56:18 +00:00
|
|
|
ptr += opsize - 2;
|
|
|
|
length -= opsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
|
|
|
|
unsigned int *size, struct mptcp_out_options *opts)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
/* we will use snd_isn to detect first pkt [re]transmission
|
|
|
|
* in mptcp_established_options_mp()
|
|
|
|
*/
|
|
|
|
subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
|
2020-01-22 00:56:18 +00:00
|
|
|
if (subflow->request_mptcp) {
|
|
|
|
opts->suboptions = OPTION_MPTCP_MPC_SYN;
|
|
|
|
*size = TCPOLEN_MPTCP_MPC_SYN;
|
|
|
|
return true;
|
2020-03-27 21:48:40 +00:00
|
|
|
} else if (subflow->request_join) {
|
|
|
|
pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
|
|
|
|
subflow->local_nonce);
|
|
|
|
opts->suboptions = OPTION_MPTCP_MPJ_SYN;
|
|
|
|
opts->join_id = subflow->local_id;
|
|
|
|
opts->token = subflow->remote_token;
|
|
|
|
opts->nonce = subflow->local_nonce;
|
|
|
|
opts->backup = subflow->request_bkup;
|
|
|
|
*size = TCPOLEN_MPTCP_MPJ_SYN;
|
|
|
|
return true;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
/* MP_JOIN client subflow must wait for 4th ack before sending any data:
|
|
|
|
* TCP can't schedule delack timer before the subflow is fully established.
|
|
|
|
* MPTCP uses the delack timer to do 3rd ack retransmissions
|
|
|
|
*/
|
|
|
|
static void schedule_3rdack_retransmission(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
|
unsigned long timeout;
|
|
|
|
|
|
|
|
/* reschedule with a timeout above RTT, as we must look only for drop */
|
|
|
|
if (tp->srtt_us)
|
|
|
|
timeout = tp->srtt_us << 1;
|
|
|
|
else
|
|
|
|
timeout = TCP_TIMEOUT_INIT;
|
|
|
|
|
|
|
|
WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER);
|
|
|
|
icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
|
|
|
|
icsk->icsk_ack.timeout = timeout;
|
|
|
|
sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void clear_3rdack_retransmission(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
|
|
|
|
sk_stop_timer(sk, &icsk->icsk_delack_timer);
|
|
|
|
icsk->icsk_ack.timeout = 0;
|
|
|
|
icsk->icsk_ack.ato = 0;
|
|
|
|
icsk->icsk_ack.pending &= ~(ICSK_ACK_SCHED | ICSK_ACK_TIMER);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
|
|
|
|
unsigned int *size,
|
2020-01-22 00:56:23 +00:00
|
|
|
unsigned int remaining,
|
|
|
|
struct mptcp_out_options *opts)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
2020-01-22 00:56:31 +00:00
|
|
|
struct mptcp_ext *mpext;
|
|
|
|
unsigned int data_len;
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
/* When skb is not available, we better over-estimate the emitted
|
|
|
|
* options len. A full DSS option (28 bytes) is longer than
|
|
|
|
* TCPOLEN_MPTCP_MPC_ACK_DATA(22) or TCPOLEN_MPTCP_MPJ_ACK(24), so
|
|
|
|
* tell the caller to defer the estimate to
|
|
|
|
* mptcp_established_options_dss(), which will reserve enough space.
|
|
|
|
*/
|
|
|
|
if (!skb)
|
|
|
|
return false;
|
2020-01-22 00:56:31 +00:00
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
/* MPC/MPJ needed only on 3rd ack packet */
|
|
|
|
if (subflow->fully_established ||
|
|
|
|
subflow->snd_isn != TCP_SKB_CB(skb)->seq)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (subflow->mp_capable) {
|
2020-01-22 00:56:31 +00:00
|
|
|
mpext = mptcp_get_ext(skb);
|
|
|
|
data_len = mpext ? mpext->data_len : 0;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
/* we will check ext_copy.data_len in mptcp_write_options() to
|
|
|
|
* discriminate between TCPOLEN_MPTCP_MPC_ACK_DATA and
|
|
|
|
* TCPOLEN_MPTCP_MPC_ACK
|
|
|
|
*/
|
|
|
|
opts->ext_copy.data_len = data_len;
|
2020-01-22 00:56:18 +00:00
|
|
|
opts->suboptions = OPTION_MPTCP_MPC_ACK;
|
|
|
|
opts->sndr_key = subflow->local_key;
|
|
|
|
opts->rcvr_key = subflow->remote_key;
|
2020-01-22 00:56:31 +00:00
|
|
|
|
|
|
|
/* Section 3.1.
|
|
|
|
* The MP_CAPABLE option is carried on the SYN, SYN/ACK, and ACK
|
|
|
|
* packets that start the first subflow of an MPTCP connection,
|
|
|
|
* as well as the first packet that carries data
|
|
|
|
*/
|
|
|
|
if (data_len > 0)
|
|
|
|
*size = ALIGN(TCPOLEN_MPTCP_MPC_ACK_DATA, 4);
|
|
|
|
else
|
|
|
|
*size = TCPOLEN_MPTCP_MPC_ACK;
|
|
|
|
|
|
|
|
pr_debug("subflow=%p, local_key=%llu, remote_key=%llu map_len=%d",
|
|
|
|
subflow, subflow->local_key, subflow->remote_key,
|
|
|
|
data_len);
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
return true;
|
2020-03-27 21:48:40 +00:00
|
|
|
} else if (subflow->mp_join) {
|
|
|
|
opts->suboptions = OPTION_MPTCP_MPJ_ACK;
|
|
|
|
memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
|
|
|
|
*size = TCPOLEN_MPTCP_MPJ_ACK;
|
|
|
|
pr_debug("subflow=%p", subflow);
|
|
|
|
|
|
|
|
schedule_3rdack_retransmission(sk);
|
|
|
|
return true;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:23 +00:00
|
|
|
static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
|
2020-07-03 16:06:04 +00:00
|
|
|
struct sk_buff *skb, struct mptcp_ext *ext)
|
2020-01-22 00:56:23 +00:00
|
|
|
{
|
2020-10-05 10:01:06 +00:00
|
|
|
/* The write_seq value has already been incremented, so the actual
|
|
|
|
* sequence number for the DATA_FIN is one less.
|
|
|
|
*/
|
|
|
|
u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq) - 1;
|
2020-07-28 22:12:02 +00:00
|
|
|
|
2020-07-03 16:06:04 +00:00
|
|
|
if (!ext->use_map || !skb->len) {
|
2020-01-22 00:56:23 +00:00
|
|
|
/* RFC6824 requires a DSS mapping with specific values
|
|
|
|
* if DATA_FIN is set but no data payload is mapped
|
|
|
|
*/
|
2020-02-28 23:47:41 +00:00
|
|
|
ext->data_fin = 1;
|
2020-01-22 00:56:23 +00:00
|
|
|
ext->use_map = 1;
|
|
|
|
ext->dsn64 = 1;
|
2020-10-05 10:01:06 +00:00
|
|
|
ext->data_seq = data_fin_tx_seq;
|
2020-01-22 00:56:23 +00:00
|
|
|
ext->subflow_seq = 0;
|
|
|
|
ext->data_len = 1;
|
2020-07-28 22:12:02 +00:00
|
|
|
} else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
|
2020-02-28 23:47:41 +00:00
|
|
|
/* If there's an existing DSS mapping and it is the
|
|
|
|
* final mapping, DATA_FIN consumes 1 additional byte of
|
|
|
|
* mapping space.
|
2020-01-22 00:56:23 +00:00
|
|
|
*/
|
2020-02-28 23:47:41 +00:00
|
|
|
ext->data_fin = 1;
|
2020-01-22 00:56:23 +00:00
|
|
|
ext->data_len++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
|
|
|
|
unsigned int *size,
|
|
|
|
unsigned int remaining,
|
|
|
|
struct mptcp_out_options *opts)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
2020-07-28 22:12:02 +00:00
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
2020-01-22 00:56:23 +00:00
|
|
|
unsigned int dss_size = 0;
|
2020-07-28 22:12:02 +00:00
|
|
|
u64 snd_data_fin_enable;
|
2020-01-22 00:56:23 +00:00
|
|
|
struct mptcp_ext *mpext;
|
|
|
|
unsigned int ack_size;
|
2020-01-22 00:56:32 +00:00
|
|
|
bool ret = false;
|
2020-01-22 00:56:23 +00:00
|
|
|
|
2020-07-28 22:11:59 +00:00
|
|
|
mpext = skb ? mptcp_get_ext(skb) : NULL;
|
2020-11-16 09:48:09 +00:00
|
|
|
snd_data_fin_enable = mptcp_data_fin_enabled(msk);
|
2020-01-22 00:56:23 +00:00
|
|
|
|
2020-07-28 22:12:02 +00:00
|
|
|
if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
|
2020-01-22 00:56:23 +00:00
|
|
|
unsigned int map_size;
|
|
|
|
|
|
|
|
map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
|
|
|
|
|
|
|
|
remaining -= map_size;
|
|
|
|
dss_size = map_size;
|
|
|
|
if (mpext)
|
|
|
|
opts->ext_copy = *mpext;
|
|
|
|
|
2020-07-28 22:12:02 +00:00
|
|
|
if (skb && snd_data_fin_enable)
|
2020-07-03 16:06:04 +00:00
|
|
|
mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
|
2020-01-22 00:56:32 +00:00
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
2020-03-04 15:51:07 +00:00
|
|
|
/* passive sockets msk will set the 'can_ack' after accept(), even
|
|
|
|
* if the first subflow may have the already the remote key handy
|
|
|
|
*/
|
2020-01-22 00:56:32 +00:00
|
|
|
opts->ext_copy.use_ack = 0;
|
2020-03-13 15:52:42 +00:00
|
|
|
if (!READ_ONCE(msk->can_ack)) {
|
2020-01-22 00:56:32 +00:00
|
|
|
*size = ALIGN(dss_size, 4);
|
|
|
|
return ret;
|
2020-01-22 00:56:23 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 16:26:17 +00:00
|
|
|
if (READ_ONCE(msk->use_64bit_ack)) {
|
2020-05-14 15:53:03 +00:00
|
|
|
ack_size = TCPOLEN_MPTCP_DSS_ACK64;
|
2020-09-29 22:08:19 +00:00
|
|
|
opts->ext_copy.data_ack = READ_ONCE(msk->ack_seq);
|
2020-05-14 15:53:03 +00:00
|
|
|
opts->ext_copy.ack64 = 1;
|
|
|
|
} else {
|
|
|
|
ack_size = TCPOLEN_MPTCP_DSS_ACK32;
|
2020-09-29 22:08:19 +00:00
|
|
|
opts->ext_copy.data_ack32 = (uint32_t)READ_ONCE(msk->ack_seq);
|
2020-05-14 15:53:03 +00:00
|
|
|
opts->ext_copy.ack64 = 0;
|
|
|
|
}
|
|
|
|
opts->ext_copy.use_ack = 1;
|
2020-11-19 19:46:03 +00:00
|
|
|
WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk));
|
2020-01-22 00:56:23 +00:00
|
|
|
|
|
|
|
/* Add kind/length/subtype/flag overhead if mapping is not populated */
|
|
|
|
if (dss_size == 0)
|
|
|
|
ack_size += TCPOLEN_MPTCP_DSS_BASE;
|
|
|
|
|
|
|
|
dss_size += ack_size;
|
|
|
|
|
|
|
|
*size = ALIGN(dss_size, 4);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
static u64 add_addr_generate_hmac(u64 key1, u64 key2, u8 addr_id,
|
|
|
|
struct in_addr *addr)
|
|
|
|
{
|
2020-05-22 02:10:49 +00:00
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
2020-03-27 21:48:37 +00:00
|
|
|
u8 msg[7];
|
|
|
|
|
|
|
|
msg[0] = addr_id;
|
|
|
|
memcpy(&msg[1], &addr->s_addr, 4);
|
|
|
|
msg[5] = 0;
|
|
|
|
msg[6] = 0;
|
|
|
|
|
|
|
|
mptcp_crypto_hmac_sha(key1, key2, msg, 7, hmac);
|
|
|
|
|
2020-05-22 02:10:49 +00:00
|
|
|
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
|
|
|
|
struct in6_addr *addr)
|
|
|
|
{
|
2020-05-22 02:10:49 +00:00
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
2020-03-27 21:48:37 +00:00
|
|
|
u8 msg[19];
|
|
|
|
|
|
|
|
msg[0] = addr_id;
|
|
|
|
memcpy(&msg[1], &addr->s6_addr, 16);
|
|
|
|
msg[17] = 0;
|
|
|
|
msg[18] = 0;
|
|
|
|
|
|
|
|
mptcp_crypto_hmac_sha(key1, key2, msg, 19, hmac);
|
|
|
|
|
2020-05-22 02:10:49 +00:00
|
|
|
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-11-19 19:46:00 +00:00
|
|
|
static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb,
|
2020-09-24 00:29:47 +00:00
|
|
|
unsigned int *size,
|
|
|
|
unsigned int remaining,
|
|
|
|
struct mptcp_out_options *opts)
|
2020-03-27 21:48:37 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
2020-11-19 19:46:00 +00:00
|
|
|
bool drop_other_suboptions = false;
|
|
|
|
unsigned int opt_size = *size;
|
2020-03-27 21:48:38 +00:00
|
|
|
struct mptcp_addr_info saddr;
|
2020-09-24 00:29:50 +00:00
|
|
|
bool echo;
|
2020-12-09 23:51:22 +00:00
|
|
|
bool port;
|
2020-03-27 21:48:38 +00:00
|
|
|
int len;
|
2020-03-27 21:48:37 +00:00
|
|
|
|
2020-12-09 23:51:23 +00:00
|
|
|
if ((mptcp_pm_should_add_signal_ipv6(msk) ||
|
|
|
|
mptcp_pm_should_add_signal_port(msk)) &&
|
2020-11-19 19:46:00 +00:00
|
|
|
skb && skb_is_tcp_pure_ack(skb)) {
|
|
|
|
pr_debug("drop other suboptions");
|
|
|
|
opts->suboptions = 0;
|
|
|
|
remaining += opt_size;
|
|
|
|
drop_other_suboptions = true;
|
|
|
|
}
|
|
|
|
|
2020-09-24 00:29:47 +00:00
|
|
|
if (!mptcp_pm_should_add_signal(msk) ||
|
2020-12-09 23:51:22 +00:00
|
|
|
!(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo, &port)))
|
2020-03-27 21:48:38 +00:00
|
|
|
return false;
|
|
|
|
|
2020-12-09 23:51:22 +00:00
|
|
|
len = mptcp_add_addr_len(saddr.family, echo, port);
|
2020-03-27 21:48:38 +00:00
|
|
|
if (remaining < len)
|
|
|
|
return false;
|
2020-03-27 21:48:37 +00:00
|
|
|
|
2020-03-27 21:48:38 +00:00
|
|
|
*size = len;
|
2020-11-19 19:46:00 +00:00
|
|
|
if (drop_other_suboptions)
|
|
|
|
*size -= opt_size;
|
2020-03-27 21:48:38 +00:00
|
|
|
opts->addr_id = saddr.id;
|
2020-12-09 23:51:22 +00:00
|
|
|
if (port)
|
|
|
|
opts->port = ntohs(saddr.port);
|
2020-03-27 21:48:38 +00:00
|
|
|
if (saddr.family == AF_INET) {
|
2020-03-27 21:48:37 +00:00
|
|
|
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
|
2020-03-27 21:48:38 +00:00
|
|
|
opts->addr = saddr.addr;
|
2020-09-24 00:29:50 +00:00
|
|
|
if (!echo) {
|
|
|
|
opts->ahmac = add_addr_generate_hmac(msk->local_key,
|
|
|
|
msk->remote_key,
|
|
|
|
opts->addr_id,
|
|
|
|
&opts->addr);
|
|
|
|
}
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2020-03-27 21:48:38 +00:00
|
|
|
else if (saddr.family == AF_INET6) {
|
2020-03-27 21:48:37 +00:00
|
|
|
opts->suboptions |= OPTION_MPTCP_ADD_ADDR6;
|
2020-03-27 21:48:38 +00:00
|
|
|
opts->addr6 = saddr.addr6;
|
2020-09-24 00:29:50 +00:00
|
|
|
if (!echo) {
|
|
|
|
opts->ahmac = add_addr6_generate_hmac(msk->local_key,
|
|
|
|
msk->remote_key,
|
|
|
|
opts->addr_id,
|
|
|
|
&opts->addr6);
|
|
|
|
}
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
#endif
|
2020-12-09 23:51:22 +00:00
|
|
|
pr_debug("addr_id=%d, ahmac=%llu, echo=%d, port=%d",
|
|
|
|
opts->addr_id, opts->ahmac, echo, opts->port);
|
2020-03-27 21:48:37 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-09-24 00:29:48 +00:00
|
|
|
static bool mptcp_established_options_rm_addr(struct sock *sk,
|
|
|
|
unsigned 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);
|
|
|
|
u8 rm_id;
|
|
|
|
|
|
|
|
if (!mptcp_pm_should_rm_signal(msk) ||
|
|
|
|
!(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
|
|
|
|
opts->suboptions |= OPTION_MPTCP_RM_ADDR;
|
|
|
|
opts->rm_id = rm_id;
|
|
|
|
|
|
|
|
pr_debug("rm_id=%d", opts->rm_id);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:23 +00:00
|
|
|
bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
|
|
|
|
unsigned int *size, unsigned int remaining,
|
|
|
|
struct mptcp_out_options *opts)
|
|
|
|
{
|
|
|
|
unsigned int opt_size = 0;
|
|
|
|
bool ret = false;
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
opts->suboptions = 0;
|
|
|
|
|
2020-06-29 20:26:20 +00:00
|
|
|
if (unlikely(mptcp_check_fallback(sk)))
|
|
|
|
return false;
|
|
|
|
|
2020-10-09 17:00:00 +00:00
|
|
|
/* prevent adding of any MPTCP related options on reset packet
|
|
|
|
* until we support MP_TCPRST/MP_FASTCLOSE
|
|
|
|
*/
|
|
|
|
if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST))
|
|
|
|
return false;
|
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
if (mptcp_established_options_mp(sk, skb, &opt_size, remaining, opts))
|
2020-01-22 00:56:23 +00:00
|
|
|
ret = true;
|
|
|
|
else if (mptcp_established_options_dss(sk, skb, &opt_size, remaining,
|
|
|
|
opts))
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
/* we reserved enough space for the above options, and exceeding the
|
|
|
|
* TCP option space would be fatal
|
|
|
|
*/
|
|
|
|
if (WARN_ON_ONCE(opt_size > remaining))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*size += opt_size;
|
|
|
|
remaining -= opt_size;
|
2020-11-19 19:46:00 +00:00
|
|
|
if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, opts)) {
|
2020-03-27 21:48:37 +00:00
|
|
|
*size += opt_size;
|
|
|
|
remaining -= opt_size;
|
|
|
|
ret = true;
|
2020-09-24 00:29:48 +00:00
|
|
|
} else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
|
|
|
|
*size += opt_size;
|
|
|
|
remaining -= opt_size;
|
|
|
|
ret = true;
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
2020-01-22 00:56:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
bool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
|
|
|
|
struct mptcp_out_options *opts)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
|
|
|
|
if (subflow_req->mp_capable) {
|
|
|
|
opts->suboptions = OPTION_MPTCP_MPC_SYNACK;
|
|
|
|
opts->sndr_key = subflow_req->local_key;
|
|
|
|
*size = TCPOLEN_MPTCP_MPC_SYNACK;
|
|
|
|
pr_debug("subflow_req=%p, local_key=%llu",
|
|
|
|
subflow_req, subflow_req->local_key);
|
|
|
|
return true;
|
2020-03-27 21:48:39 +00:00
|
|
|
} else if (subflow_req->mp_join) {
|
|
|
|
opts->suboptions = OPTION_MPTCP_MPJ_SYNACK;
|
|
|
|
opts->backup = subflow_req->backup;
|
|
|
|
opts->join_id = subflow_req->local_id;
|
|
|
|
opts->thmac = subflow_req->thmac;
|
|
|
|
opts->nonce = subflow_req->local_nonce;
|
|
|
|
pr_debug("req=%p, bkup=%u, id=%u, thmac=%llu, nonce=%u",
|
|
|
|
subflow_req, opts->backup, opts->join_id,
|
|
|
|
opts->thmac, opts->nonce);
|
|
|
|
*size = TCPOLEN_MPTCP_MPJ_SYNACK;
|
|
|
|
return true;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-09 17:00:00 +00:00
|
|
|
static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
|
2020-03-27 21:48:39 +00:00
|
|
|
struct mptcp_subflow_context *subflow,
|
2020-03-19 10:06:30 +00:00
|
|
|
struct sk_buff *skb,
|
|
|
|
struct mptcp_options_received *mp_opt)
|
2020-01-22 00:56:32 +00:00
|
|
|
{
|
|
|
|
/* here we can process OoO, in-window pkts, only in-sequence 4th ack
|
2020-03-27 21:48:39 +00:00
|
|
|
* will make the subflow fully established
|
2020-01-22 00:56:32 +00:00
|
|
|
*/
|
2020-03-27 21:48:39 +00:00
|
|
|
if (likely(subflow->fully_established)) {
|
|
|
|
/* on passive sockets, check for 3rd ack retransmission
|
|
|
|
* note that msk is always set by subflow_syn_recv_sock()
|
|
|
|
* for mp_join subflows
|
|
|
|
*/
|
|
|
|
if (TCP_SKB_CB(skb)->seq == subflow->ssn_offset + 1 &&
|
|
|
|
TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq &&
|
|
|
|
subflow->mp_join && mp_opt->mp_join &&
|
|
|
|
READ_ONCE(msk->pm.server_side))
|
2020-10-09 17:00:00 +00:00
|
|
|
tcp_send_ack(ssk);
|
2020-03-27 21:48:39 +00:00
|
|
|
goto fully_established;
|
|
|
|
}
|
|
|
|
|
2020-10-09 17:00:00 +00:00
|
|
|
/* we must process OoO packets before the first subflow is fully
|
|
|
|
* established. OoO packets are instead a protocol violation
|
|
|
|
* for MP_JOIN subflows as the peer must not send any data
|
|
|
|
* before receiving the forth ack - cfr. RFC 8684 section 3.2.
|
2020-03-27 21:48:39 +00:00
|
|
|
*/
|
2020-10-09 17:00:00 +00:00
|
|
|
if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1) {
|
|
|
|
if (subflow->mp_join)
|
|
|
|
goto reset;
|
2020-03-27 21:48:39 +00:00
|
|
|
return subflow->mp_capable;
|
2020-10-09 17:00:00 +00:00
|
|
|
}
|
2020-01-22 00:56:32 +00:00
|
|
|
|
2020-04-30 13:01:54 +00:00
|
|
|
if (mp_opt->dss && mp_opt->use_ack) {
|
2020-03-27 21:48:39 +00:00
|
|
|
/* subflows are fully established as soon as we get any
|
|
|
|
* additional ack.
|
|
|
|
*/
|
2020-03-19 10:06:30 +00:00
|
|
|
subflow->fully_established = 1;
|
2020-07-23 11:02:32 +00:00
|
|
|
WRITE_ONCE(msk->fully_established, true);
|
2020-03-27 21:48:39 +00:00
|
|
|
goto fully_established;
|
|
|
|
}
|
2020-01-22 00:56:32 +00:00
|
|
|
|
2020-11-19 19:46:00 +00:00
|
|
|
if (mp_opt->add_addr) {
|
|
|
|
WRITE_ONCE(msk->fully_established, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:32 +00:00
|
|
|
/* If the first established packet does not contain MP_CAPABLE + data
|
2020-10-09 17:00:00 +00:00
|
|
|
* then fallback to TCP. Fallback scenarios requires a reset for
|
|
|
|
* MP_JOIN subflows.
|
2020-01-22 00:56:32 +00:00
|
|
|
*/
|
|
|
|
if (!mp_opt->mp_capable) {
|
2020-10-09 17:00:00 +00:00
|
|
|
if (subflow->mp_join)
|
|
|
|
goto reset;
|
2020-01-22 00:56:32 +00:00
|
|
|
subflow->mp_capable = 0;
|
2020-06-29 20:26:20 +00:00
|
|
|
pr_fallback(msk);
|
|
|
|
__mptcp_do_fallback(msk);
|
2020-01-22 00:56:32 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-03-27 21:48:39 +00:00
|
|
|
|
2020-04-30 13:01:53 +00:00
|
|
|
if (unlikely(!READ_ONCE(msk->pm.server_side)))
|
|
|
|
pr_warn_once("bogus mpc option on established client sk");
|
2020-07-23 11:02:32 +00:00
|
|
|
mptcp_subflow_fully_established(subflow, mp_opt);
|
2020-03-27 21:48:39 +00:00
|
|
|
|
|
|
|
fully_established:
|
2020-12-09 11:03:29 +00:00
|
|
|
/* if the subflow is not already linked into the conn_list, we can't
|
|
|
|
* notify the PM: this subflow is still on the listener queue
|
|
|
|
* and the PM possibly acquiring the subflow lock could race with
|
|
|
|
* the listener close
|
|
|
|
*/
|
|
|
|
if (likely(subflow->pm_notified) || list_empty(&subflow->node))
|
2020-03-27 21:48:39 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
subflow->pm_notified = 1;
|
2020-03-27 21:48:40 +00:00
|
|
|
if (subflow->mp_join) {
|
2020-10-09 17:00:00 +00:00
|
|
|
clear_3rdack_retransmission(ssk);
|
2020-03-27 21:48:39 +00:00
|
|
|
mptcp_pm_subflow_established(msk, subflow);
|
2020-03-27 21:48:40 +00:00
|
|
|
} else {
|
2020-03-27 21:48:39 +00:00
|
|
|
mptcp_pm_fully_established(msk);
|
2020-03-27 21:48:40 +00:00
|
|
|
}
|
2020-01-22 00:56:32 +00:00
|
|
|
return true;
|
2020-10-09 17:00:00 +00:00
|
|
|
|
|
|
|
reset:
|
|
|
|
mptcp_subflow_reset(ssk);
|
|
|
|
return false;
|
2020-01-22 00:56:32 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:42 +00:00
|
|
|
static u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit)
|
|
|
|
{
|
|
|
|
u32 old_ack32, cur_ack32;
|
|
|
|
|
|
|
|
if (use_64bit)
|
|
|
|
return cur_ack;
|
|
|
|
|
|
|
|
old_ack32 = (u32)old_ack;
|
|
|
|
cur_ack32 = (u32)cur_ack;
|
|
|
|
cur_ack = (old_ack & GENMASK_ULL(63, 32)) + cur_ack32;
|
|
|
|
if (unlikely(before(cur_ack32, old_ack32)))
|
|
|
|
return cur_ack + (1LL << 32);
|
|
|
|
return cur_ack;
|
|
|
|
}
|
|
|
|
|
2020-11-16 09:48:13 +00:00
|
|
|
static void ack_update_msk(struct mptcp_sock *msk,
|
2020-11-27 10:10:27 +00:00
|
|
|
struct sock *ssk,
|
2020-11-16 09:48:13 +00:00
|
|
|
struct mptcp_options_received *mp_opt)
|
2020-03-27 21:48:42 +00:00
|
|
|
{
|
2020-11-27 10:10:26 +00:00
|
|
|
u64 new_wnd_end, new_snd_una, snd_nxt = READ_ONCE(msk->snd_nxt);
|
2020-11-16 09:48:13 +00:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
2020-11-27 10:10:26 +00:00
|
|
|
u64 old_snd_una;
|
|
|
|
|
|
|
|
mptcp_data_lock(sk);
|
2020-03-27 21:48:42 +00:00
|
|
|
|
|
|
|
/* avoid ack expansion on update conflict, to reduce the risk of
|
|
|
|
* wrongly expanding to a future ack sequence number, which is way
|
|
|
|
* more dangerous than missing an ack
|
|
|
|
*/
|
2020-11-27 10:10:26 +00:00
|
|
|
old_snd_una = msk->snd_una;
|
2020-03-27 21:48:42 +00:00
|
|
|
new_snd_una = expand_ack(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
|
|
|
|
|
|
|
|
/* ACK for data not even sent yet? Ignore. */
|
2020-11-16 09:48:08 +00:00
|
|
|
if (after64(new_snd_una, snd_nxt))
|
2020-03-27 21:48:42 +00:00
|
|
|
new_snd_una = old_snd_una;
|
|
|
|
|
2020-11-16 09:48:13 +00:00
|
|
|
new_wnd_end = new_snd_una + tcp_sk(ssk)->snd_wnd;
|
|
|
|
|
2020-11-27 10:10:26 +00:00
|
|
|
if (after64(new_wnd_end, msk->wnd_end)) {
|
|
|
|
msk->wnd_end = new_wnd_end;
|
2020-11-27 10:10:27 +00:00
|
|
|
__mptcp_wnd_updated(sk, ssk);
|
2020-11-16 09:48:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 10:10:26 +00:00
|
|
|
if (after64(new_snd_una, old_snd_una)) {
|
|
|
|
msk->snd_una = new_snd_una;
|
|
|
|
__mptcp_data_acked(sk);
|
2020-03-27 21:48:42 +00:00
|
|
|
}
|
2020-11-27 10:10:26 +00:00
|
|
|
mptcp_data_unlock(sk);
|
2020-03-27 21:48:42 +00:00
|
|
|
}
|
|
|
|
|
2020-09-29 22:08:20 +00:00
|
|
|
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit)
|
2020-07-28 22:12:03 +00:00
|
|
|
{
|
|
|
|
/* Skip if DATA_FIN was already received.
|
|
|
|
* If updating simultaneously with the recvmsg loop, values
|
|
|
|
* should match. If they mismatch, the peer is misbehaving and
|
|
|
|
* we will prefer the most recent information.
|
|
|
|
*/
|
|
|
|
if (READ_ONCE(msk->rcv_data_fin) || !READ_ONCE(msk->first))
|
|
|
|
return false;
|
|
|
|
|
2020-09-29 22:08:20 +00:00
|
|
|
WRITE_ONCE(msk->rcv_data_fin_seq,
|
|
|
|
expand_ack(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
|
2020-07-28 22:12:03 +00:00
|
|
|
WRITE_ONCE(msk->rcv_data_fin, 1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:38 +00:00
|
|
|
static bool add_addr_hmac_valid(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_options_received *mp_opt)
|
|
|
|
{
|
|
|
|
u64 hmac = 0;
|
|
|
|
|
|
|
|
if (mp_opt->echo)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (mp_opt->family == MPTCP_ADDR_IPVERSION_4)
|
|
|
|
hmac = add_addr_generate_hmac(msk->remote_key,
|
|
|
|
msk->local_key,
|
|
|
|
mp_opt->addr_id, &mp_opt->addr);
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else
|
|
|
|
hmac = add_addr6_generate_hmac(msk->remote_key,
|
|
|
|
msk->local_key,
|
|
|
|
mp_opt->addr_id, &mp_opt->addr6);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pr_debug("msk=%p, ahmac=%llu, mp_opt->ahmac=%llu\n",
|
|
|
|
msk, (unsigned long long)hmac,
|
|
|
|
(unsigned long long)mp_opt->ahmac);
|
|
|
|
|
|
|
|
return hmac == mp_opt->ahmac;
|
|
|
|
}
|
|
|
|
|
2020-09-24 23:23:02 +00:00
|
|
|
void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
|
2020-01-22 00:56:24 +00:00
|
|
|
{
|
2020-01-22 00:56:32 +00:00
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
2020-03-27 21:48:38 +00:00
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
struct mptcp_options_received mp_opt;
|
2020-01-22 00:56:24 +00:00
|
|
|
struct mptcp_ext *mpext;
|
|
|
|
|
2020-11-27 10:10:27 +00:00
|
|
|
if (__mptcp_check_fallback(msk)) {
|
|
|
|
/* Keep it simple and unconditionally trigger send data cleanup and
|
|
|
|
* pending queue spooling. We will need to acquire the data lock
|
|
|
|
* for more accurate checks, and once the lock is acquired, such
|
|
|
|
* helpers are cheap.
|
|
|
|
*/
|
|
|
|
mptcp_data_lock(subflow->conn);
|
|
|
|
if (mptcp_send_head(subflow->conn))
|
|
|
|
__mptcp_wnd_updated(subflow->conn, sk);
|
|
|
|
__mptcp_data_acked(subflow->conn);
|
|
|
|
mptcp_data_unlock(subflow->conn);
|
2020-06-29 20:26:20 +00:00
|
|
|
return;
|
2020-11-27 10:10:27 +00:00
|
|
|
}
|
2020-06-29 20:26:20 +00:00
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
|
|
|
if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
|
2020-01-22 00:56:32 +00:00
|
|
|
return;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
2020-12-10 22:25:04 +00:00
|
|
|
if (mp_opt.fastclose &&
|
|
|
|
msk->local_key == mp_opt.rcvr_key) {
|
|
|
|
WRITE_ONCE(msk->rcv_fastclose, true);
|
|
|
|
mptcp_schedule_work((struct sock *)msk);
|
|
|
|
}
|
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) {
|
2020-03-27 21:48:38 +00:00
|
|
|
struct mptcp_addr_info addr;
|
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
addr.port = htons(mp_opt.port);
|
|
|
|
addr.id = mp_opt.addr_id;
|
|
|
|
if (mp_opt.family == MPTCP_ADDR_IPVERSION_4) {
|
2020-03-27 21:48:38 +00:00
|
|
|
addr.family = AF_INET;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
addr.addr = mp_opt.addr;
|
2020-03-27 21:48:38 +00:00
|
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
else if (mp_opt.family == MPTCP_ADDR_IPVERSION_6) {
|
2020-03-27 21:48:38 +00:00
|
|
|
addr.family = AF_INET6;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
addr.addr6 = mp_opt.addr6;
|
2020-03-27 21:48:38 +00:00
|
|
|
}
|
|
|
|
#endif
|
2020-09-24 00:29:51 +00:00
|
|
|
if (!mp_opt.echo) {
|
2020-03-27 21:48:38 +00:00
|
|
|
mptcp_pm_add_addr_received(msk, &addr);
|
2020-09-24 00:29:51 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
|
|
|
|
} else {
|
2020-09-24 00:30:02 +00:00
|
|
|
mptcp_pm_del_add_timer(msk, &addr);
|
2020-09-24 00:29:51 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
|
|
|
|
}
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mp_opt.add_addr = 0;
|
2020-03-27 21:48:38 +00:00
|
|
|
}
|
|
|
|
|
2020-09-24 00:29:49 +00:00
|
|
|
if (mp_opt.rm_addr) {
|
|
|
|
mptcp_pm_rm_addr_received(msk, mp_opt.rm_id);
|
|
|
|
mp_opt.rm_addr = 0;
|
|
|
|
}
|
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
if (!mp_opt.dss)
|
2020-01-22 00:56:24 +00:00
|
|
|
return;
|
|
|
|
|
2020-03-27 21:48:42 +00:00
|
|
|
/* we can't wait for recvmsg() to update the ack_seq, otherwise
|
|
|
|
* monodirectional flows will stuck
|
|
|
|
*/
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
if (mp_opt.use_ack)
|
2020-11-16 09:48:13 +00:00
|
|
|
ack_update_msk(msk, sk, &mp_opt);
|
2020-03-27 21:48:42 +00:00
|
|
|
|
2020-07-28 22:12:08 +00:00
|
|
|
/* Zero-data-length packets are dropped by the caller and not
|
|
|
|
* propagated to the MPTCP layer, so the skb extension does not
|
|
|
|
* need to be allocated or populated. DATA_FIN information, if
|
|
|
|
* present, needs to be updated here before the skb is freed.
|
2020-07-28 22:12:06 +00:00
|
|
|
*/
|
|
|
|
if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
|
|
|
|
if (mp_opt.data_fin && mp_opt.data_len == 1 &&
|
2020-09-29 22:08:20 +00:00
|
|
|
mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) &&
|
2020-07-28 22:12:06 +00:00
|
|
|
schedule_work(&msk->work))
|
|
|
|
sock_hold(subflow->conn);
|
2020-07-28 22:12:08 +00:00
|
|
|
|
|
|
|
return;
|
2020-07-28 22:12:06 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
|
|
|
|
if (!mpext)
|
|
|
|
return;
|
|
|
|
|
|
|
|
memset(mpext, 0, sizeof(*mpext));
|
|
|
|
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
if (mp_opt.use_map) {
|
|
|
|
if (mp_opt.mpc_map) {
|
2020-01-22 00:56:31 +00:00
|
|
|
/* this is an MP_CAPABLE carrying MPTCP data
|
|
|
|
* we know this map the first chunk of data
|
|
|
|
*/
|
|
|
|
mptcp_crypto_key_sha(subflow->remote_key, NULL,
|
|
|
|
&mpext->data_seq);
|
|
|
|
mpext->data_seq++;
|
|
|
|
mpext->subflow_seq = 1;
|
|
|
|
mpext->dsn64 = 1;
|
|
|
|
mpext->mpc_map = 1;
|
2020-04-30 13:01:55 +00:00
|
|
|
mpext->data_fin = 0;
|
2020-01-22 00:56:31 +00:00
|
|
|
} else {
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mpext->data_seq = mp_opt.data_seq;
|
|
|
|
mpext->subflow_seq = mp_opt.subflow_seq;
|
|
|
|
mpext->dsn64 = mp_opt.dsn64;
|
|
|
|
mpext->data_fin = mp_opt.data_fin;
|
2020-01-22 00:56:31 +00:00
|
|
|
}
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
mpext->data_len = mp_opt.data_len;
|
2020-01-22 00:56:24 +00:00
|
|
|
mpext->use_map = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-19 19:46:02 +00:00
|
|
|
static void mptcp_set_rwin(const struct tcp_sock *tp)
|
|
|
|
{
|
|
|
|
const struct sock *ssk = (const struct sock *)tp;
|
|
|
|
const struct mptcp_subflow_context *subflow;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
u64 ack_seq;
|
|
|
|
|
|
|
|
subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
msk = mptcp_sk(subflow->conn);
|
|
|
|
|
|
|
|
ack_seq = READ_ONCE(msk->ack_seq) + tp->rcv_wnd;
|
|
|
|
|
|
|
|
if (after64(ack_seq, READ_ONCE(msk->rcv_wnd_sent)))
|
|
|
|
WRITE_ONCE(msk->rcv_wnd_sent, ack_seq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp,
|
|
|
|
struct mptcp_out_options *opts)
|
2020-01-22 00:56:16 +00:00
|
|
|
{
|
2020-01-22 00:56:31 +00:00
|
|
|
if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
|
2020-01-22 00:56:16 +00:00
|
|
|
OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
|
|
|
|
u8 len;
|
|
|
|
|
|
|
|
if (OPTION_MPTCP_MPC_SYN & opts->suboptions)
|
|
|
|
len = TCPOLEN_MPTCP_MPC_SYN;
|
2020-01-22 00:56:18 +00:00
|
|
|
else if (OPTION_MPTCP_MPC_SYNACK & opts->suboptions)
|
|
|
|
len = TCPOLEN_MPTCP_MPC_SYNACK;
|
2020-01-22 00:56:31 +00:00
|
|
|
else if (opts->ext_copy.data_len)
|
|
|
|
len = TCPOLEN_MPTCP_MPC_ACK_DATA;
|
2020-01-22 00:56:16 +00:00
|
|
|
else
|
|
|
|
len = TCPOLEN_MPTCP_MPC_ACK;
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_MP_CAPABLE, len,
|
|
|
|
MPTCP_SUPPORTED_VERSION,
|
|
|
|
MPTCP_CAP_HMAC_SHA256);
|
2020-01-22 00:56:31 +00:00
|
|
|
|
|
|
|
if (!((OPTION_MPTCP_MPC_SYNACK | OPTION_MPTCP_MPC_ACK) &
|
|
|
|
opts->suboptions))
|
|
|
|
goto mp_capable_done;
|
|
|
|
|
2020-01-22 00:56:16 +00:00
|
|
|
put_unaligned_be64(opts->sndr_key, ptr);
|
|
|
|
ptr += 2;
|
2020-01-22 00:56:31 +00:00
|
|
|
if (!((OPTION_MPTCP_MPC_ACK) & opts->suboptions))
|
|
|
|
goto mp_capable_done;
|
|
|
|
|
|
|
|
put_unaligned_be64(opts->rcvr_key, ptr);
|
|
|
|
ptr += 2;
|
|
|
|
if (!opts->ext_copy.data_len)
|
|
|
|
goto mp_capable_done;
|
|
|
|
|
|
|
|
put_unaligned_be32(opts->ext_copy.data_len << 16 |
|
|
|
|
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
|
|
|
|
ptr += 1;
|
2020-01-22 00:56:16 +00:00
|
|
|
}
|
2020-01-22 00:56:23 +00:00
|
|
|
|
2020-01-22 00:56:31 +00:00
|
|
|
mp_capable_done:
|
2020-12-09 23:51:19 +00:00
|
|
|
if ((OPTION_MPTCP_ADD_ADDR
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
| OPTION_MPTCP_ADD_ADDR6
|
|
|
|
#endif
|
|
|
|
) & opts->suboptions) {
|
2020-12-09 23:51:18 +00:00
|
|
|
u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
|
|
|
|
u8 echo = MPTCP_ADDR_ECHO;
|
|
|
|
|
2020-12-09 23:51:19 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (OPTION_MPTCP_ADD_ADDR6 & opts->suboptions)
|
|
|
|
len = TCPOLEN_MPTCP_ADD_ADDR6_BASE;
|
|
|
|
#endif
|
|
|
|
|
2020-12-09 23:51:20 +00:00
|
|
|
if (opts->port)
|
|
|
|
len += TCPOLEN_MPTCP_PORT_LEN;
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
if (opts->ahmac) {
|
2020-12-09 23:51:18 +00:00
|
|
|
len += sizeof(opts->ahmac);
|
|
|
|
echo = 0;
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
|
2020-12-09 23:51:18 +00:00
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
|
|
|
|
len, echo, opts->addr_id);
|
2020-12-09 23:51:19 +00:00
|
|
|
if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) {
|
|
|
|
memcpy((u8 *)ptr, (u8 *)&opts->addr.s_addr, 4);
|
|
|
|
ptr += 1;
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2020-12-09 23:51:19 +00:00
|
|
|
else if (OPTION_MPTCP_ADD_ADDR6 & opts->suboptions) {
|
|
|
|
memcpy((u8 *)ptr, opts->addr6.s6_addr, 16);
|
|
|
|
ptr += 4;
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-12-09 23:51:20 +00:00
|
|
|
if (!opts->port) {
|
|
|
|
if (opts->ahmac) {
|
|
|
|
put_unaligned_be64(opts->ahmac, ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (opts->ahmac) {
|
|
|
|
u8 *bptr = (u8 *)ptr;
|
|
|
|
|
|
|
|
put_unaligned_be16(opts->port, bptr);
|
|
|
|
bptr += 2;
|
|
|
|
put_unaligned_be64(opts->ahmac, bptr);
|
|
|
|
bptr += 8;
|
|
|
|
put_unaligned_be16(TCPOPT_NOP << 8 |
|
|
|
|
TCPOPT_NOP, bptr);
|
|
|
|
|
|
|
|
ptr += 3;
|
|
|
|
} else {
|
|
|
|
put_unaligned_be32(opts->port << 16 |
|
|
|
|
TCPOPT_NOP << 8 |
|
|
|
|
TCPOPT_NOP, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
}
|
2020-03-27 21:48:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OPTION_MPTCP_RM_ADDR & opts->suboptions) {
|
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_RM_ADDR,
|
|
|
|
TCPOLEN_MPTCP_RM_ADDR_BASE,
|
|
|
|
0, opts->rm_id);
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
|
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
|
|
|
|
TCPOLEN_MPTCP_MPJ_SYN,
|
|
|
|
opts->backup, opts->join_id);
|
|
|
|
put_unaligned_be32(opts->token, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
put_unaligned_be32(opts->nonce, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
|
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
|
|
|
|
TCPOLEN_MPTCP_MPJ_SYNACK,
|
|
|
|
opts->backup, opts->join_id);
|
|
|
|
put_unaligned_be64(opts->thmac, ptr);
|
|
|
|
ptr += 2;
|
|
|
|
put_unaligned_be32(opts->nonce, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
|
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
|
|
|
|
TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
|
|
|
|
memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
|
|
|
|
ptr += 5;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:23 +00:00
|
|
|
if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
|
|
|
|
struct mptcp_ext *mpext = &opts->ext_copy;
|
|
|
|
u8 len = TCPOLEN_MPTCP_DSS_BASE;
|
|
|
|
u8 flags = 0;
|
|
|
|
|
|
|
|
if (mpext->use_ack) {
|
2020-05-14 15:53:03 +00:00
|
|
|
flags = MPTCP_DSS_HAS_ACK;
|
|
|
|
if (mpext->ack64) {
|
|
|
|
len += TCPOLEN_MPTCP_DSS_ACK64;
|
|
|
|
flags |= MPTCP_DSS_ACK64;
|
|
|
|
} else {
|
|
|
|
len += TCPOLEN_MPTCP_DSS_ACK32;
|
|
|
|
}
|
2020-01-22 00:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mpext->use_map) {
|
|
|
|
len += TCPOLEN_MPTCP_DSS_MAP64;
|
|
|
|
|
|
|
|
/* Use only 64-bit mapping flags for now, add
|
|
|
|
* support for optional 32-bit mappings later.
|
|
|
|
*/
|
|
|
|
flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
|
|
|
|
if (mpext->data_fin)
|
|
|
|
flags |= MPTCP_DSS_DATA_FIN;
|
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:37 +00:00
|
|
|
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
|
2020-01-22 00:56:23 +00:00
|
|
|
|
|
|
|
if (mpext->use_ack) {
|
2020-05-14 15:53:03 +00:00
|
|
|
if (mpext->ack64) {
|
|
|
|
put_unaligned_be64(mpext->data_ack, ptr);
|
|
|
|
ptr += 2;
|
|
|
|
} else {
|
|
|
|
put_unaligned_be32(mpext->data_ack32, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
}
|
2020-01-22 00:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mpext->use_map) {
|
|
|
|
put_unaligned_be64(mpext->data_seq, ptr);
|
|
|
|
ptr += 2;
|
|
|
|
put_unaligned_be32(mpext->subflow_seq, ptr);
|
|
|
|
ptr += 1;
|
|
|
|
put_unaligned_be32(mpext->data_len << 16 |
|
|
|
|
TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
|
|
|
|
}
|
|
|
|
}
|
2020-11-19 19:46:02 +00:00
|
|
|
|
|
|
|
if (tp)
|
|
|
|
mptcp_set_rwin(tp);
|
2020-01-22 00:56:16 +00:00
|
|
|
}
|