tcp: Remove TCPCT
TCPCT uses option-number 253, reserved for experimental use and should not be used in production environments. Further, TCPCT does not fully implement RFC 6013. As a nice side-effect, removing TCPCT increases TCP's performance for very short flows: Doing an apache-benchmark with -c 100 -n 100000, sending HTTP-requests for files of 1KB size. before this patch: average (among 7 runs) of 20845.5 Requests/Second after: average (among 7 runs) of 21403.6 Requests/Second Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
94d8f2b133
commit
1a2c6181c4
@@ -65,9 +65,6 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS;
|
||||
/* By default, RFC2861 behavior. */
|
||||
int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
|
||||
|
||||
int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
|
||||
EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
|
||||
|
||||
static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
|
||||
int push_one, gfp_t gfp);
|
||||
|
||||
@@ -386,7 +383,6 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
|
||||
#define OPTION_TS (1 << 1)
|
||||
#define OPTION_MD5 (1 << 2)
|
||||
#define OPTION_WSCALE (1 << 3)
|
||||
#define OPTION_COOKIE_EXTENSION (1 << 4)
|
||||
#define OPTION_FAST_OPEN_COOKIE (1 << 8)
|
||||
|
||||
struct tcp_out_options {
|
||||
@@ -400,36 +396,6 @@ struct tcp_out_options {
|
||||
struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */
|
||||
};
|
||||
|
||||
/* The sysctl int routines are generic, so check consistency here.
|
||||
*/
|
||||
static u8 tcp_cookie_size_check(u8 desired)
|
||||
{
|
||||
int cookie_size;
|
||||
|
||||
if (desired > 0)
|
||||
/* previously specified */
|
||||
return desired;
|
||||
|
||||
cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
|
||||
if (cookie_size <= 0)
|
||||
/* no default specified */
|
||||
return 0;
|
||||
|
||||
if (cookie_size <= TCP_COOKIE_MIN)
|
||||
/* value too small, specify minimum */
|
||||
return TCP_COOKIE_MIN;
|
||||
|
||||
if (cookie_size >= TCP_COOKIE_MAX)
|
||||
/* value too large, specify maximum */
|
||||
return TCP_COOKIE_MAX;
|
||||
|
||||
if (cookie_size & 1)
|
||||
/* 8-bit multiple, illegal, fix it */
|
||||
cookie_size++;
|
||||
|
||||
return (u8)cookie_size;
|
||||
}
|
||||
|
||||
/* Write previously computed TCP options to the packet.
|
||||
*
|
||||
* Beware: Something in the Internet is very sensitive to the ordering of
|
||||
@@ -448,27 +414,9 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
|
||||
{
|
||||
u16 options = opts->options; /* mungable copy */
|
||||
|
||||
/* Having both authentication and cookies for security is redundant,
|
||||
* and there's certainly not enough room. Instead, the cookie-less
|
||||
* extension variant is proposed.
|
||||
*
|
||||
* Consider the pessimal case with authentication. The options
|
||||
* could look like:
|
||||
* COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40
|
||||
*/
|
||||
if (unlikely(OPTION_MD5 & options)) {
|
||||
if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
|
||||
*ptr++ = htonl((TCPOPT_COOKIE << 24) |
|
||||
(TCPOLEN_COOKIE_BASE << 16) |
|
||||
(TCPOPT_MD5SIG << 8) |
|
||||
TCPOLEN_MD5SIG);
|
||||
} else {
|
||||
*ptr++ = htonl((TCPOPT_NOP << 24) |
|
||||
(TCPOPT_NOP << 16) |
|
||||
(TCPOPT_MD5SIG << 8) |
|
||||
TCPOLEN_MD5SIG);
|
||||
}
|
||||
options &= ~OPTION_COOKIE_EXTENSION;
|
||||
*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
|
||||
(TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
|
||||
/* overload cookie hash location */
|
||||
opts->hash_location = (__u8 *)ptr;
|
||||
ptr += 4;
|
||||
@@ -497,44 +445,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
|
||||
*ptr++ = htonl(opts->tsecr);
|
||||
}
|
||||
|
||||
/* Specification requires after timestamp, so do it now.
|
||||
*
|
||||
* Consider the pessimal case without authentication. The options
|
||||
* could look like:
|
||||
* MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40
|
||||
*/
|
||||
if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
|
||||
__u8 *cookie_copy = opts->hash_location;
|
||||
u8 cookie_size = opts->hash_size;
|
||||
|
||||
/* 8-bit multiple handled in tcp_cookie_size_check() above,
|
||||
* and elsewhere.
|
||||
*/
|
||||
if (0x2 & cookie_size) {
|
||||
__u8 *p = (__u8 *)ptr;
|
||||
|
||||
/* 16-bit multiple */
|
||||
*p++ = TCPOPT_COOKIE;
|
||||
*p++ = TCPOLEN_COOKIE_BASE + cookie_size;
|
||||
*p++ = *cookie_copy++;
|
||||
*p++ = *cookie_copy++;
|
||||
ptr++;
|
||||
cookie_size -= 2;
|
||||
} else {
|
||||
/* 32-bit multiple */
|
||||
*ptr++ = htonl(((TCPOPT_NOP << 24) |
|
||||
(TCPOPT_NOP << 16) |
|
||||
(TCPOPT_COOKIE << 8) |
|
||||
TCPOLEN_COOKIE_BASE) +
|
||||
cookie_size);
|
||||
}
|
||||
|
||||
if (cookie_size > 0) {
|
||||
memcpy(ptr, cookie_copy, cookie_size);
|
||||
ptr += (cookie_size / 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(OPTION_SACK_ADVERTISE & options)) {
|
||||
*ptr++ = htonl((TCPOPT_NOP << 24) |
|
||||
(TCPOPT_NOP << 16) |
|
||||
@@ -593,11 +503,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
|
||||
struct tcp_md5sig_key **md5)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct tcp_cookie_values *cvp = tp->cookie_values;
|
||||
unsigned int remaining = MAX_TCP_OPTION_SPACE;
|
||||
u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ?
|
||||
tcp_cookie_size_check(cvp->cookie_desired) :
|
||||
0;
|
||||
struct tcp_fastopen_request *fastopen = tp->fastopen_req;
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
@@ -649,52 +555,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
|
||||
tp->syn_fastopen = 1;
|
||||
}
|
||||
}
|
||||
/* Note that timestamps are required by the specification.
|
||||
*
|
||||
* Odd numbers of bytes are prohibited by the specification, ensuring
|
||||
* that the cookie is 16-bit aligned, and the resulting cookie pair is
|
||||
* 32-bit aligned.
|
||||
*/
|
||||
if (*md5 == NULL &&
|
||||
(OPTION_TS & opts->options) &&
|
||||
cookie_size > 0) {
|
||||
int need = TCPOLEN_COOKIE_BASE + cookie_size;
|
||||
|
||||
if (0x2 & need) {
|
||||
/* 32-bit multiple */
|
||||
need += 2; /* NOPs */
|
||||
|
||||
if (need > remaining) {
|
||||
/* try shrinking cookie to fit */
|
||||
cookie_size -= 2;
|
||||
need -= 4;
|
||||
}
|
||||
}
|
||||
while (need > remaining && TCP_COOKIE_MIN <= cookie_size) {
|
||||
cookie_size -= 4;
|
||||
need -= 4;
|
||||
}
|
||||
if (TCP_COOKIE_MIN <= cookie_size) {
|
||||
opts->options |= OPTION_COOKIE_EXTENSION;
|
||||
opts->hash_location = (__u8 *)&cvp->cookie_pair[0];
|
||||
opts->hash_size = cookie_size;
|
||||
|
||||
/* Remember for future incarnations. */
|
||||
cvp->cookie_desired = cookie_size;
|
||||
|
||||
if (cvp->cookie_desired != cvp->cookie_pair_size) {
|
||||
/* Currently use random bytes as a nonce,
|
||||
* assuming these are completely unpredictable
|
||||
* by hostile users of the same system.
|
||||
*/
|
||||
get_random_bytes(&cvp->cookie_pair[0],
|
||||
cookie_size);
|
||||
cvp->cookie_pair_size = cookie_size;
|
||||
}
|
||||
|
||||
remaining -= need;
|
||||
}
|
||||
}
|
||||
return MAX_TCP_OPTION_SPACE - remaining;
|
||||
}
|
||||
|
||||
@@ -704,14 +565,10 @@ static unsigned int tcp_synack_options(struct sock *sk,
|
||||
unsigned int mss, struct sk_buff *skb,
|
||||
struct tcp_out_options *opts,
|
||||
struct tcp_md5sig_key **md5,
|
||||
struct tcp_extend_values *xvp,
|
||||
struct tcp_fastopen_cookie *foc)
|
||||
{
|
||||
struct inet_request_sock *ireq = inet_rsk(req);
|
||||
unsigned int remaining = MAX_TCP_OPTION_SPACE;
|
||||
u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
|
||||
xvp->cookie_plus :
|
||||
0;
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
*md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
|
||||
@@ -759,28 +616,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
|
||||
remaining -= need;
|
||||
}
|
||||
}
|
||||
/* Similar rationale to tcp_syn_options() applies here, too.
|
||||
* If the <SYN> options fit, the same options should fit now!
|
||||
*/
|
||||
if (*md5 == NULL &&
|
||||
ireq->tstamp_ok &&
|
||||
cookie_plus > TCPOLEN_COOKIE_BASE) {
|
||||
int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */
|
||||
|
||||
if (0x2 & need) {
|
||||
/* 32-bit multiple */
|
||||
need += 2; /* NOPs */
|
||||
}
|
||||
if (need <= remaining) {
|
||||
opts->options |= OPTION_COOKIE_EXTENSION;
|
||||
opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE;
|
||||
remaining -= need;
|
||||
} else {
|
||||
/* There's no error return, so flag it. */
|
||||
xvp->cookie_out_never = 1; /* true */
|
||||
opts->hash_size = 0;
|
||||
}
|
||||
}
|
||||
return MAX_TCP_OPTION_SPACE - remaining;
|
||||
}
|
||||
|
||||
@@ -2802,32 +2638,24 @@ int tcp_send_synack(struct sock *sk)
|
||||
* sk: listener socket
|
||||
* dst: dst entry attached to the SYNACK
|
||||
* req: request_sock pointer
|
||||
* rvp: request_values pointer
|
||||
*
|
||||
* Allocate one skb and build a SYNACK packet.
|
||||
* @dst is consumed : Caller should not use it again.
|
||||
*/
|
||||
struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
||||
struct request_sock *req,
|
||||
struct request_values *rvp,
|
||||
struct tcp_fastopen_cookie *foc)
|
||||
{
|
||||
struct tcp_out_options opts;
|
||||
struct tcp_extend_values *xvp = tcp_xv(rvp);
|
||||
struct inet_request_sock *ireq = inet_rsk(req);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
const struct tcp_cookie_values *cvp = tp->cookie_values;
|
||||
struct tcphdr *th;
|
||||
struct sk_buff *skb;
|
||||
struct tcp_md5sig_key *md5;
|
||||
int tcp_header_size;
|
||||
int mss;
|
||||
int s_data_desired = 0;
|
||||
|
||||
if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
|
||||
s_data_desired = cvp->s_data_desired;
|
||||
skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired,
|
||||
sk_gfp_atomic(sk, GFP_ATOMIC));
|
||||
skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
|
||||
if (unlikely(!skb)) {
|
||||
dst_release(dst);
|
||||
return NULL;
|
||||
@@ -2869,9 +2697,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
||||
else
|
||||
#endif
|
||||
TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
||||
tcp_header_size = tcp_synack_options(sk, req, mss,
|
||||
skb, &opts, &md5, xvp, foc)
|
||||
+ sizeof(*th);
|
||||
tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5,
|
||||
foc) + sizeof(*th);
|
||||
|
||||
skb_push(skb, tcp_header_size);
|
||||
skb_reset_transport_header(skb);
|
||||
@@ -2889,40 +2716,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
||||
tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
|
||||
TCPHDR_SYN | TCPHDR_ACK);
|
||||
|
||||
if (OPTION_COOKIE_EXTENSION & opts.options) {
|
||||
if (s_data_desired) {
|
||||
u8 *buf = skb_put(skb, s_data_desired);
|
||||
|
||||
/* copy data directly from the listening socket. */
|
||||
memcpy(buf, cvp->s_data_payload, s_data_desired);
|
||||
TCP_SKB_CB(skb)->end_seq += s_data_desired;
|
||||
}
|
||||
|
||||
if (opts.hash_size > 0) {
|
||||
__u32 workspace[SHA_WORKSPACE_WORDS];
|
||||
u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS];
|
||||
u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1];
|
||||
|
||||
/* Secret recipe depends on the Timestamp, (future)
|
||||
* Sequence and Acknowledgment Numbers, Initiator
|
||||
* Cookie, and others handled by IP variant caller.
|
||||
*/
|
||||
*tail-- ^= opts.tsval;
|
||||
*tail-- ^= tcp_rsk(req)->rcv_isn + 1;
|
||||
*tail-- ^= TCP_SKB_CB(skb)->seq + 1;
|
||||
|
||||
/* recommended */
|
||||
*tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source);
|
||||
*tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */
|
||||
|
||||
sha_transform((__u32 *)&xvp->cookie_bakery[0],
|
||||
(char *)mess,
|
||||
&workspace[0]);
|
||||
opts.hash_location =
|
||||
(__u8 *)&xvp->cookie_bakery[0];
|
||||
}
|
||||
}
|
||||
|
||||
th->seq = htonl(TCP_SKB_CB(skb)->seq);
|
||||
/* XXX data is queued and acked as is. No buffer/window check */
|
||||
th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
|
||||
|
Reference in New Issue
Block a user