28f7f8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ecb9bb
From: Josef Bacik <jbacik@fb.com>
ecb9bb
Date: Wed, 12 Aug 2015 08:57:55 -0700
28f7f8
Subject: [PATCH] tcp: add window scaling support
ecb9bb
ecb9bb
Sometimes we have to provision boxes across regions, such as California to
ecb9bb
Sweden.  The http server has a 10 minute timeout, so if we can't get our 250mb
ecb9bb
image transferred fast enough our provisioning fails, which is not ideal.  So
ecb9bb
add tcp window scaling on open connections and set the window size to 1mb.  With
ecb9bb
this change we're able to get higher sustained transfers between regions and can
ecb9bb
transfer our image in well below 10 minutes.  Without this patch we'd time out
ecb9bb
every time halfway through the transfer.  Thanks,
ecb9bb
ecb9bb
Signed-off-by: Josef Bacik <jbacik@fb.com>
ecb9bb
---
ecb9bb
 grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++-------------
ecb9bb
 1 file changed, 29 insertions(+), 13 deletions(-)
ecb9bb
ecb9bb
diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c
28f7f8
index fa29a2afc6c..c22ef033d6e 100644
ecb9bb
--- a/grub-core/net/tcp.c
ecb9bb
+++ b/grub-core/net/tcp.c
ecb9bb
@@ -106,6 +106,18 @@ struct tcphdr
ecb9bb
   grub_uint16_t urgent;
ecb9bb
 } GRUB_PACKED;
ecb9bb
 
ecb9bb
+struct tcp_scale_opt {
ecb9bb
+  grub_uint8_t kind;
ecb9bb
+  grub_uint8_t length;
ecb9bb
+  grub_uint8_t scale;
ecb9bb
+} GRUB_PACKED;
ecb9bb
+
ecb9bb
+struct tcp_synhdr {
ecb9bb
+  struct tcphdr tcphdr;
ecb9bb
+  struct tcp_scale_opt scale_opt;
ecb9bb
+  grub_uint8_t padding;
ecb9bb
+};
ecb9bb
+
ecb9bb
 struct tcp_pseudohdr
ecb9bb
 {
ecb9bb
   grub_uint32_t src;
ecb9bb
@@ -555,7 +567,7 @@ grub_net_tcp_open (char *server,
ecb9bb
   grub_net_tcp_socket_t socket;
ecb9bb
   static grub_uint16_t in_port = 21550;
ecb9bb
   struct grub_net_buff *nb;
ecb9bb
-  struct tcphdr *tcph;
ecb9bb
+  struct tcp_synhdr *tcph;
ecb9bb
   int i;
ecb9bb
   grub_uint8_t *nbd;
ecb9bb
   grub_net_link_level_address_t ll_target_addr;
ecb9bb
@@ -617,20 +629,24 @@ grub_net_tcp_open (char *server,
ecb9bb
     }
ecb9bb
 
ecb9bb
   tcph = (void *) nb->data;
ecb9bb
+  grub_memset(tcph, 0, sizeof (*tcph));
ecb9bb
   socket->my_start_seq = grub_get_time_ms ();
ecb9bb
   socket->my_cur_seq = socket->my_start_seq + 1;
ecb9bb
-  socket->my_window = 8192;
ecb9bb
-  tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
ecb9bb
-  tcph->ack = grub_cpu_to_be32_compile_time (0);
ecb9bb
-  tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
ecb9bb
-  tcph->window = grub_cpu_to_be16 (socket->my_window);
ecb9bb
-  tcph->urgent = 0;
ecb9bb
-  tcph->src = grub_cpu_to_be16 (socket->in_port);
ecb9bb
-  tcph->dst = grub_cpu_to_be16 (socket->out_port);
ecb9bb
-  tcph->checksum = 0;
ecb9bb
-  tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
ecb9bb
-						   &socket->inf->address,
ecb9bb
-						   &socket->out_nla);
ecb9bb
+  socket->my_window = 32768;
ecb9bb
+  tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq);
ecb9bb
+  tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0);
ecb9bb
+  tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN);
ecb9bb
+  tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window);
ecb9bb
+  tcph->tcphdr.urgent = 0;
ecb9bb
+  tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port);
ecb9bb
+  tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port);
ecb9bb
+  tcph->tcphdr.checksum = 0;
ecb9bb
+  tcph->scale_opt.kind = 3;
ecb9bb
+  tcph->scale_opt.length = 3;
ecb9bb
+  tcph->scale_opt.scale = 5;
ecb9bb
+  tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
ecb9bb
+							  &socket->inf->address,
ecb9bb
+							  &socket->out_nla);
ecb9bb
 
ecb9bb
   tcp_socket_register (socket);
ecb9bb