mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 11:00:56 +07:00
mptcp: Handle MPTCP TCP options
Add hooks to parse and format the MP_CAPABLE option. This option is handled according to MPTCP version 0 (RFC6824). MPTCP version 1 MP_CAPABLE (RFC6824bis/RFC8684) will be added later in coordination with related code changes. Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net> Co-developed-by: Florian Westphal <fw@strlen.de> Signed-off-by: Florian Westphal <fw@strlen.de> Co-developed-by: Davide Caratti <dcaratti@redhat.com> Signed-off-by: Davide Caratti <dcaratti@redhat.com> Signed-off-by: Peter Krystad <peter.krystad@linux.intel.com> Signed-off-by: Christoph Paasch <cpaasch@apple.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f870fa0b57
commit
eda7acddf8
@ -78,6 +78,16 @@ struct tcp_sack_block {
|
||||
#define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */
|
||||
#define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
struct mptcp_options_received {
|
||||
u64 sndr_key;
|
||||
u64 rcvr_key;
|
||||
u8 mp_capable : 1,
|
||||
mp_join : 1,
|
||||
dss : 1;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct tcp_options_received {
|
||||
/* PAWS/RTTM data */
|
||||
int ts_recent_stamp;/* Time we stored ts_recent (for aging) */
|
||||
@ -95,6 +105,9 @@ struct tcp_options_received {
|
||||
u8 num_sacks; /* Number of SACK blocks */
|
||||
u16 user_mss; /* mss requested by user in ioctl */
|
||||
u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
struct mptcp_options_received mptcp;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
|
||||
@ -104,6 +117,11 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
|
||||
#if IS_ENABLED(CONFIG_SMC)
|
||||
rx_opt->smc_ok = 0;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
rx_opt->mptcp.mp_capable = 0;
|
||||
rx_opt->mptcp.mp_join = 0;
|
||||
rx_opt->mptcp.dss = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is the max number of SACKS that we'll generate and process. It's safe
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define __NET_MPTCP_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MPTCP sk_buff extension data */
|
||||
@ -26,10 +27,22 @@ struct mptcp_ext {
|
||||
/* one byte hole */
|
||||
};
|
||||
|
||||
struct mptcp_out_options {
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
u16 suboptions;
|
||||
u64 sndr_key;
|
||||
u64 rcvr_key;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MPTCP
|
||||
|
||||
void mptcp_init(void);
|
||||
|
||||
void mptcp_parse_option(const unsigned char *ptr, int opsize,
|
||||
struct tcp_options_received *opt_rx);
|
||||
void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts);
|
||||
|
||||
/* move the skb extension owership, with the assumption that 'to' is
|
||||
* newly allocated
|
||||
*/
|
||||
@ -76,6 +89,11 @@ static inline void mptcp_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mptcp_parse_option(const unsigned char *ptr, int opsize,
|
||||
struct tcp_options_received *opt_rx)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mptcp_skb_ext_move(struct sk_buff *to,
|
||||
const struct sk_buff *from)
|
||||
{
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include <trace/events/tcp.h>
|
||||
#include <linux/jump_label_ratelimit.h>
|
||||
#include <net/busy_poll.h>
|
||||
#include <net/mptcp.h>
|
||||
|
||||
int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
|
||||
|
||||
@ -3924,6 +3925,10 @@ void tcp_parse_options(const struct net *net,
|
||||
*/
|
||||
break;
|
||||
#endif
|
||||
case TCPOPT_MPTCP:
|
||||
mptcp_parse_option(ptr, opsize, opt_rx);
|
||||
break;
|
||||
|
||||
case TCPOPT_FASTOPEN:
|
||||
tcp_parse_fastopen_option(
|
||||
opsize - TCPOLEN_FASTOPEN_BASE,
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define pr_fmt(fmt) "TCP: " fmt
|
||||
|
||||
#include <net/tcp.h>
|
||||
#include <net/mptcp.h>
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/gfp.h>
|
||||
@ -414,6 +415,7 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
|
||||
#define OPTION_WSCALE (1 << 3)
|
||||
#define OPTION_FAST_OPEN_COOKIE (1 << 8)
|
||||
#define OPTION_SMC (1 << 9)
|
||||
#define OPTION_MPTCP (1 << 10)
|
||||
|
||||
static void smc_options_write(__be32 *ptr, u16 *options)
|
||||
{
|
||||
@ -439,8 +441,17 @@ struct tcp_out_options {
|
||||
__u8 *hash_location; /* temporary pointer, overloaded */
|
||||
__u32 tsval, tsecr; /* need to include OPTION_TS */
|
||||
struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */
|
||||
struct mptcp_out_options mptcp;
|
||||
};
|
||||
|
||||
static void mptcp_options_write(__be32 *ptr, struct tcp_out_options *opts)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_MPTCP)
|
||||
if (unlikely(OPTION_MPTCP & opts->options))
|
||||
mptcp_write_options(ptr, &opts->mptcp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Write previously computed TCP options to the packet.
|
||||
*
|
||||
* Beware: Something in the Internet is very sensitive to the ordering of
|
||||
@ -549,6 +560,8 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
|
||||
}
|
||||
|
||||
smc_options_write(ptr, &options);
|
||||
|
||||
mptcp_options_write(ptr, opts);
|
||||
}
|
||||
|
||||
static void smc_set_option(const struct tcp_sock *tp,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_MPTCP) += mptcp.o
|
||||
|
||||
mptcp-y := protocol.o
|
||||
mptcp-y := protocol.o options.o
|
||||
|
97
net/mptcp/options.c
Normal file
97
net/mptcp/options.c
Normal file
@ -0,0 +1,97 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Multipath TCP
|
||||
*
|
||||
* Copyright (c) 2017 - 2019, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/mptcp.h>
|
||||
#include "protocol.h"
|
||||
|
||||
void mptcp_parse_option(const unsigned char *ptr, int opsize,
|
||||
struct tcp_options_received *opt_rx)
|
||||
{
|
||||
struct mptcp_options_received *mp_opt = &opt_rx->mptcp;
|
||||
u8 subtype = *ptr >> 4;
|
||||
u8 version;
|
||||
u8 flags;
|
||||
|
||||
switch (subtype) {
|
||||
case MPTCPOPT_MP_CAPABLE:
|
||||
if (opsize != TCPOLEN_MPTCP_MPC_SYN &&
|
||||
opsize != TCPOLEN_MPTCP_MPC_ACK)
|
||||
break;
|
||||
|
||||
version = *ptr++ & MPTCP_VERSION_MASK;
|
||||
if (version != MPTCP_SUPPORTED_VERSION)
|
||||
break;
|
||||
|
||||
flags = *ptr++;
|
||||
if (!((flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) ||
|
||||
(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;
|
||||
mp_opt->sndr_key = get_unaligned_be64(ptr);
|
||||
ptr += 8;
|
||||
|
||||
if (opsize == TCPOLEN_MPTCP_MPC_ACK) {
|
||||
mp_opt->rcvr_key = get_unaligned_be64(ptr);
|
||||
ptr += 8;
|
||||
pr_debug("MP_CAPABLE sndr=%llu, rcvr=%llu",
|
||||
mp_opt->sndr_key, mp_opt->rcvr_key);
|
||||
} else {
|
||||
pr_debug("MP_CAPABLE sndr=%llu", mp_opt->sndr_key);
|
||||
}
|
||||
break;
|
||||
|
||||
case MPTCPOPT_DSS:
|
||||
pr_debug("DSS");
|
||||
mp_opt->dss = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
|
||||
{
|
||||
if ((OPTION_MPTCP_MPC_SYN |
|
||||
OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
|
||||
u8 len;
|
||||
|
||||
if (OPTION_MPTCP_MPC_SYN & opts->suboptions)
|
||||
len = TCPOLEN_MPTCP_MPC_SYN;
|
||||
else
|
||||
len = TCPOLEN_MPTCP_MPC_ACK;
|
||||
|
||||
*ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) |
|
||||
(MPTCPOPT_MP_CAPABLE << 12) |
|
||||
(MPTCP_SUPPORTED_VERSION << 8) |
|
||||
MPTCP_CAP_HMAC_SHA1);
|
||||
put_unaligned_be64(opts->sndr_key, ptr);
|
||||
ptr += 2;
|
||||
if (OPTION_MPTCP_MPC_ACK & opts->suboptions) {
|
||||
put_unaligned_be64(opts->rcvr_key, ptr);
|
||||
ptr += 2;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,35 @@
|
||||
#ifndef __MPTCP_PROTOCOL_H
|
||||
#define __MPTCP_PROTOCOL_H
|
||||
|
||||
#define MPTCP_SUPPORTED_VERSION 0
|
||||
|
||||
/* MPTCP option bits */
|
||||
#define OPTION_MPTCP_MPC_SYN BIT(0)
|
||||
#define OPTION_MPTCP_MPC_SYNACK BIT(1)
|
||||
#define OPTION_MPTCP_MPC_ACK BIT(2)
|
||||
|
||||
/* MPTCP option subtypes */
|
||||
#define MPTCPOPT_MP_CAPABLE 0
|
||||
#define MPTCPOPT_MP_JOIN 1
|
||||
#define MPTCPOPT_DSS 2
|
||||
#define MPTCPOPT_ADD_ADDR 3
|
||||
#define MPTCPOPT_RM_ADDR 4
|
||||
#define MPTCPOPT_MP_PRIO 5
|
||||
#define MPTCPOPT_MP_FAIL 6
|
||||
#define MPTCPOPT_MP_FASTCLOSE 7
|
||||
|
||||
/* MPTCP suboption lengths */
|
||||
#define TCPOLEN_MPTCP_MPC_SYN 12
|
||||
#define TCPOLEN_MPTCP_MPC_SYNACK 12
|
||||
#define TCPOLEN_MPTCP_MPC_ACK 20
|
||||
|
||||
/* MPTCP MP_CAPABLE flags */
|
||||
#define MPTCP_VERSION_MASK (0x0F)
|
||||
#define MPTCP_CAP_CHECKSUM_REQD BIT(7)
|
||||
#define MPTCP_CAP_EXTENSIBILITY BIT(6)
|
||||
#define MPTCP_CAP_HMAC_SHA1 BIT(0)
|
||||
#define MPTCP_CAP_FLAG_MASK (0x3F)
|
||||
|
||||
/* MPTCP connection sock */
|
||||
struct mptcp_sock {
|
||||
/* inet_connection_sock must be the first member */
|
||||
|
Loading…
Reference in New Issue
Block a user