History

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.

Peter Krystad committed 6 years ago

Commit eda7acd1 parent f870fa07 files · +181 −1Browse files

Unified · Split

7 files
  1. include/linux/tcp.h +18 −0
  2. include/net/mptcp.h +18 −0
  3. net/ipv4/tcp_input.c +5 −0
  4. net/ipv4/tcp_output.c +13 −0
  5. net/mptcp/Makefile +1 −1
  6. net/mptcp/options.c +97 −0
  7. net/mptcp/protocol.h +29 −0
include/linux/tcp.h+18−0
@@ -78,6 +78,16 @@ struct tcp_sack_block { · 77 unmodified lines
78#define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */78#define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */
79#define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/79#define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/
80 80
81#if IS_ENABLED(CONFIG_MPTCP)
82struct mptcp_options_received {
83 u64 sndr_key;
84 u64 rcvr_key;
85 u8 mp_capable : 1,
86 mp_join : 1,
87 dss : 1;
88};
89#endif
90
81struct tcp_options_received {91struct tcp_options_received {
82/* PAWS/RTTM data */92/* PAWS/RTTM data */
83 int ts_recent_stamp;/* Time we stored ts_recent (for aging) */93 int ts_recent_stamp;/* Time we stored ts_recent (for aging) */
@@ -95,6 +105,9 @@ struct tcp_options_received { · 11 unmodified lines
95 u8 num_sacks; /* Number of SACK blocks */105 u8 num_sacks; /* Number of SACK blocks */
96 u16 user_mss; /* mss requested by user in ioctl */106 u16 user_mss; /* mss requested by user in ioctl */
97 u16 mss_clamp; /* Maximal mss, negotiated at connection setup */107 u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
108#if IS_ENABLED(CONFIG_MPTCP)
109 struct mptcp_options_received mptcp;
110#endif
98};111};
99 112
100static inline void tcp_clear_options(struct tcp_options_received *rx_opt)113static 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) · 3 unmodified lines
104#if IS_ENABLED(CONFIG_SMC)117#if IS_ENABLED(CONFIG_SMC)
105 rx_opt->smc_ok = 0;118 rx_opt->smc_ok = 0;
106#endif119#endif
120#if IS_ENABLED(CONFIG_MPTCP)
121 rx_opt->mptcp.mp_capable = 0;
122 rx_opt->mptcp.mp_join = 0;
123 rx_opt->mptcp.dss = 0;
124#endif
107}125}
108 126
109/* This is the max number of SACKS that we'll generate and process. It's safe127/* This is the max number of SACKS that we'll generate and process. It's safe
include/net/mptcp.h+18−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#define __NET_MPTCP_H9#define __NET_MPTCP_H
10 10
11#include <linux/skbuff.h>11#include <linux/skbuff.h>
12#include <linux/tcp.h>
12#include <linux/types.h>13#include <linux/types.h>
13 14
14/* MPTCP sk_buff extension data */15/* MPTCP sk_buff extension data */
@@ -26,10 +27,22 @@ struct mptcp_ext { · 11 unmodified lines
26 /* one byte hole */27 /* one byte hole */
27};28};
28 29
30struct mptcp_out_options {
31#if IS_ENABLED(CONFIG_MPTCP)
32 u16 suboptions;
33 u64 sndr_key;
34 u64 rcvr_key;
35#endif
36};
37
29#ifdef CONFIG_MPTCP38#ifdef CONFIG_MPTCP
30 39
31void mptcp_init(void);40void mptcp_init(void);
32 41
42void mptcp_parse_option(const unsigned char *ptr, int opsize,
43 struct tcp_options_received *opt_rx);
44void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts);
45
33/* move the skb extension owership, with the assumption that 'to' is46/* move the skb extension owership, with the assumption that 'to' is
34 * newly allocated47 * newly allocated
35 */48 */
@@ -76,6 +89,11 @@ static inline void mptcp_init(void) · 40 unmodified lines
76{89{
77}90}
78 91
92static inline void mptcp_parse_option(const unsigned char *ptr, int opsize,
93 struct tcp_options_received *opt_rx)
94{
95}
96
79static inline void mptcp_skb_ext_move(struct sk_buff *to,97static inline void mptcp_skb_ext_move(struct sk_buff *to,
80 const struct sk_buff *from)98 const struct sk_buff *from)
81{99{
net/ipv4/tcp_input.c+5−0
@@ -79,6 +79,7 @@ · 78 unmodified lines
79#include <trace/events/tcp.h>79#include <trace/events/tcp.h>
80#include <linux/jump_label_ratelimit.h>80#include <linux/jump_label_ratelimit.h>
81#include <net/busy_poll.h>81#include <net/busy_poll.h>
82#include <net/mptcp.h>
82 83
83int sysctl_tcp_max_orphans __read_mostly = NR_FILE;84int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
84 85
@@ -3924,6 +3925,10 @@ void tcp_parse_options(const struct net *net, · 3839 unmodified lines
3924 */3925 */
3925 break;3926 break;
3926#endif3927#endif
3928 case TCPOPT_MPTCP:
3929 mptcp_parse_option(ptr, opsize, opt_rx);
3930 break;
3931
3927 case TCPOPT_FASTOPEN:3932 case TCPOPT_FASTOPEN:
3928 tcp_parse_fastopen_option(3933 tcp_parse_fastopen_option(
3929 opsize - TCPOLEN_FASTOPEN_BASE,3934 opsize - TCPOLEN_FASTOPEN_BASE,
net/ipv4/tcp_output.c+13−0
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#define pr_fmt(fmt) "TCP: " fmt38#define pr_fmt(fmt) "TCP: " fmt
39 39
40#include <net/tcp.h>40#include <net/tcp.h>
41#include <net/mptcp.h>
41 42
42#include <linux/compiler.h>43#include <linux/compiler.h>
43#include <linux/gfp.h>44#include <linux/gfp.h>
@@ -414,6 +415,7 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp) · 370 unmodified lines
414#define OPTION_WSCALE (1 << 3)415#define OPTION_WSCALE (1 << 3)
415#define OPTION_FAST_OPEN_COOKIE (1 << 8)416#define OPTION_FAST_OPEN_COOKIE (1 << 8)
416#define OPTION_SMC (1 << 9)417#define OPTION_SMC (1 << 9)
418#define OPTION_MPTCP (1 << 10)
417 419
418static void smc_options_write(__be32 *ptr, u16 *options)420static void smc_options_write(__be32 *ptr, u16 *options)
419{421{
@@ -439,8 +441,17 @@ struct tcp_out_options { · 19 unmodified lines
439 __u8 *hash_location; /* temporary pointer, overloaded */441 __u8 *hash_location; /* temporary pointer, overloaded */
440 __u32 tsval, tsecr; /* need to include OPTION_TS */442 __u32 tsval, tsecr; /* need to include OPTION_TS */
441 struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */443 struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */
444 struct mptcp_out_options mptcp;
442};445};
443 446
447static void mptcp_options_write(__be32 *ptr, struct tcp_out_options *opts)
448{
449#if IS_ENABLED(CONFIG_MPTCP)
450 if (unlikely(OPTION_MPTCP & opts->options))
451 mptcp_write_options(ptr, &opts->mptcp);
452#endif
453}
454
444/* Write previously computed TCP options to the packet.455/* Write previously computed TCP options to the packet.
445 *456 *
446 * Beware: Something in the Internet is very sensitive to the ordering of457 * 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, · 102 unmodified lines
549 }560 }
550 561
551 smc_options_write(ptr, &options);562 smc_options_write(ptr, &options);
563
564 mptcp_options_write(ptr, opts);
552}565}
553 566
554static void smc_set_option(const struct tcp_sock *tp,567static void smc_set_option(const struct tcp_sock *tp,
net/mptcp/Makefile+1−1
@@ -1,4 +1,4 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_MPTCP) += mptcp.o2obj-$(CONFIG_MPTCP) += mptcp.o
3 3
4mptcp-y := protocol.o4mptcp-y := protocol.o options.o
net/mptcp/options.c+97−0
@@ -0,0 +1,97 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Multipath TCP
3 *
4 * Copyright (c) 2017 - 2019, Intel Corporation.
5 */
6
7#include <linux/kernel.h>
8#include <net/tcp.h>
9#include <net/mptcp.h>
10#include "protocol.h"
11
12void mptcp_parse_option(const unsigned char *ptr, int opsize,
13 struct tcp_options_received *opt_rx)
14{
15 struct mptcp_options_received *mp_opt = &opt_rx->mptcp;
16 u8 subtype = *ptr >> 4;
17 u8 version;
18 u8 flags;
19
20 switch (subtype) {
21 case MPTCPOPT_MP_CAPABLE:
22 if (opsize != TCPOLEN_MPTCP_MPC_SYN &&
23 opsize != TCPOLEN_MPTCP_MPC_ACK)
24 break;
25
26 version = *ptr++ & MPTCP_VERSION_MASK;
27 if (version != MPTCP_SUPPORTED_VERSION)
28 break;
29
30 flags = *ptr++;
31 if (!((flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) ||
32 (flags & MPTCP_CAP_EXTENSIBILITY))
33 break;
34
35 /* RFC 6824, Section 3.1:
36 * "For the Checksum Required bit (labeled "A"), if either
37 * host requires the use of checksums, checksums MUST be used.
38 * In other words, the only way for checksums not to be used
39 * is if both hosts in their SYNs set A=0."
40 *
41 * Section 3.3.0:
42 * "If a checksum is not present when its use has been
43 * negotiated, the receiver MUST close the subflow with a RST as
44 * it is considered broken."
45 *
46 * We don't implement DSS checksum - fall back to TCP.
47 */
48 if (flags & MPTCP_CAP_CHECKSUM_REQD)
49 break;
50
51 mp_opt->mp_capable = 1;
52 mp_opt->sndr_key = get_unaligned_be64(ptr);
53 ptr += 8;
54
55 if (opsize == TCPOLEN_MPTCP_MPC_ACK) {
56 mp_opt->rcvr_key = get_unaligned_be64(ptr);
57 ptr += 8;
58 pr_debug("MP_CAPABLE sndr=%llu, rcvr=%llu",
59 mp_opt->sndr_key, mp_opt->rcvr_key);
60 } else {
61 pr_debug("MP_CAPABLE sndr=%llu", mp_opt->sndr_key);
62 }
63 break;
64
65 case MPTCPOPT_DSS:
66 pr_debug("DSS");
67 mp_opt->dss = 1;
68 break;
69
70 default:
71 break;
72 }
73}
74
75void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
76{
77 if ((OPTION_MPTCP_MPC_SYN |
78 OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
79 u8 len;
80
81 if (OPTION_MPTCP_MPC_SYN & opts->suboptions)
82 len = TCPOLEN_MPTCP_MPC_SYN;
83 else
84 len = TCPOLEN_MPTCP_MPC_ACK;
85
86 *ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) |
87 (MPTCPOPT_MP_CAPABLE << 12) |
88 (MPTCP_SUPPORTED_VERSION << 8) |
89 MPTCP_CAP_HMAC_SHA1);
90 put_unaligned_be64(opts->sndr_key, ptr);
91 ptr += 2;
92 if (OPTION_MPTCP_MPC_ACK & opts->suboptions) {
93 put_unaligned_be64(opts->rcvr_key, ptr);
94 ptr += 2;
95 }
96 }
97}
net/mptcp/protocol.h+29−0
@@ -7,6 +7,35 @@ · 6 unmodified lines
7#ifndef __MPTCP_PROTOCOL_H7#ifndef __MPTCP_PROTOCOL_H
8#define __MPTCP_PROTOCOL_H8#define __MPTCP_PROTOCOL_H
9 9
10#define MPTCP_SUPPORTED_VERSION 0
11
12/* MPTCP option bits */
13#define OPTION_MPTCP_MPC_SYN BIT(0)
14#define OPTION_MPTCP_MPC_SYNACK BIT(1)
15#define OPTION_MPTCP_MPC_ACK BIT(2)
16
17/* MPTCP option subtypes */
18#define MPTCPOPT_MP_CAPABLE 0
19#define MPTCPOPT_MP_JOIN 1
20#define MPTCPOPT_DSS 2
21#define MPTCPOPT_ADD_ADDR 3
22#define MPTCPOPT_RM_ADDR 4
23#define MPTCPOPT_MP_PRIO 5
24#define MPTCPOPT_MP_FAIL 6
25#define MPTCPOPT_MP_FASTCLOSE 7
26
27/* MPTCP suboption lengths */
28#define TCPOLEN_MPTCP_MPC_SYN 12
29#define TCPOLEN_MPTCP_MPC_SYNACK 12
30#define TCPOLEN_MPTCP_MPC_ACK 20
31
32/* MPTCP MP_CAPABLE flags */
33#define MPTCP_VERSION_MASK (0x0F)
34#define MPTCP_CAP_CHECKSUM_REQD BIT(7)
35#define MPTCP_CAP_EXTENSIBILITY BIT(6)
36#define MPTCP_CAP_HMAC_SHA1 BIT(0)
37#define MPTCP_CAP_FLAG_MASK (0x3F)
38
10/* MPTCP connection sock */39/* MPTCP connection sock */
11struct mptcp_sock {40struct mptcp_sock {
12 /* inet_connection_sock must be the first member */41 /* inet_connection_sock must be the first member */