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
7878 #define TCP_SACK_SEEN (1 << 0) /*1 = peer is SACK capable, */
7979 #define TCP_DSACK_SEEN (1 << 2) /*1 = DSACK was received from peer*/
8080
81+#if IS_ENABLED(CONFIG_MPTCP)
82+struct 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+
8191 struct tcp_options_received {
8292 /* PAWS/RTTM data */
8393 int ts_recent_stamp;/* Time we stored ts_recent (for aging) */
@@ -95,6 +105,9 @@ struct tcp_options_received { · 11 unmodified lines
95105 u8 num_sacks; /* Number of SACK blocks */
96106 u16 user_mss; /* mss requested by user in ioctl */
97107 u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
108+#if IS_ENABLED(CONFIG_MPTCP)
109+ struct mptcp_options_received mptcp;
110+#endif
98111 };
99112
100113 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) · 3 unmodified lines
104117 #if IS_ENABLED(CONFIG_SMC)
105118 rx_opt->smc_ok = 0;
106119 #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
107125 }
108126
109127 /* 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
99 #define __NET_MPTCP_H
1010
1111 #include <linux/skbuff.h>
12+#include <linux/tcp.h>
1213 #include <linux/types.h>
1314
1415 /* MPTCP sk_buff extension data */
@@ -26,10 +27,22 @@ struct mptcp_ext { · 11 unmodified lines
2627 /* one byte hole */
2728 };
2829
30+struct mptcp_out_options {
31+#if IS_ENABLED(CONFIG_MPTCP)
32+ u16 suboptions;
33+ u64 sndr_key;
34+ u64 rcvr_key;
35+#endif
36+};
37+
2938 #ifdef CONFIG_MPTCP
3039
3140 void mptcp_init(void);
3241
42+void mptcp_parse_option(const unsigned char *ptr, int opsize,
43+ struct tcp_options_received *opt_rx);
44+void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts);
45+
3346 /* move the skb extension owership, with the assumption that 'to' is
3447 * newly allocated
3548 */
@@ -76,6 +89,11 @@ static inline void mptcp_init(void) · 40 unmodified lines
7689 {
7790 }
7891
92+static inline void mptcp_parse_option(const unsigned char *ptr, int opsize,
93+ struct tcp_options_received *opt_rx)
94+{
95+}
96+
7997 static inline void mptcp_skb_ext_move(struct sk_buff *to,
8098 const struct sk_buff *from)
8199 {
net/ipv4/tcp_input.c+5−0
@@ -79,6 +79,7 @@ · 78 unmodified lines
7979 #include <trace/events/tcp.h>
8080 #include <linux/jump_label_ratelimit.h>
8181 #include <net/busy_poll.h>
82+#include <net/mptcp.h>
8283
8384 int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
8485
@@ -3924,6 +3925,10 @@ void tcp_parse_options(const struct net *net, · 3839 unmodified lines
39243925 */
39253926 break;
39263927 #endif
3928+ case TCPOPT_MPTCP:
3929+ mptcp_parse_option(ptr, opsize, opt_rx);
3930+ break;
3931+
39273932 case TCPOPT_FASTOPEN:
39283933 tcp_parse_fastopen_option(
39293934 opsize - TCPOLEN_FASTOPEN_BASE,
net/ipv4/tcp_output.c+13−0
@@ -38,6 +38,7 @@ · 37 unmodified lines
3838 #define pr_fmt(fmt) "TCP: " fmt
3939
4040 #include <net/tcp.h>
41+#include <net/mptcp.h>
4142
4243 #include <linux/compiler.h>
4344 #include <linux/gfp.h>
@@ -414,6 +415,7 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp) · 370 unmodified lines
414415 #define OPTION_WSCALE (1 << 3)
415416 #define OPTION_FAST_OPEN_COOKIE (1 << 8)
416417 #define OPTION_SMC (1 << 9)
418+#define OPTION_MPTCP (1 << 10)
417419
418420 static void smc_options_write(__be32 *ptr, u16 *options)
419421 {
@@ -439,8 +441,17 @@ struct tcp_out_options { · 19 unmodified lines
439441 __u8 *hash_location; /* temporary pointer, overloaded */
440442 __u32 tsval, tsecr; /* need to include OPTION_TS */
441443 struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */
444+ struct mptcp_out_options mptcp;
442445 };
443446
447+static 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+
444455 /* Write previously computed TCP options to the packet.
445456 *
446457 * 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
549560 }
550561
551562 smc_options_write(ptr, &options);
563+
564+ mptcp_options_write(ptr, opts);
552565 }
553566
554567 static void smc_set_option(const struct tcp_sock *tp,
net/mptcp/Makefile+1−1
@@ -1,4 +1,4 @@
11 # SPDX-License-Identifier: GPL-2.0
22 obj-$(CONFIG_MPTCP) += mptcp.o
33
4−mptcp-y := protocol.o
4+mptcp-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+
12+void 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+
75+void 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
77 #ifndef __MPTCP_PROTOCOL_H
88 #define __MPTCP_PROTOCOL_H
99
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+
1039 /* MPTCP connection sock */
1140 struct mptcp_sock {
1241 /* inet_connection_sock must be the first member */