tcp: enable gso in tcp hoststack
[vpp.git] / src / vnet / tcp / tcp_output.c
index ff281b5..15aa857 100644 (file)
@@ -2126,10 +2126,32 @@ tcp_output_push_ip (vlib_main_t * vm, vlib_buffer_t * b0,
       b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
       vnet_buffer (b0)->l3_hdr_offset = (u8 *) ih0 - b0->data;
       vnet_buffer (b0)->l4_hdr_offset = (u8 *) th0 - b0->data;
+      b0->flags |=
+       VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
       th0->checksum = 0;
     }
 }
 
+always_inline void
+tcp_check_if_gso (tcp_connection_t * tc, vlib_buffer_t * b)
+{
+  if (PREDICT_TRUE (!(b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)))
+    return;
+  u16 data_len =
+    b->current_length + b->total_length_not_including_first_buffer -
+    sizeof (tcp_header_t) - tc->snd_opts_len;
+
+  if (data_len > tc->snd_mss)
+    {
+      ASSERT ((b->flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID) != 0);
+      ASSERT ((b->flags & VNET_BUFFER_F_L4_HDR_OFFSET_VALID) != 0);
+      b->flags |= VNET_BUFFER_F_GSO;
+      vnet_buffer2 (b)->gso_l4_hdr_sz =
+       sizeof (tcp_header_t) + tc->snd_opts_len;
+      vnet_buffer2 (b)->gso_size = tc->snd_mss;
+    }
+}
+
 always_inline void
 tcp_output_handle_packet (tcp_connection_t * tc0, vlib_buffer_t * b0,
                          vlib_node_runtime_t * error_node, u16 * next0,
@@ -2213,6 +2235,9 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          tcp_output_push_ip (vm, b[0], tc0, is_ip4);
          tcp_output_push_ip (vm, b[1], tc1, is_ip4);
 
+         tcp_check_if_gso (tc0, b[0]);
+         tcp_check_if_gso (tc1, b[1]);
+
          tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
          tcp_output_handle_packet (tc1, b[1], error_node, &next[1], is_ip4);
        }
@@ -2221,6 +2246,7 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          if (tc0 != 0)
            {
              tcp_output_push_ip (vm, b[0], tc0, is_ip4);
+             tcp_check_if_gso (tc0, b[0]);
              tcp_output_handle_packet (tc0, b[0], error_node, &next[0],
                                        is_ip4);
            }
@@ -2232,6 +2258,7 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          if (tc1 != 0)
            {
              tcp_output_push_ip (vm, b[1], tc1, is_ip4);
+             tcp_check_if_gso (tc1, b[1]);
              tcp_output_handle_packet (tc1, b[1], error_node, &next[1],
                                        is_ip4);
            }
@@ -2262,6 +2289,7 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       if (PREDICT_TRUE (tc0 != 0))
        {
          tcp_output_push_ip (vm, b[0], tc0, is_ip4);
+         tcp_check_if_gso (tc0, b[0]);
          tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
        }
       else