tcp: fix tcp packet trace
[vpp.git] / src / vnet / tcp / tcp_input.c
index fa2961e..1bcdd4c 100644 (file)
@@ -75,6 +75,18 @@ typedef enum _tcp_state_next
     TCP_STATE_N_NEXT,
 } tcp_state_next_t;
 
+typedef enum _tcp_input_next
+{
+  TCP_INPUT_NEXT_DROP,
+  TCP_INPUT_NEXT_LISTEN,
+  TCP_INPUT_NEXT_RCV_PROCESS,
+  TCP_INPUT_NEXT_SYN_SENT,
+  TCP_INPUT_NEXT_ESTABLISHED,
+  TCP_INPUT_NEXT_RESET,
+  TCP_INPUT_NEXT_PUNT,
+  TCP_INPUT_N_NEXT
+} tcp_input_next_t;
+
 #define tcp_next_output(is_ip4) (is_ip4 ? TCP_NEXT_TCP4_OUTPUT          \
                                         : TCP_NEXT_TCP6_OUTPUT)
 
@@ -1356,9 +1368,13 @@ format_tcp_rx_trace (u8 * s, va_list * args)
   tcp_connection_t *tc = &t->tcp_connection;
   u32 indent = format_get_indent (s);
 
-  s = format (s, "%U state %U\n%U%U", format_tcp_connection_id, tc,
-             format_tcp_state, tc->state, format_white_space, indent,
-             format_tcp_header, &t->tcp_header, 128);
+  if (!tc->c_lcl_port)
+    s = format (s, "no tcp connection\n%U%U", format_white_space, indent,
+               format_tcp_header, &t->tcp_header, 128);
+  else
+    s = format (s, "%U state %U\n%U%U", format_tcp_connection_id, tc,
+               format_tcp_state, tc->state, format_white_space, indent,
+               format_tcp_header, &t->tcp_header, 128);
 
   return s;
 }
@@ -1757,6 +1773,45 @@ tcp_check_tx_offload (tcp_connection_t * tc, int is_ipv4)
     tc->cfg_flags |= TCP_CFG_F_TSO;
 }
 
+static void
+tcp_input_trace_frame (vlib_main_t *vm, vlib_node_runtime_t *node,
+                      vlib_buffer_t **bs, u16 *nexts, u32 n_bufs, u8 is_ip4)
+{
+  tcp_connection_t *tc;
+  tcp_header_t *tcp;
+  tcp_rx_trace_t *t;
+  u8 flags;
+  int i;
+
+  for (i = 0; i < n_bufs; i++)
+    {
+      if (!(bs[i]->flags & VLIB_BUFFER_IS_TRACED))
+       continue;
+
+      t = vlib_add_trace (vm, node, bs[i], sizeof (*t));
+      if (nexts[i] == TCP_INPUT_NEXT_DROP || nexts[i] == TCP_INPUT_NEXT_PUNT ||
+         nexts[i] == TCP_INPUT_NEXT_RESET)
+       {
+         tc = 0;
+       }
+      else
+       {
+         flags = vnet_buffer (bs[i])->tcp.flags;
+
+         if (flags == TCP_STATE_LISTEN)
+           tc = tcp_listener_get (vnet_buffer (bs[i])->tcp.connection_index);
+         else if (flags == TCP_STATE_SYN_SENT)
+           tc = tcp_half_open_connection_get (
+             vnet_buffer (bs[i])->tcp.connection_index);
+         else
+           tc = tcp_connection_get (vnet_buffer (bs[i])->tcp.connection_index,
+                                    vm->thread_index);
+       }
+      tcp = tcp_buffer_hdr (bs[i]);
+      tcp_set_rx_trace_data (t, tc, tcp, bs[i], is_ip4);
+    }
+}
+
 always_inline uword
 tcp46_syn_sent_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
                       vlib_frame_t *frame, int is_ip4)
@@ -2628,7 +2683,8 @@ tcp46_listen_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
        {
          lc = tcp_listener_get (vnet_buffer (b[0])->tcp.connection_index);
        }
-      else /* We are in TimeWait state*/
+      /* Probably we are in time-wait or closed state */
+      else
        {
          tcp_connection_t *tc;
          tc = tcp_connection_get (vnet_buffer (b[0])->tcp.connection_index,
@@ -2780,18 +2836,6 @@ VLIB_REGISTER_NODE (tcp6_listen_node) =
 };
 /* *INDENT-ON* */
 
-typedef enum _tcp_input_next
-{
-  TCP_INPUT_NEXT_DROP,
-  TCP_INPUT_NEXT_LISTEN,
-  TCP_INPUT_NEXT_RCV_PROCESS,
-  TCP_INPUT_NEXT_SYN_SENT,
-  TCP_INPUT_NEXT_ESTABLISHED,
-  TCP_INPUT_NEXT_RESET,
-  TCP_INPUT_NEXT_PUNT,
-  TCP_INPUT_N_NEXT
-} tcp_input_next_t;
-
 #define foreach_tcp4_input_next                 \
   _ (DROP, "ip4-drop")                          \
   _ (LISTEN, "tcp4-listen")                     \
@@ -2812,28 +2856,6 @@ typedef enum _tcp_input_next
 
 #define filter_flags (TCP_FLAG_SYN|TCP_FLAG_ACK|TCP_FLAG_RST|TCP_FLAG_FIN)
 
-static void
-tcp_input_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
-                      vlib_buffer_t ** bs, u32 n_bufs, u8 is_ip4)
-{
-  tcp_connection_t *tc;
-  tcp_header_t *tcp;
-  tcp_rx_trace_t *t;
-  int i;
-
-  for (i = 0; i < n_bufs; i++)
-    {
-      if (bs[i]->flags & VLIB_BUFFER_IS_TRACED)
-       {
-         t = vlib_add_trace (vm, node, bs[i], sizeof (*t));
-         tc = tcp_connection_get (vnet_buffer (bs[i])->tcp.connection_index,
-                                  vm->thread_index);
-         tcp = vlib_buffer_get_current (bs[i]);
-         tcp_set_rx_trace_data (t, tc, tcp, bs[i], is_ip4);
-       }
-    }
-}
-
 static void
 tcp_input_set_error_next (tcp_main_t * tm, u16 * next, u32 * error, u8 is_ip4)
 {
@@ -2854,9 +2876,8 @@ tcp_input_set_error_next (tcp_main_t * tm, u16 * next, u32 * error, u8 is_ip4)
 }
 
 static inline void
-tcp_input_dispatch_buffer (tcp_main_t * tm, tcp_connection_t * tc,
-                          vlib_buffer_t * b, u16 * next,
-                          vlib_node_runtime_t * error_node)
+tcp_input_dispatch_buffer (tcp_main_t *tm, tcp_connection_t *tc,
+                          vlib_buffer_t *b, u16 *next, u16 *err_counters)
 {
   tcp_header_t *tcp;
   u32 error;
@@ -2878,7 +2899,7 @@ tcp_input_dispatch_buffer (tcp_main_t * tm, tcp_connection_t * tc,
 
   if (PREDICT_FALSE (error != TCP_ERROR_NONE))
     {
-      b->error = error_node->errors[error];
+      tcp_inc_err_counter (err_counters, error, 1);
       if (error == TCP_ERROR_DISPATCH)
        clib_warning ("tcp conn %u disp error state %U flags %U",
                      tc->c_c_index, format_tcp_state, tc->state,
@@ -2933,8 +2954,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
          vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
 
-         tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], node);
-         tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], node);
+         tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], err_counters);
+         tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], err_counters);
        }
       else
        {
@@ -2942,7 +2963,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
            {
              ASSERT (tcp_lookup_is_valid (tc0, b[0], tcp_buffer_hdr (b[0])));
              vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
-             tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], node);
+             tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0],
+                                        err_counters);
            }
          else
            {
@@ -2954,7 +2976,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
            {
              ASSERT (tcp_lookup_is_valid (tc1, b[1], tcp_buffer_hdr (b[1])));
              vnet_buffer (b[1])->tcp.connection_index = tc1->c_c_index;
-             tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1], node);
+             tcp_input_dispatch_buffer (tm, tc1, b[1], &next[1],
+                                        err_counters);
            }
          else
            {
@@ -2985,7 +3008,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          ASSERT (tcp_lookup_is_valid (tc0, b[0], tcp_buffer_hdr (b[0])));
          vnet_buffer (b[0])->tcp.connection_index = tc0->c_c_index;
-         tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], node);
+         tcp_input_dispatch_buffer (tm, tc0, b[0], &next[0], err_counters);
        }
       else
        {
@@ -2999,7 +3022,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
     }
 
   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
-    tcp_input_trace_frame (vm, node, bufs, frame->n_vectors, is_ip4);
+    tcp_input_trace_frame (vm, node, bufs, nexts, frame->n_vectors, is_ip4);
 
   tcp_store_err_counters (input, err_counters);
   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
@@ -3349,7 +3372,7 @@ do {                                                              \
   _(CLOSED, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_DROP,
     TCP_ERROR_CONNECTION_CLOSED);
   _(CLOSED, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_CONNECTION_CLOSED);
-  _(CLOSED, TCP_FLAG_SYN, TCP_INPUT_NEXT_RESET, TCP_ERROR_CONNECTION_CLOSED);
+  _ (CLOSED, TCP_FLAG_SYN, TCP_INPUT_NEXT_LISTEN, TCP_ERROR_NONE);
   _(CLOSED, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET,
     TCP_ERROR_CONNECTION_CLOSED);
 #undef _