fd closed twice
[vpp.git] / vnet / vnet / ip / udp_local.c
index 253ad0f..7676630 100644 (file)
 
 udp_main_t udp_main;
 
-#define foreach_udp_input_next                 \
-  _ (PUNT, "error-punt")                       \
-  _ (DROP, "error-drop")
+#define foreach_udp_input_next                  \
+  _ (PUNT, "error-punt")                        \
+  _ (DROP, "error-drop")                        \
+  _ (ICMP4_ERROR, "ip4-icmp-error")             \
+  _ (ICMP6_ERROR, "ip6-icmp-error")
 
 typedef enum {
 #define _(s,n) UDP_INPUT_NEXT_##s,
@@ -37,6 +39,7 @@ typedef enum {
 typedef struct {
   u16 src_port;
   u16 dst_port;
+  u8 bound;
 } udp_rx_trace_t;
 
 u8 * format_udp_rx_trace (u8 * s, va_list * args)
@@ -45,9 +48,10 @@ u8 * format_udp_rx_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   udp_rx_trace_t * t = va_arg (*args, udp_rx_trace_t *);
     
-  s = format (s, "UDP: src-port %d dst-port %d",
+  s = format (s, "UDP: src-port %d dst-port %d%s",
               clib_net_to_host_u16(t->src_port),
-              clib_net_to_host_u16(t->dst_port));
+              clib_net_to_host_u16(t->dst_port),
+              t->bound ? "" : " (no listener)");
   return s;
 }
 
@@ -55,8 +59,6 @@ typedef struct {
   /* Sparse vector mapping udp dst_port in network byte order
      to next index. */
   u16 * next_by_dst_port;
-
-  u32 * sparse_index_by_next_index;
 } udp_input_runtime_t;
 
 vlib_node_registration_t udp4_input_node;
@@ -71,13 +73,13 @@ udp46_input_inline (vlib_main_t * vm,
   udp_input_runtime_t * rt = is_ip4 ?
     (void *) vlib_node_get_runtime_data (vm, udp4_input_node.index)
     : (void *) vlib_node_get_runtime_data (vm, udp6_input_node.index);
-  __attribute__((unused)) u32 n_left_from, next_index, i_next, * from, * to_next;
+  __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next;
+  word n_no_listener = 0;
 
   from = vlib_frame_vector_args (from_frame);
   n_left_from = from_frame->n_vectors;
 
   next_index = node->cached_next_index;
-  i_next = vec_elt (rt->sparse_index_by_next_index, next_index);
 
   while (n_left_from > 0)
     {
@@ -177,10 +179,59 @@ udp46_input_inline (vlib_main_t * vm,
           next0 = (error0 == 0) ? vec_elt(rt->next_by_dst_port, i0) : next0;
           next1 = (error1 == 0) ? vec_elt(rt->next_by_dst_port, i1) : next1;
 
-         b0->error = node->errors[next0 == SPARSE_VEC_INVALID_INDEX ? 
-                                  UDP_ERROR_NO_LISTENER : error0];
-         b1->error = node->errors[next1 == SPARSE_VEC_INVALID_INDEX ? 
-                                  UDP_ERROR_NO_LISTENER : error1];
+          if (PREDICT_FALSE(i0 == SPARSE_VEC_INVALID_INDEX))
+            {
+              // move the pointer back so icmp-error can find the
+              // ip packet header
+              vlib_buffer_advance (b0, - (word)advance0);
+
+              if (is_ip4)
+                {
+                  icmp4_error_set_vnet_buffer(b0, ICMP4_destination_unreachable,
+                        ICMP4_destination_unreachable_port_unreachable, 0);
+                  next0 = UDP_INPUT_NEXT_ICMP4_ERROR;
+                }
+              else
+                {
+                  icmp6_error_set_vnet_buffer(b0, ICMP6_destination_unreachable,
+                        ICMP6_destination_unreachable_port_unreachable, 0);
+                  next0 = UDP_INPUT_NEXT_ICMP6_ERROR;
+                }
+                n_no_listener ++;
+            }
+          else
+            {
+              b0->error = node->errors[UDP_ERROR_NONE];
+              // advance to the payload
+              vlib_buffer_advance (b0, sizeof (*h0));
+            }
+
+          if (PREDICT_FALSE(i1 == SPARSE_VEC_INVALID_INDEX))
+            {
+              // move the pointer back so icmp-error can find the
+              // ip packet header
+              vlib_buffer_advance (b1, - (word)advance1);
+
+              if (is_ip4)
+                {
+                  icmp4_error_set_vnet_buffer(b1, ICMP4_destination_unreachable,
+                        ICMP4_destination_unreachable_port_unreachable, 0);
+                  next1 = UDP_INPUT_NEXT_ICMP4_ERROR;
+                }
+              else
+                {
+                  icmp6_error_set_vnet_buffer(b1, ICMP6_destination_unreachable,
+                        ICMP6_destination_unreachable_port_unreachable, 0);
+                  next1 = UDP_INPUT_NEXT_ICMP6_ERROR;
+                }
+                n_no_listener ++;
+            }
+          else
+            {
+              b1->error = node->errors[UDP_ERROR_NONE];
+              // advance to the payload
+              vlib_buffer_advance (b1, sizeof (*h1));
+            }
           
           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
             {
@@ -188,8 +239,10 @@ udp46_input_inline (vlib_main_t * vm,
                                                    b0, sizeof (*tr));
               if (b0->error != node->errors[UDP_ERROR_LENGTH_ERROR])
                 {
-                  tr->src_port = h0->src_port;
-                  tr->dst_port = h0->dst_port;
+                  tr->src_port = h0 ? h0->src_port : 0;
+                  tr->dst_port = h0 ? h0->dst_port : 0;
+                  tr->bound = (next0 != UDP_INPUT_NEXT_ICMP4_ERROR &&
+                               next0 != UDP_INPUT_NEXT_ICMP6_ERROR);
                 }
             }
           if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) 
@@ -198,14 +251,13 @@ udp46_input_inline (vlib_main_t * vm,
                                                    b1, sizeof (*tr));
               if (b1->error != node->errors[UDP_ERROR_LENGTH_ERROR])
                 {
-                  tr->src_port = h1->src_port;
-                  tr->dst_port = h1->dst_port;
+                  tr->src_port = h1 ? h1->src_port : 0;
+                  tr->dst_port = h1 ? h1->dst_port : 0;
+                  tr->bound = (next1 != UDP_INPUT_NEXT_ICMP4_ERROR &&
+                               next1 != UDP_INPUT_NEXT_ICMP6_ERROR);
                 }
             }
 
-          vlib_buffer_advance (b0, sizeof (*h0));
-          vlib_buffer_advance (b1, sizeof (*h1));
-
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
                                           to_next, n_left_to_next,
                                           bi0, bi1, next0, next1);
@@ -251,7 +303,32 @@ udp46_input_inline (vlib_main_t * vm,
               i0 = sparse_vec_index (rt->next_by_dst_port, h0->dst_port);
               next0 = vec_elt(rt->next_by_dst_port, i0);
 
-              b0->error = node->errors [next0 == SPARSE_VEC_INVALID_INDEX ? UDP_ERROR_NO_LISTENER : UDP_ERROR_NONE];
+              if (PREDICT_FALSE(i0 == SPARSE_VEC_INVALID_INDEX))
+                {
+                  // move the pointer back so icmp-error can find the
+                  // ip packet header
+                  vlib_buffer_advance (b0, - (word)advance0);
+
+                  if (is_ip4)
+                    {
+                      icmp4_error_set_vnet_buffer(b0, ICMP4_destination_unreachable,
+                            ICMP4_destination_unreachable_port_unreachable, 0);
+                      next0 = UDP_INPUT_NEXT_ICMP4_ERROR;
+                    }
+                  else
+                    {
+                      icmp6_error_set_vnet_buffer(b0, ICMP6_destination_unreachable,
+                            ICMP6_destination_unreachable_port_unreachable, 0);
+                      next0 = UDP_INPUT_NEXT_ICMP6_ERROR;
+                    }
+                    n_no_listener ++;
+                }
+              else
+                {
+                  b0->error = node->errors[UDP_ERROR_NONE];
+                  // advance to the payload
+                  vlib_buffer_advance (b0, sizeof (*h0));
+                }
             }
           else
             {
@@ -268,9 +345,11 @@ udp46_input_inline (vlib_main_t * vm,
                 {
                   tr->src_port = h0->src_port;
                   tr->dst_port = h0->dst_port;
+                  tr->bound = (next0 != UDP_INPUT_NEXT_ICMP4_ERROR &&
+                               next0 != UDP_INPUT_NEXT_ICMP6_ERROR);
                 }
             }
-          vlib_buffer_advance (b0, sizeof (*h0));
+
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
                                           to_next, n_left_to_next,
                                           bi0, next0);
@@ -278,6 +357,7 @@ udp46_input_inline (vlib_main_t * vm,
 
       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     }
+  vlib_error_count(vm, node->node_index, UDP_ERROR_NO_LISTENER, n_no_listener);
   return from_frame->n_vectors;
 }
 
@@ -327,6 +407,8 @@ VLIB_REGISTER_NODE (udp4_input_node) = {
   .unformat_buffer = unformat_udp_header,
 };
 
+VLIB_NODE_FUNCTION_MULTIARCH (udp4_input_node, udp4_input)
+
 VLIB_REGISTER_NODE (udp6_input_node) = {
   .function = udp6_input,
   .name = "ip6-udp-lookup",
@@ -350,6 +432,8 @@ VLIB_REGISTER_NODE (udp6_input_node) = {
   .unformat_buffer = unformat_udp_header,
 };
 
+VLIB_NODE_FUNCTION_MULTIARCH (udp6_input_node, udp6_input)
+
 static void add_dst_port (udp_main_t * um,
                           udp_dst_port_t dst_port,
                          char * dst_port_name, u8 is_ip4)
@@ -379,7 +463,6 @@ udp_register_dst_port (vlib_main_t * vm,
   udp_dst_port_info_t * pi;
   udp_input_runtime_t * rt;
   u16 * n;
-  u32 i;
 
   {
     clib_error_t * error = vlib_call_init_function (vm, udp_local_init);
@@ -407,12 +490,6 @@ udp_register_dst_port (vlib_main_t * vm,
   n = sparse_vec_validate (rt->next_by_dst_port, 
                            clib_host_to_net_u16 (dst_port));
   n[0] = pi->next_index;
-
-  /* Rebuild next index -> sparse index inverse mapping when sparse vector
-     is updated. */
-  vec_validate (rt->sparse_index_by_next_index, pi->next_index);
-  for (i = 1; i < vec_len (rt->next_by_dst_port); i++)
-    rt->sparse_index_by_next_index[rt->next_by_dst_port[i]] = i;
 }
 
 /* Parse a UDP header. */
@@ -483,13 +560,6 @@ clib_error_t * udp_local_init (vlib_main_t * vm)
     (/* elt bytes */ sizeof (rt->next_by_dst_port[0]),
      /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
 
-  vec_validate (rt->sparse_index_by_next_index, UDP_INPUT_NEXT_DROP);
-  vec_validate (rt->sparse_index_by_next_index, UDP_INPUT_NEXT_PUNT);
-  rt->sparse_index_by_next_index[UDP_INPUT_NEXT_DROP]
-    = SPARSE_VEC_INVALID_INDEX;
-  rt->sparse_index_by_next_index[UDP_INPUT_NEXT_PUNT]
-    = SPARSE_VEC_INVALID_INDEX;
-
 #define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 1 /* is_ip4 */);
   foreach_udp4_dst_port
 #undef _
@@ -500,13 +570,6 @@ clib_error_t * udp_local_init (vlib_main_t * vm)
     (/* elt bytes */ sizeof (rt->next_by_dst_port[0]),
      /* bits in index */ BITS (((udp_header_t *) 0)->dst_port));
 
-  vec_validate (rt->sparse_index_by_next_index, UDP_INPUT_NEXT_DROP);
-  vec_validate (rt->sparse_index_by_next_index, UDP_INPUT_NEXT_PUNT);
-  rt->sparse_index_by_next_index[UDP_INPUT_NEXT_DROP]
-    = SPARSE_VEC_INVALID_INDEX;
-  rt->sparse_index_by_next_index[UDP_INPUT_NEXT_PUNT]
-    = SPARSE_VEC_INVALID_INDEX;
-
 #define _(n,s) add_dst_port (um, UDP_DST_PORT_##s, #s, 0 /* is_ip4 */);
   foreach_udp6_dst_port
 #undef _