vcl: RX event may lost when accept session repeatedly
[vpp.git] / src / vnet / ip / ip_neighbor.c
index 8043765..ef61dde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * src/vnet/ip/ip_neighboor.c: ip neighbor generic handling
+ * src/vnet/ip/ip_neighbor.c: ip neighbor generic handling
  *
  * Copyright (c) 2018 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,7 +27,7 @@
  *   - Max processing allowed per run      : 20 usec
  *   - Max probe/delete operations per run : 10
  *   - Scan interrupt delay to resume scan : 1 msec
- *   - Neighbor stale threashold           : 4 x scan-interval
+ *   - Neighbor stale threshold            : 4 x scan-interval
  */
 #define IP_NEIGHBOR_DEF_SCAN_INTERVAL (60.0)
 #define IP_NEIGHBOR_DEF_MAX_PROC_TIME (20e-6)
@@ -47,6 +47,89 @@ typedef struct
 
 static ip_neighbor_scan_config_t ip_neighbor_scan_conf;
 
+u8 *
+format_ip_neighbor_flags (u8 * s, va_list * args)
+{
+  const ip_neighbor_flags_t flags = va_arg (*args, int);
+
+  if (flags & IP_NEIGHBOR_FLAG_STATIC)
+    s = format (s, "S");
+
+  if (flags & IP_NEIGHBOR_FLAG_DYNAMIC)
+    s = format (s, "D");
+
+  if (flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY)
+    s = format (s, "N");
+
+  return s;
+}
+
+int
+ip_neighbor_add (const ip46_address_t * ip,
+                ip46_type_t type,
+                const mac_address_t * mac,
+                u32 sw_if_index,
+                ip_neighbor_flags_t flags, u32 * stats_index)
+{
+  fib_protocol_t fproto;
+  vnet_link_t linkt;
+  int rv;
+
+  /*
+   * there's no validation here of the ND/ARP entry being added.
+   * The expectation is that the FIB will ensure that nothing bad
+   * will come of adding bogus entries.
+   */
+  if (IP46_TYPE_IP6 == type)
+    {
+      rv = vnet_set_ip6_ethernet_neighbor (vlib_get_main (),
+                                          sw_if_index, &ip->ip6, mac, flags);
+      fproto = FIB_PROTOCOL_IP6;
+      linkt = VNET_LINK_IP6;
+    }
+  else
+    {
+      ethernet_arp_ip4_over_ethernet_address_t a = {
+       .ip4 = ip->ip4,
+       .mac = *mac,
+      };
+
+      rv =
+       vnet_arp_set_ip4_over_ethernet (vnet_get_main (), sw_if_index, &a,
+                                       flags);
+      fproto = FIB_PROTOCOL_IP4;
+      linkt = VNET_LINK_IP4;
+    }
+
+  if (0 == rv && stats_index)
+    *stats_index = adj_nbr_find (fproto, linkt, ip, sw_if_index);
+
+  return (rv);
+}
+
+int
+ip_neighbor_del (const ip46_address_t * ip, ip46_type_t type, u32 sw_if_index)
+{
+  int rv;
+
+  if (IP46_TYPE_IP6 == type)
+    {
+      rv = vnet_unset_ip6_ethernet_neighbor (vlib_get_main (),
+                                            sw_if_index, &ip->ip6);
+    }
+  else
+    {
+      ethernet_arp_ip4_over_ethernet_address_t a = {
+       .ip4 = ip->ip4,
+      };
+
+      rv =
+       vnet_arp_unset_ip4_over_ethernet (vnet_get_main (), sw_if_index, &a);
+    }
+
+  return (rv);
+}
+
 void
 ip_neighbor_scan_enable_disable (ip_neighbor_scan_arg_t * arg)
 {
@@ -107,14 +190,14 @@ ip_neighbor_scan (vlib_main_t * vm, f64 start_time, u32 start_idx,
       if (!is_ip6)
        {
          n4 = pool_elt_at_index (np4, curr_idx);
-         if (n4->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
+         if (n4->flags & IP_NEIGHBOR_FLAG_STATIC)
            goto next_neighbor;
          update_time = n4->time_last_updated;
        }
       else
        {
          n6 = pool_elt_at_index (np6, curr_idx);
-         if (n6->flags & IP6_NEIGHBOR_FLAG_STATIC)
+         if (n6->flags & IP_NEIGHBOR_FLAG_STATIC)
            goto next_neighbor;
          update_time = n6->time_last_updated;
        }
@@ -126,16 +209,17 @@ ip_neighbor_scan (vlib_main_t * vm, f64 start_time, u32 start_idx,
          /* delete stale neighbor */
          if (!is_ip6)
            {
-             ethernet_arp_ip4_over_ethernet_address_t delme;
-             clib_memcpy (&delme.ethernet, n4->ethernet_address, 6);
-             delme.ip4.as_u32 = n4->ip4_address.as_u32;
+             ethernet_arp_ip4_over_ethernet_address_t delme = {
+               .ip4.as_u32 = n4->ip4_address.as_u32,
+               .mac = n4->mac,
+             };
+
              vnet_arp_unset_ip4_over_ethernet (vnm, n4->sw_if_index, &delme);
            }
          else
            {
              vnet_unset_ip6_ethernet_neighbor
-               (vm, n6->key.sw_if_index, &n6->key.ip6_address,
-                n6->link_layer_address, 6);
+               (vm, n6->key.sw_if_index, &n6->key.ip6_address);
            }
        }
       else if (delta >= cfg->scan_interval)
@@ -240,7 +324,7 @@ ip_neighbor_scan_cli (vlib_main_t * vm, unformat_input_t * input,
   u32 interval = 0, time = 0, update = 0, delay = 0, stale = 0;
   ip_neighbor_scan_arg_t arg;
 
-  memset (&arg, 0, sizeof (arg));
+  clib_memset (&arg, 0, sizeof (arg));
   arg.mode = IP_SCAN_V46_NEIGHBORS;
 
   /* Get a line of input. */
@@ -323,11 +407,11 @@ done:
 
 /*?
  * The '<em>ip scan-neighbor</em>' command can be used to enable and disable
- * periodic IP neighbor scan and change various scan parameneters.
+ * periodic IP neighbor scan and change various scan parameters.
  *
  * @note The default parameters used for IP neighbor scan should work fine
  * under normal conditions. They should not be changed from the default unless
- * properly tested to work as desied.
+ * properly tested to work as desired.
  *
  * @cliexpar
  * Example of enabling IP neighbor scan: