ip: Use .api declared error counters
[vpp.git] / src / vnet / mpls / mpls_output.c
index 3699163..3ea6ce5 100644 (file)
@@ -363,12 +363,6 @@ VLIB_REGISTER_NODE (mpls_midchain_node) = {
   .format_trace = format_mpls_output_trace,
 };
 
-static char *mpls_frag_error_strings[] = {
-#define _(sym,string) string,
-  foreach_ip_frag_error
-#undef _
-};
-
 typedef struct mpls_frag_trace_t_
 {
     u16 pkt_size;
@@ -377,11 +371,12 @@ typedef struct mpls_frag_trace_t_
 
 typedef enum
 {
-    MPLS_FRAG_NEXT_REWRITE,
-    MPLS_FRAG_NEXT_REWRITE_MIDCHAIN,
-    MPLS_FRAG_NEXT_ICMP_ERROR,
-    MPLS_FRAG_NEXT_DROP,
-    MPLS_FRAG_N_NEXT,
+  MPLS_FRAG_NEXT_REWRITE,
+  MPLS_FRAG_NEXT_REWRITE_MIDCHAIN,
+  MPLS_FRAG_NEXT_ICMP4_ERROR,
+  MPLS_FRAG_NEXT_ICMP6_ERROR,
+  MPLS_FRAG_NEXT_DROP,
+  MPLS_FRAG_N_NEXT,
 } mpls_frag_next_t;
 
 static uword
@@ -390,9 +385,7 @@ mpls_frag (vlib_main_t * vm,
            vlib_frame_t * frame)
 {
     u32 n_left_from, next_index, * from, * to_next, n_left_to_next, *frags;
-    vlib_node_runtime_t * error_node;
 
-    error_node = vlib_node_get_runtime (vm, mpls_output_node.index);
     from = vlib_frame_vector_args (frame);
     n_left_from = frame->n_vectors;
     next_index = node->cached_next_index;
@@ -410,8 +403,7 @@ mpls_frag (vlib_main_t * vm,
             mpls_frag_next_t next0;
             u32 pi0, adj_index0;
             ip_frag_error_t error0 = IP_FRAG_ERROR_NONE;
-            i16 encap_size;
-           u16 mtu;
+           i16 encap_size, mtu;
            u8 is_ip4;
 
            pi0 = to_next[0] = from[0];
@@ -422,6 +414,7 @@ mpls_frag (vlib_main_t * vm,
 
            adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
            adj0 = adj_get (adj_index0);
+
            /* the size of the MPLS stack */
            encap_size = vnet_buffer (p0)->l3_hdr_offset - p0->current_data;
            mtu = adj0->rewrite_header.max_l3_packet_bytes - encap_size;
@@ -430,7 +423,18 @@ mpls_frag (vlib_main_t * vm,
            if (is_ip4)
              error0 = ip4_frag_do_fragment (vm, pi0, mtu, encap_size, &frags);
            else
-             error0 = ip6_frag_do_fragment (vm, pi0, mtu, encap_size, &frags);
+             {
+               if (!(p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED))
+                 {
+                   /* only fragment locally generated IPv6 */
+                   error0 = IP_FRAG_ERROR_DONT_FRAGMENT_SET;
+                 }
+               else
+                 {
+                   error0 =
+                     ip6_frag_do_fragment (vm, pi0, mtu, encap_size, &frags);
+                 }
+             }
 
            if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
              {
@@ -443,24 +447,40 @@ mpls_frag (vlib_main_t * vm,
            if (PREDICT_TRUE (error0 == IP_FRAG_ERROR_NONE))
              {
                /* Free original buffer chain */
-               vlib_buffer_free_one (vm, pi0); /* Free original packet */
+               vlib_buffer_free_one (vm, pi0);
                next0 = (IP_LOOKUP_NEXT_MIDCHAIN == adj0->lookup_next_index ?
                           MPLS_FRAG_NEXT_REWRITE_MIDCHAIN :
                           MPLS_FRAG_NEXT_REWRITE);
              }
-           else if (is_ip4 && error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET)
-             {
-               icmp4_error_set_vnet_buffer (
-                 p0, ICMP4_destination_unreachable,
-                 ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
-                 vnet_buffer (p0)->ip_frag.mtu);
-               next0 = MPLS_FRAG_NEXT_ICMP_ERROR;
-             }
            else
              {
-               vlib_error_count (vm, mpls_output_node.index, error0, 1);
-               vec_add1 (frags, pi0); /* Get rid of the original buffer */
-               next0 = MPLS_FRAG_NEXT_DROP;
+               vlib_error_count (vm, node->node_index, error0, 1);
+
+               if (error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET)
+                 {
+                   vlib_buffer_advance (p0, encap_size);
+                   if (is_ip4)
+                     {
+                       icmp4_error_set_vnet_buffer (
+                         p0, ICMP4_destination_unreachable,
+                         ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
+                         mtu);
+                       next0 = MPLS_FRAG_NEXT_ICMP4_ERROR;
+                     }
+                   else
+                     {
+                       icmp6_error_set_vnet_buffer (p0, ICMP6_packet_too_big,
+                                                    0, mtu);
+                       next0 = MPLS_FRAG_NEXT_ICMP6_ERROR;
+                     }
+                 }
+               else
+                 {
+                   next0 = MPLS_FRAG_NEXT_DROP;
+                 }
+
+               /* Get rid of the original buffer */
+               vec_add1 (frags, pi0);
              }
 
            /* Send fragments that were added in the frame */
@@ -480,9 +500,6 @@ mpls_frag (vlib_main_t * vm,
                    to_next += 1;
                    n_left_to_next -= 1;
 
-                   p0 = vlib_get_buffer (vm, i);
-                   p0->error = error_node->errors[error0];
-
                    vlib_validate_buffer_enqueue_x1 (
                      vm, node, next_index, to_next, n_left_to_next, i, next0);
                  }
@@ -511,22 +528,21 @@ format_mpls_frag_trace (u8 * s, va_list * args)
 }
 
 VLIB_REGISTER_NODE (mpls_frag_node) = {
-    .function = mpls_frag,
-    .name = "mpls-frag",
-    .vector_size = sizeof (u32),
-    .format_trace = format_mpls_frag_trace,
-    .type = VLIB_NODE_TYPE_INTERNAL,
-
-    .n_errors = IP_FRAG_N_ERROR,
-    .error_strings = mpls_frag_error_strings,
-
-    .n_next_nodes = MPLS_FRAG_N_NEXT,
-    .next_nodes = {
-        [MPLS_FRAG_NEXT_REWRITE] = "mpls-output",
-        [MPLS_FRAG_NEXT_REWRITE_MIDCHAIN] = "mpls-midchain",
-        [MPLS_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
-        [MPLS_FRAG_NEXT_DROP] = "mpls-drop"
-    },
+  .function = mpls_frag,
+  .name = "mpls-frag",
+  .vector_size = sizeof (u32),
+  .format_trace = format_mpls_frag_trace,
+  .type = VLIB_NODE_TYPE_INTERNAL,
+
+  .n_errors = IP_FRAG_N_ERROR,
+  .error_counters = ip_frag_error_counters,
+
+  .n_next_nodes = MPLS_FRAG_N_NEXT,
+  .next_nodes = { [MPLS_FRAG_NEXT_REWRITE] = "mpls-output",
+                 [MPLS_FRAG_NEXT_REWRITE_MIDCHAIN] = "mpls-midchain",
+                 [MPLS_FRAG_NEXT_ICMP4_ERROR] = "ip4-icmp-error",
+                 [MPLS_FRAG_NEXT_ICMP6_ERROR] = "ip6-icmp-error",
+                 [MPLS_FRAG_NEXT_DROP] = "mpls-drop" },
 };
 
 /*