arp:add error counters for all failure cases 30/15630/3
authorEyal Bari <ebari@cisco.com>
Wed, 31 Oct 2018 11:19:11 +0000 (13:19 +0200)
committerNeale Ranns <nranns@cisco.com>
Fri, 2 Nov 2018 07:45:39 +0000 (07:45 +0000)
Change-Id: Ided6c661edc9e2035fd7b472c312e2380d3f9c0b
Signed-off-by: Eyal Bari <ebari@cisco.com>
src/vnet/ethernet/arp_packet.h
src/vnet/ip/ip4_forward.c

index e5f424d..206be41 100644 (file)
@@ -109,11 +109,11 @@ typedef enum
 
 typedef enum
 {
-  IP4_ARP_ERROR_DROP,
+  IP4_ARP_ERROR_THROTTLED,
+  IP4_ARP_ERROR_RESOLVED,
+  IP4_ARP_ERROR_NO_BUFFERS,
   IP4_ARP_ERROR_REQUEST_SENT,
   IP4_ARP_ERROR_NON_ARP_ADJ,
-  IP4_ARP_ERROR_REPLICATE_DROP,
-  IP4_ARP_ERROR_REPLICATE_FAIL,
   IP4_ARP_ERROR_NO_SOURCE_ADDRESS,
 } ip4_arp_error_t;
 
index d8b9054..4fdedc1 100644 (file)
@@ -1770,60 +1770,58 @@ ip4_arp_inline (vlib_main_t * vm,
 
       while (n_left_from > 0 && n_left_to_next_drop > 0)
        {
-         u32 pi0, adj_index0, sw_if_index0, drop0;
+         u32 pi0, bi0, adj_index0, sw_if_index0;
          ip_adjacency_t *adj0;
-         vlib_buffer_t *p0;
-         ip4_header_t *ip0;
+         vlib_buffer_t *p0, *b0;
+         ip4_address_t resolve0;
+         ethernet_arp_header_t *h0;
+         vnet_hw_interface_t *hw_if0;
          u64 r0;
 
          pi0 = from[0];
-
          p0 = vlib_get_buffer (vm, pi0);
 
+         from += 1;
+         n_left_from -= 1;
+         to_next_drop[0] = pi0;
+         to_next_drop += 1;
+         n_left_to_next_drop -= 1;
+
          adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
          adj0 = adj_get (adj_index0);
-         ip0 = vlib_buffer_get_current (p0);
-
-         sw_if_index0 = adj0->rewrite_header.sw_if_index;
-         vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
 
-         if (PREDICT_TRUE (is_glean))
+         if (is_glean)
            {
-             /*
-              * this is the Glean case, so we are ARPing for the
-              * packet's destination
-              */
-             r0 = ip0->dst_address.data_u32;
+             /* resolve the packet's destination */
+             ip4_header_t *ip0 = vlib_buffer_get_current (p0);
+             resolve0 = ip0->dst_address;
            }
          else
            {
-             r0 = adj0->sub_type.nbr.next_hop.ip4.data_u32;
+             /* resolve the incomplete adj */
+             resolve0 = adj0->sub_type.nbr.next_hop.ip4;
            }
+
          /* combine the address and interface for the hash key */
-         r0 = r0 << 32;
+         sw_if_index0 = adj0->rewrite_header.sw_if_index;
+         r0 = (u64) resolve0.data_u32 << 32;
          r0 |= sw_if_index0;
 
-         drop0 = throttle_check (&im->arp_throttle, thread_index, r0, seed);
-
-         from += 1;
-         n_left_from -= 1;
-         to_next_drop[0] = pi0;
-         to_next_drop += 1;
-         n_left_to_next_drop -= 1;
-
-         p0->error =
-           node->errors[drop0 ? IP4_ARP_ERROR_DROP :
-                        IP4_ARP_ERROR_REQUEST_SENT];
+         if (throttle_check (&im->arp_throttle, thread_index, r0, seed))
+           {
+             p0->error = node->errors[IP4_ARP_ERROR_THROTTLED];
+             continue;
+           }
 
          /*
           * the adj has been updated to a rewrite but the node the DPO that got
           * us here hasn't - yet. no big deal. we'll drop while we wait.
           */
          if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index)
-           continue;
-
-         if (drop0)
-           continue;
+           {
+             p0->error = node->errors[IP4_ARP_ERROR_RESOLVED];
+             continue;
+           }
 
          /*
           * Can happen if the control-plane is programming tables
@@ -1833,77 +1831,61 @@ ip4_arp_inline (vlib_main_t * vm,
              || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
            {
              p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
+             continue;
            }
-         else
-           /* Send ARP request. */
+         /* Send ARP request. */
+         h0 =
+           vlib_packet_template_get_packet (vm,
+                                            &im->ip4_arp_request_packet_template,
+                                            &bi0);
+
+         /* Seems we're out of buffers */
+         if (PREDICT_FALSE (!h0))
            {
-             u32 bi0 = 0;
-             vlib_buffer_t *b0;
-             ethernet_arp_header_t *h0;
-             vnet_hw_interface_t *hw_if0;
-
-             h0 =
-               vlib_packet_template_get_packet (vm,
-                                                &im->ip4_arp_request_packet_template,
-                                                &bi0);
-
-             /* Seems we're out of buffers */
-             if (PREDICT_FALSE (!h0))
-               continue;
-
-             /* Add rewrite/encap string for ARP packet. */
-             vnet_rewrite_one_header (adj0[0], h0,
-                                      sizeof (ethernet_header_t));
+             p0->error = node->errors[IP4_ARP_ERROR_NO_BUFFERS];
+             continue;
+           }
 
-             hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+         /* Add rewrite/encap string for ARP packet. */
+         vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t));
 
-             /* Src ethernet address in ARP header. */
-             clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
-                          hw_if0->hw_address,
-                          sizeof (h0->ip4_over_ethernet[0].ethernet));
+         hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
 
-             if (is_glean)
-               {
-                 /* The interface's source address is stashed in the Glean Adj */
-                 h0->ip4_over_ethernet[0].ip4 =
-                   adj0->sub_type.glean.receive_addr.ip4;
-
-                 /* Copy in destination address we are requesting. This is the
-                  * glean case, so it's the packet's destination.*/
-                 h0->ip4_over_ethernet[1].ip4.data_u32 =
-                   ip0->dst_address.data_u32;
-               }
-             else
+         /* Src ethernet address in ARP header. */
+         clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
+                      hw_if0->hw_address,
+                      sizeof (h0->ip4_over_ethernet[0].ethernet));
+         if (is_glean)
+           {
+             /* The interface's source address is stashed in the Glean Adj */
+             h0->ip4_over_ethernet[0].ip4 =
+               adj0->sub_type.glean.receive_addr.ip4;
+           }
+         else
+           {
+             /* Src IP address in ARP header. */
+             if (ip4_src_address_for_packet (lm, sw_if_index0,
+                                             &h0->ip4_over_ethernet[0].ip4))
                {
-                 /* Src IP address in ARP header. */
-                 if (ip4_src_address_for_packet (lm, sw_if_index0,
-                                                 &h0->
-                                                 ip4_over_ethernet[0].ip4))
-                   {
-                     /* No source address available */
-                     p0->error =
-                       node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
-                     vlib_buffer_free (vm, &bi0, 1);
-                     continue;
-                   }
-
-                 /* Copy in destination address we are requesting from the
-                    incomplete adj */
-                 h0->ip4_over_ethernet[1].ip4.data_u32 =
-                   adj0->sub_type.nbr.next_hop.ip4.as_u32;
+                 /* No source address available */
+                 p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
+                 vlib_buffer_free (vm, &bi0, 1);
+                 continue;
                }
+           }
+         h0->ip4_over_ethernet[1].ip4 = resolve0;
 
-             vlib_buffer_copy_trace_flag (vm, p0, bi0);
-             b0 = vlib_get_buffer (vm, bi0);
-             VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
-             vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
+         p0->error = node->errors[IP4_ARP_ERROR_REQUEST_SENT];
 
-             vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+         vlib_buffer_copy_trace_flag (vm, p0, bi0);
+         b0 = vlib_get_buffer (vm, bi0);
+         VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
+         vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
 
-             vlib_set_next_frame_buffer (vm, node,
-                                         adj0->rewrite_header.next_index,
-                                         bi0);
-           }
+         vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+
+         vlib_set_next_frame_buffer (vm, node,
+                                     adj0->rewrite_header.next_index, bi0);
        }
 
       vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
@@ -1925,11 +1907,11 @@ VLIB_NODE_FN (ip4_glean_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
 }
 
 static char *ip4_arp_error_strings[] = {
-  [IP4_ARP_ERROR_DROP] = "address overflow drops",
+  [IP4_ARP_ERROR_THROTTLED] = "ARP requests throttled",
+  [IP4_ARP_ERROR_RESOLVED] = "ARP requests resolved",
+  [IP4_ARP_ERROR_NO_BUFFERS] = "ARP requests out of buffer",
   [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
   [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
-  [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
-  [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
   [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
 };
 
@@ -1963,10 +1945,12 @@ VLIB_REGISTER_NODE (ip4_glean_node) =
 /* *INDENT-ON* */
 
 #define foreach_notrace_ip4_arp_error           \
-_(DROP)                                         \
+_(THROTTLED)                                    \
+_(RESOLVED)                                     \
+_(NO_BUFFERS)                                   \
 _(REQUEST_SENT)                                 \
-_(REPLICATE_DROP)                               \
-_(REPLICATE_FAIL)
+_(NON_ARP_ADJ)                                  \
+_(NO_SOURCE_ADDRESS)
 
 static clib_error_t *
 arp_notrace_init (vlib_main_t * vm)