misc: fix error handling in punt_replicate
[vpp.git] / src / vnet / ip / punt_node.c
index 53c8199..0306d59 100644 (file)
@@ -27,7 +27,6 @@
 #include <vnet/pg/pg.h>
 #include <vnet/udp/udp.h>
 #include <vnet/tcp/tcp.h>
-#include <vnet/sctp/sctp.h>
 #include <vnet/ip/punt.h>
 #include <vlib/unix/unix.h>
 
@@ -224,6 +223,7 @@ typedef struct
 {
   punt_client_t client;
   u8 is_midchain;
+  u8 packet_data[64];
 } udp_punt_trace_t;
 
 static u8 *
@@ -239,6 +239,9 @@ format_udp_punt_trace (u8 * s, va_list * args)
       s = format (s, "\n%U(buffer is part of chain)", format_white_space,
                  indent);
     }
+  s = format (s, "\n%U%U", format_white_space, indent,
+             format_hex_bytes, t->packet_data, sizeof (t->packet_data));
+
   return s;
 }
 
@@ -249,13 +252,15 @@ punt_socket_inline (vlib_main_t * vm,
                    punt_type_t pt, ip_address_family_t af)
 {
   u32 *buffers = vlib_frame_vector_args (frame);
+  u32 thread_index = vm->thread_index;
   uword n_packets = frame->n_vectors;
-  struct iovec *iovecs = 0;
   punt_main_t *pm = &punt_main;
   int i;
 
-  u32 node_index = AF_IP4 == af ? udp4_punt_socket_node.index :
-    udp6_punt_socket_node.index;
+  punt_thread_data_t *ptd = &pm->thread_data[thread_index];
+  u32 node_index = (AF_IP4 == af ?
+                   udp4_punt_socket_node.index :
+                   udp6_punt_socket_node.index);
 
   for (i = 0; i < n_packets; i++)
     {
@@ -286,13 +291,29 @@ punt_socket_inline (vlib_main_t * vm,
              udp = (udp_header_t *) (ip + 1);
            }
 
-         u16 port = clib_net_to_host_u16 (udp->dst_port);
-
          /*
           * Find registerered client
           * If no registered client, drop packet and count
           */
-         c = punt_client_l4_get (af, port);
+         c = punt_client_l4_get (af, clib_net_to_host_u16 (udp->dst_port));
+       }
+      else if (PUNT_TYPE_IP_PROTO == pt)
+       {
+         /* Reverse UDP Punt advance */
+         ip_protocol_t proto;
+
+         if (AF_IP4 == af)
+           {
+             ip4_header_t *ip = vlib_buffer_get_current (b);
+             proto = ip->protocol;
+           }
+         else
+           {
+             ip6_header_t *ip = vlib_buffer_get_current (b);
+             proto = ip->protocol;
+           }
+
+         c = punt_client_ip_proto_get (af, proto);
        }
       else if (PUNT_TYPE_EXCEPTION == pt)
        {
@@ -310,30 +331,32 @@ punt_socket_inline (vlib_main_t * vm,
 
       struct sockaddr_un *caddr = &c->caddr;
 
-      if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
-       {
-         udp_punt_trace_t *t;
-         t = vlib_add_trace (vm, node, b, sizeof (t[0]));
-         clib_memcpy_fast (&t->client, c, sizeof (t->client));
-       }
-
-      /* Re-set iovecs if present. */
-      if (iovecs)
-       _vec_len (iovecs) = 0;
+      /* Re-set iovecs */
+      vec_reset_length (ptd->iovecs);
 
       /* Add packet descriptor */
       packetdesc.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
       packetdesc.action = 0;
-      vec_add2 (iovecs, iov, 1);
+      vec_add2 (ptd->iovecs, iov, 1);
       iov->iov_base = &packetdesc;
       iov->iov_len = sizeof (packetdesc);
 
       /** VLIB buffer chain -> Unix iovec(s). */
       vlib_buffer_advance (b, -(sizeof (ethernet_header_t)));
-      vec_add2 (iovecs, iov, 1);
+      vec_add2 (ptd->iovecs, iov, 1);
       iov->iov_base = b->data + b->current_data;
       iov->iov_len = l = b->current_length;
 
+      if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
+       {
+         udp_punt_trace_t *t;
+         t = vlib_add_trace (vm, node, b, sizeof (t[0]));
+         clib_memcpy_fast (&t->client, c, sizeof (t->client));
+         clib_memcpy_fast (t->packet_data,
+                           vlib_buffer_get_current (b),
+                           sizeof (t->packet_data));
+       }
+
       if (PREDICT_FALSE (b->flags & VLIB_BUFFER_NEXT_PRESENT))
        {
          do
@@ -347,7 +370,7 @@ punt_socket_inline (vlib_main_t * vm,
                  t->is_midchain = 1;
                }
 
-             vec_add2 (iovecs, iov, 1);
+             vec_add2 (ptd->iovecs, iov, 1);
 
              iov->iov_base = b->data + b->current_data;
              iov->iov_len = b->current_length;
@@ -359,8 +382,8 @@ punt_socket_inline (vlib_main_t * vm,
       struct msghdr msg = {
        .msg_name = caddr,
        .msg_namelen = sizeof (*caddr),
-       .msg_iov = iovecs,
-       .msg_iovlen = vec_len (iovecs),
+       .msg_iov = ptd->iovecs,
+       .msg_iovlen = vec_len (ptd->iovecs),
       };
 
       if (sendmsg (pm->socket_fd, &msg, 0) < (ssize_t) l)
@@ -390,6 +413,22 @@ udp6_punt_socket (vlib_main_t * vm,
   return punt_socket_inline (vm, node, from_frame, PUNT_TYPE_L4, AF_IP6);
 }
 
+static uword
+ip4_proto_punt_socket (vlib_main_t * vm,
+                      vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+{
+  return punt_socket_inline (vm, node, from_frame,
+                            PUNT_TYPE_IP_PROTO, AF_IP4);
+}
+
+static uword
+ip6_proto_punt_socket (vlib_main_t * vm,
+                      vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+{
+  return punt_socket_inline (vm, node, from_frame,
+                            PUNT_TYPE_IP_PROTO, AF_IP6);
+}
+
 static uword
 exception_punt_socket (vlib_main_t * vm,
                       vlib_node_runtime_t * node, vlib_frame_t * from_frame)
@@ -419,6 +458,25 @@ VLIB_REGISTER_NODE (udp6_punt_socket_node) = {
   .n_errors = PUNT_N_ERROR,
   .error_strings = punt_error_strings,
 };
+VLIB_REGISTER_NODE (ip4_proto_punt_socket_node) = {
+  .function = ip4_proto_punt_socket,
+  .name = "ip4-proto-punt-socket",
+  .format_trace = format_udp_punt_trace,
+  .flags = VLIB_NODE_FLAG_IS_DROP,
+  /* Takes a vector of packets. */
+  .vector_size = sizeof (u32),
+  .n_errors = PUNT_N_ERROR,
+  .error_strings = punt_error_strings,
+};
+VLIB_REGISTER_NODE (ip6_proto_punt_socket_node) = {
+  .function = ip6_proto_punt_socket,
+  .name = "ip6-proto-punt-socket",
+  .format_trace = format_udp_punt_trace,
+  .flags = VLIB_NODE_FLAG_IS_DROP,
+  .vector_size = sizeof (u32),
+  .n_errors = PUNT_N_ERROR,
+  .error_strings = punt_error_strings,
+};
 VLIB_REGISTER_NODE (exception_punt_socket_node) = {
   .function = exception_punt_socket,
   .name = "exception-punt-socket",
@@ -538,6 +596,7 @@ punt_socket_rx_fd (vlib_main_t * vm, vlib_node_runtime_t * node, u32 fd)
   return 1;
 
 error:
+  vlib_put_next_frame (vm, node, next, n_left_to_next);
   vlib_node_increment_counter (vm, punt_socket_rx_node.index, error, 1);
   return 0;
 }
@@ -563,6 +622,7 @@ VLIB_REGISTER_NODE (punt_socket_rx_node) =
 {
  .function = punt_socket_rx,
  .name = "punt-socket-rx",
+ .flags = VLIB_NODE_FLAG_TRACE_SUPPORTED,
  .type = VLIB_NODE_TYPE_INPUT,
  .state = VLIB_NODE_STATE_INTERRUPT,
  .vector_size = 1,