Don't re-write adjacency with same information.
[vpp.git] / vnet / vnet / ethernet / arp.c
index 205023a..fa13d52 100644 (file)
@@ -70,8 +70,6 @@ typedef struct {
   uword * mac_changes_by_address;
   pending_resolution_t * mac_changes;
 
-  u32 * arp_input_next_index_by_hw_if_index;
-
   ethernet_arp_ip4_entry_t * ip4_entry_pool;
 
   mhash_t ip4_entry_by_key;
@@ -280,7 +278,7 @@ ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
           ethernet_arp_ip4_over_ethernet_address_t delme;
          e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
 
-          memcpy (&delme.ethernet, e->ethernet_address, 6);
+          clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
           delme.ip4.as_u32 = e->key.ip4_address.as_u32;
 
           vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
@@ -349,7 +347,7 @@ vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
   args.fib_index = fib_index;
   args.is_static = is_static;
   args.is_remove = 0;
-  memcpy (&args.a, a, sizeof (*a));
+  clib_memcpy (&args.a, a, sizeof (*a));
 
   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, 
                                (u8 *) &args, sizeof (args));
@@ -392,7 +390,8 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
       e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
 
       /* Refuse to over-write static arp. */
-      if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
+      if (!is_static &&
+          (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC))
        return -2;
       make_new_arp_cache_entry = 0;
     }
@@ -400,6 +399,7 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
   /* Note: always install the route. It might have been deleted */
   memset(&adj, 0, sizeof(adj));
   adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
+  adj.n_adj = 1; /*  otherwise signature compare fails */
 
   vnet_rewrite_for_sw_interface
     (vnm,
@@ -433,15 +433,22 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
     }
   else
     {
-      /* create new adj */
-      args.table_index_or_table_id = fib_index;
-      args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD | IP4_ROUTE_FLAG_NEIGHBOR;
-      args.dst_address = a->ip4;
-      args.dst_address_length = 32;
-      args.adj_index = ~0;
-      args.add_adj = &adj;
-      args.n_add_adj = 1;
-      ip4_add_del_route (im, &args);
+      /* Check that new adjacency actually isn't exactly the same as
+       *  what is already there. If we over-write the adjacency with
+       *  exactly the same info, its technically a new adjacency with
+       *  new counters, but to user it appears as counters reset.
+       */
+      if (vnet_ip_adjacency_share_compare (&adj, existing_adj) == 0) {
+        /* create new adj */
+        args.table_index_or_table_id = fib_index;
+        args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD | IP4_ROUTE_FLAG_NEIGHBOR;
+        args.dst_address = a->ip4;
+        args.dst_address_length = 32;
+        args.adj_index = ~0;
+        args.add_adj = &adj;
+        args.n_add_adj = 1;
+        ip4_add_del_route (im, &args);
+      }
     }
 
   if (make_new_arp_cache_entry)
@@ -454,7 +461,7 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
     }
 
   /* Update time stamp and ethernet address. */
-  memcpy (e->ethernet_address, a->ethernet, sizeof (e->ethernet_address));
+  clib_memcpy (e->ethernet_address, a->ethernet, sizeof (e->ethernet_address));
   e->cpu_time_last_updated = clib_cpu_time_now ();
   if (is_static)
     e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC;
@@ -627,6 +634,7 @@ int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
 /* Either we drop the packet or we send a reply to the sender. */
 typedef enum {
   ARP_INPUT_NEXT_DROP,
+  ARP_INPUT_NEXT_REPLY_TX,
   ARP_INPUT_N_NEXT,
 } arp_input_next_t;
 
@@ -697,19 +705,18 @@ static void unset_random_arp_entry (void)
 
   e = pool_elt_at_index (am->ip4_entry_pool, index);
   
-  memcpy (&delme.ethernet, e->ethernet_address, 6);
+  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
   delme.ip4.as_u32 = e->key.ip4_address.as_u32;
   
   vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
                                     e->key.fib_index, &delme);
 }
   
-static u32 arp_unnumbered (vlib_buffer_t * p0, 
-                           u32 pi0,
-                           ethernet_header_t * eth0,
-                           ip_interface_address_t * ifa0)
+static void arp_unnumbered (vlib_buffer_t * p0, 
+                      u32 pi0,
+                      ethernet_header_t * eth0,
+                      ip_interface_address_t * ifa0)
 {
-  ethernet_arp_main_t * am = &ethernet_arp_main;
   vlib_main_t * vm = vlib_get_main();
   vnet_main_t * vnm = vnet_get_main();
   vnet_interface_main_t * vim = &vnm->interface_main;
@@ -726,7 +733,7 @@ static u32 arp_unnumbered (vlib_buffer_t * p0,
   ethernet_arp_header_t * arp0;
 
   /* Save the dst mac address */
-  memcpy(dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
+  clib_memcpy(dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
 
   /* Figure out which sw_if_index supplied the address */
   unnum_src_sw_if_index = ifa0->sw_if_index;
@@ -755,7 +762,7 @@ static u32 arp_unnumbered (vlib_buffer_t * p0,
           b0 = vlib_get_buffer (vm, buffers[i]);
 
           /* xerox (partially built) ARP pkt */
-          memcpy (b0->data, p0->data, p0->current_length + p0->current_data);
+          clib_memcpy (b0->data, p0->data, p0->current_length + p0->current_data);
           b0->current_data = p0->current_data;
           b0->current_length = p0->current_length;
           vnet_buffer(b0)->sw_if_index[VLIB_RX] =
@@ -778,7 +785,7 @@ static u32 arp_unnumbered (vlib_buffer_t * p0,
       vnet_buffer(b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
 
       /* Fix ARP pkt src address */
-      memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
+      clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
 
       /* Build L2 encaps for this swif */
       header_size = sizeof (ethernet_header_t);
@@ -819,8 +826,8 @@ static u32 arp_unnumbered (vlib_buffer_t * p0,
       }
       
       /* Restore the original dst address, set src address */
-      memcpy (eth0->dst_address, dst_mac_address, sizeof (eth0->dst_address));
-      memcpy (eth0->src_address, hi->hw_address, sizeof (eth0->src_address));
+      clib_memcpy (eth0->dst_address, dst_mac_address, sizeof (eth0->dst_address));
+      clib_memcpy (eth0->src_address, hi->hw_address, sizeof (eth0->src_address));
       
       /* Transmit replicas */
       if (i > 0)
@@ -833,13 +840,11 @@ static u32 arp_unnumbered (vlib_buffer_t * p0,
         }
     }
 
-  hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[0]);
+  /* The regular path outputs the original pkt.. */
+  vnet_buffer (p0)->sw_if_index[VLIB_TX] = broadcast_swifs[0];
 
   vec_free (broadcast_swifs);
   vec_free (buffers);
-
-  /* The regular path outputs the original pkt.. */
-  return vec_elt (am->arp_input_next_index_by_hw_if_index, hi->hw_if_index);
 }
 
 static uword
@@ -982,27 +987,22 @@ arp_input (vlib_main_t * vm,
          vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
          hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
 
-          /* Can happen in a multi-core env. */
-          if (PREDICT_FALSE(hw_if0->hw_if_index >= vec_len (am->arp_input_next_index_by_hw_if_index)))
-            {
-              error0 = ETHERNET_ARP_ERROR_missing_interface_address;
-              goto drop2;
-            }
-
-         next0 = vec_elt (am->arp_input_next_index_by_hw_if_index, hw_if0->hw_if_index);
+         /* Send reply back through input interface */
+         vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
+         next0 = ARP_INPUT_NEXT_REPLY_TX;
 
          arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
 
          arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
 
-         memcpy (arp0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address, 6);
+         clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address, 6);
          clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) = if_addr0->data_u32;
 
          /* Hardware must be ethernet-like. */
          ASSERT (vec_len (hw_if0->hw_address) == 6);
 
-         memcpy (eth0->dst_address, eth0->src_address, 6);
-         memcpy (eth0->src_address, hw_if0->hw_address, 6);
+         clib_memcpy (eth0->dst_address, eth0->src_address, 6);
+         clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
 
          /* Figure out how much to rewind current data from adjacency. */
           if (ifa0)
@@ -1015,7 +1015,7 @@ arp_input (vlib_main_t * vm,
                   goto drop2;
                 }
               if (is_unnum0)
-                next0 = arp_unnumbered (p0, pi0, eth0, ifa0);
+                arp_unnumbered (p0, pi0, eth0, ifa0);
               else
                 vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
             }
@@ -1117,32 +1117,13 @@ VLIB_REGISTER_NODE (arp_input_node,static) = {
   .n_next_nodes = ARP_INPUT_N_NEXT,
   .next_nodes = {
     [ARP_INPUT_NEXT_DROP] = "error-drop",
+    [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
   },
 
   .format_buffer = format_ethernet_arp_header,
   .format_trace = format_ethernet_arp_input_trace,
 };
 
-clib_error_t *
-ethernet_arp_hw_interface_link_up_down (vnet_main_t * vnm,
-                                       u32 hw_if_index,
-                                       u32 flags)
-{
-  ethernet_arp_main_t * am = &ethernet_arp_main;
-  vnet_hw_interface_t * hw_if;
-
-  hw_if = vnet_get_hw_interface (vnm, hw_if_index);
-
-  /* Fill in lookup tables with default table (0). */
-  vec_validate_init_empty (am->arp_input_next_index_by_hw_if_index, hw_if_index, ~0);
-  am->arp_input_next_index_by_hw_if_index[hw_if_index]
-    = vlib_node_add_next (vnm->vlib_main, arp_input_node.index, hw_if->output_node_index);
-
-  return 0;
-}
-
-VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (ethernet_arp_hw_interface_link_up_down);
-
 static int
 ip4_arp_entry_sort (void *a1, void *a2)
 {
@@ -1341,7 +1322,7 @@ arp_add_del_adj_cb (struct ip_lookup_main_t * lm,
        {
          if (!e)
            clib_warning("Adjacency contains unknown ARP next hop %U (del)",
-                        format_ip4_address, &adj->arp.next_hop);
+                        format_ip46_address, &adj->arp.next_hop, IP46_TYPE_IP4);
          else
            arp_ip4_entry_del_adj(e, adj->heap_handle);
        }
@@ -1349,7 +1330,7 @@ arp_add_del_adj_cb (struct ip_lookup_main_t * lm,
        {
          if (!e)
            clib_warning("Adjacency contains unknown ARP next hop %U (add)",
-                        format_ip4_address, &adj->arp.next_hop);
+                        format_ip46_address, &adj->arp.next_hop, IP46_TYPE_IP4);
          else
            arp_ip4_entry_add_adj(e, adj->heap_handle);
        }
@@ -1418,7 +1399,7 @@ vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
   args.sw_if_index = sw_if_index;
   args.fib_index = fib_index;
   args.is_remove = 1;
-  memcpy (&args.a, a, sizeof (*a));
+  clib_memcpy (&args.a, a, sizeof (*a));
 
   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, 
                                (u8 *) &args, sizeof (args));
@@ -1628,8 +1609,8 @@ vnet_arp_glean_add(u32 fib_index, void * next_hop_arg)
   e->flags = ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN;
 
   memset(&args, 0, sizeof(args));
-  memcpy(&add_adj, adj, sizeof(add_adj));
-  add_adj.arp.next_hop.ip4.as_u32 = next_hop->as_u32; /* install neighbor /32 route */
+  clib_memcpy(&add_adj, adj, sizeof(add_adj));
+  ip46_address_set_ip4(&add_adj.arp.next_hop, next_hop); /* install neighbor /32 route */
   args.table_index_or_table_id = fib_index;
   args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD| IP4_ROUTE_FLAG_NEIGHBOR;
   args.dst_address.as_u32 = next_hop->as_u32;
@@ -1742,7 +1723,7 @@ ip_arp_add_del_command_fn (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
     .path = "set ip arp",
-    .short_help = "set ip arp [del] <intfc> <ip-address> <mac-address>",
+    .short_help = "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
     .function = ip_arp_add_del_command_fn,
 };
 
@@ -1856,7 +1837,7 @@ arp_term_l2bd (vlib_main_t * vm,
            {
              u8 *t0 = vlib_add_trace (
                  vm, node, p0, sizeof(ethernet_arp_input_trace_t));
-             memcpy (t0, l3h0, sizeof(ethernet_arp_input_trace_t));
+             clib_memcpy (t0, l3h0, sizeof(ethernet_arp_input_trace_t));
            }
 
          if (PREDICT_FALSE  (
@@ -1935,9 +1916,9 @@ arp_term_l2bd (vlib_main_t * vm,
          arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
          arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
          arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
-         memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
-         memcpy (eth0->dst_address, eth0->src_address, 6);
-         memcpy (eth0->src_address, macp0, 6);
+         clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
+         clib_memcpy (eth0->dst_address, eth0->src_address, 6);
+         clib_memcpy (eth0->src_address, macp0, 6);
          n_replies_sent += 1;
 
          // For BVI, need to use l2-fwd node to send ARP reply as