tcp: avoid fr segments less than mss if possible
[vpp.git] / src / vnet / tcp / tcp_packet.h
index fcc55ff..c137ea6 100644 (file)
@@ -16,7 +16,8 @@
 #ifndef included_tcp_packet_h
 #define included_tcp_packet_h
 
-#include <vnet/vnet.h>
+#include <vnet/ip/ip4_packet.h>
+#include <vnet/ip/ip6_packet.h>
 
 /* TCP flags bit 0 first. */
 #define foreach_tcp_flag                                \
@@ -142,12 +143,12 @@ typedef struct _sack_block
 
 typedef struct
 {
-  u8 flags;            /** Option flags, see above */
-  u8 wscale;           /**< Window scale advertised */
-  u16 mss;             /**< Maximum segment size advertised */
+  sack_block_t *sacks; /**< SACK blocks */
   u32 tsval;           /**< Timestamp value */
   u32 tsecr;           /**< Echoed/reflected time stamp */
-  sack_block_t *sacks; /**< SACK blocks */
+  u16 mss;             /**< Maximum segment size advertised */
+  u8 flags;            /**< Option flags, see above */
+  u8 wscale;           /**< Window scale advertised */
   u8 n_sack_blocks;    /**< Number of SACKs blocks */
 } tcp_options_t;
 
@@ -172,6 +173,7 @@ typedef struct
 #define TCP_MAX_WND_SCALE               14     /* See RFC 1323 */
 #define TCP_OPTS_ALIGN                  4
 #define TCP_OPTS_MAX_SACK_BLOCKS        3
+#define TCP_MAX_GSO_SZ                         65536
 
 /* Modulo arithmetic for TCP sequence numbers */
 #define seq_lt(_s1, _s2) ((i32)((_s1)-(_s2)) < 0)
@@ -184,6 +186,100 @@ typedef struct
 #define timestamp_lt(_t1, _t2) ((i32)((_t1)-(_t2)) < 0)
 #define timestamp_leq(_t1, _t2) ((i32)((_t1)-(_t2)) <= 0)
 
+always_inline void
+ip4_tcp_reply_x1 (ip4_header_t *ip0, tcp_header_t *tcp0)
+{
+  u32 src0, dst0;
+
+  src0 = ip0->src_address.data_u32;
+  dst0 = ip0->dst_address.data_u32;
+  ip0->src_address.data_u32 = dst0;
+  ip0->dst_address.data_u32 = src0;
+
+  src0 = tcp0->src;
+  dst0 = tcp0->dst;
+  tcp0->src = dst0;
+  tcp0->dst = src0;
+}
+
+always_inline void
+ip4_tcp_reply_x2 (ip4_header_t *ip0, ip4_header_t *ip1, tcp_header_t *tcp0,
+                 tcp_header_t *tcp1)
+{
+  u32 src0, dst0, src1, dst1;
+
+  src0 = ip0->src_address.data_u32;
+  src1 = ip1->src_address.data_u32;
+  dst0 = ip0->dst_address.data_u32;
+  dst1 = ip1->dst_address.data_u32;
+  ip0->src_address.data_u32 = dst0;
+  ip1->src_address.data_u32 = dst1;
+  ip0->dst_address.data_u32 = src0;
+  ip1->dst_address.data_u32 = src1;
+
+  src0 = tcp0->src;
+  src1 = tcp1->src;
+  dst0 = tcp0->dst;
+  dst1 = tcp1->dst;
+  tcp0->src = dst0;
+  tcp1->src = dst1;
+  tcp0->dst = src0;
+  tcp1->dst = src1;
+}
+
+always_inline void
+ip6_tcp_reply_x1 (ip6_header_t *ip0, tcp_header_t *tcp0)
+{
+  {
+    ip6_address_t src0, dst0;
+
+    src0 = ip0->src_address;
+    dst0 = ip0->dst_address;
+    ip0->src_address = dst0;
+    ip0->dst_address = src0;
+  }
+
+  {
+    u16 src0, dst0;
+
+    src0 = tcp0->src;
+    dst0 = tcp0->dst;
+    tcp0->src = dst0;
+    tcp0->dst = src0;
+  }
+}
+
+always_inline void
+ip6_tcp_reply_x2 (ip6_header_t *ip0, ip6_header_t *ip1, tcp_header_t *tcp0,
+                 tcp_header_t *tcp1)
+{
+  {
+    ip6_address_t src0, dst0, src1, dst1;
+
+    src0 = ip0->src_address;
+    src1 = ip1->src_address;
+    dst0 = ip0->dst_address;
+    dst1 = ip1->dst_address;
+    ip0->src_address = dst0;
+    ip1->src_address = dst1;
+    ip0->dst_address = src0;
+    ip1->dst_address = src1;
+  }
+
+  {
+    u16 src0, dst0, src1, dst1;
+
+    src0 = tcp0->src;
+    src1 = tcp1->src;
+    dst0 = tcp0->dst;
+    dst1 = tcp1->dst;
+    tcp0->src = dst0;
+    tcp1->src = dst1;
+    tcp0->dst = src0;
+    tcp1->dst = src1;
+  }
+}
+
 /**
  * Parse TCP header options.
  *
@@ -369,14 +465,10 @@ tcp_options_write (u8 * data, tcp_options_t * opts)
        }
     }
 
-  /* Terminate TCP options */
-  if (opts_len % 4)
-    {
-      *data++ = TCP_OPTION_EOL;
-      opts_len += TCP_OPTION_LEN_EOL;
-    }
-
-  /* Pad with zeroes to a u32 boundary */
+  /* Terminate TCP options by padding with NOPs to a u32 boundary. Avoid using
+   * EOL because, it seems, it can break peers with broken option parsers that
+   * rely on options ending on a u32 boundary.
+   */
   while (opts_len % 4)
     {
       *data++ = TCP_OPTION_NOOP;