c11 safe string handling support
[vpp.git] / src / vnet / lisp-gpe / lisp_gpe_adjacency.c
index 65006b8..6f85dc4 100644 (file)
  */
 
 #include <vnet/dpo/load_balance.h>
+#include <vnet/lisp-cp/control.h>
 #include <vnet/lisp-cp/lisp_types.h>
 #include <vnet/lisp-gpe/lisp_gpe_sub_interface.h>
 #include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
 #include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
 #include <vnet/fib/fib_entry.h>
 #include <vnet/adj/adj_midchain.h>
+#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_template.h>
 
 /**
  * Memory pool of all adjacencies
@@ -112,7 +115,7 @@ ip46_address_to_ip_address (const ip46_address_t * a, ip_address_t * b)
 {
   if (ip46_address_is_ip4 (a))
     {
-      memset (b, 0, sizeof (*b));
+      clib_memset (b, 0, sizeof (*b));
       ip_address_set (b, &a->ip4, IP4);
     }
   else
@@ -221,9 +224,97 @@ lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt)
 
 #define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
 
+static lisp_afi_e
+lisp_afi_from_vnet_link_type (vnet_link_t link)
+{
+  switch (link)
+    {
+    case VNET_LINK_IP4:
+      return LISP_AFI_IP;
+    case VNET_LINK_IP6:
+      return LISP_AFI_IP6;
+    case VNET_LINK_ETHERNET:
+      return LISP_AFI_MAC;
+    default:
+      return LISP_AFI_NO_ADDR;
+    }
+}
+
+static void
+lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj,
+                                  vlib_buffer_t * b)
+{
+  lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+  lisp_gpe_adjacency_t *ladj;
+  ip_address_t rloc;
+  index_t lai;
+  u32 si, di;
+  gid_address_t src, dst;
+  uword *feip;
+
+  ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc);
+  si = vnet_buffer (b)->sw_if_index[VLIB_TX];
+  lai = lisp_adj_find (&rloc, si);
+  ASSERT (INDEX_INVALID != lai);
+
+  ladj = pool_elt_at_index (lisp_adj_pool, lai);
+
+  u8 *lisp_data = (u8 *) vlib_buffer_get_current (b);
+
+  /* skip IP header */
+  if (is_v4_packet (lisp_data))
+    lisp_data += sizeof (ip4_header_t);
+  else
+    lisp_data += sizeof (ip6_header_t);
+
+  /* skip UDP header */
+  lisp_data += sizeof (udp_header_t);
+  // TODO: skip TCP?
+
+  /* skip LISP GPE header */
+  lisp_data += sizeof (lisp_gpe_header_t);
+
+  i16 saved_current_data = b->current_data;
+  b->current_data = lisp_data - b->data;
+
+  lisp_afi_e afi = lisp_afi_from_vnet_link_type (adj->ia_link);
+  get_src_and_dst_eids_from_buffer (lcm, b, &src, &dst, afi);
+  b->current_data = saved_current_data;
+  di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, &src);
+  if (PREDICT_FALSE (~0 == di))
+    {
+      clib_warning ("dst mapping not found (%U, %U)", format_gid_address,
+                   &src, format_gid_address, &dst);
+      return;
+    }
+
+  feip = hash_get (lcm->fwd_entry_by_mapping_index, di);
+  if (PREDICT_FALSE (!feip))
+    return;
+
+  lisp_stats_key_t key;
+  clib_memset (&key, 0, sizeof (key));
+  key.fwd_entry_index = feip[0];
+  key.tunnel_index = ladj->tunnel_index;
+
+  uword *p = hash_get_mem (lgm->lisp_stats_index_by_key, &key);
+  ASSERT (p);
+
+  /* compute payload length starting after GPE */
+  u32 bytes = b->current_length - (lisp_data - b->data - b->current_data);
+  vlib_increment_combined_counter (&lgm->counters, vlib_get_thread_index (),
+                                  p[0], 1, bytes);
+}
+
 static void
-lisp_gpe_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b)
+lisp_gpe_fixup (vlib_main_t * vm,
+               ip_adjacency_t * adj, vlib_buffer_t * b, const void *data)
 {
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+  if (lcm->flags & LISP_FLAG_STATS_ENABLED)
+    lisp_gpe_increment_stats_counters (lcm, adj, b);
+
   /* Fixup the checksum and len fields in the LISP tunnel encap
    * that was applied at the midchain node */
   ip_udp_fixup_one (vm, b, is_v4_packet (vlib_buffer_get_current (b)));
@@ -258,9 +349,10 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
   linkt = adj_get_link_type (ai);
   adj_nbr_midchain_update_rewrite
     (ai, lisp_gpe_fixup,
+     NULL,
      (VNET_LINK_ETHERNET == linkt ?
-      ADJ_MIDCHAIN_FLAG_NO_COUNT :
-      ADJ_MIDCHAIN_FLAG_NONE),
+      ADJ_FLAG_MIDCHAIN_NO_COUNT :
+      ADJ_FLAG_NONE),
      lisp_gpe_tunnel_build_rewrite (lgt, ladj,
                                    lisp_gpe_adj_proto_from_vnet_link_type
                                    (linkt)));
@@ -303,7 +395,7 @@ lisp_gpe_adjacency_find_or_create_and_lock (const locator_pair_t * pair,
     {
 
       pool_get (lisp_adj_pool, ladj);
-      memset (ladj, 0, sizeof (*ladj));
+      clib_memset (ladj, 0, sizeof (*ladj));
       lai = (ladj - lisp_adj_pool);
 
       ip_address_copy (&ladj->remote_rloc, &pair->rmt_loc);