ip: ip_address_t uses ip46_address_t
[vpp.git] / src / vnet / lisp-gpe / lisp_gpe_adjacency.c
index 1dbf867..cd0b338 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
@@ -43,8 +46,8 @@ BVT (clib_bihash)
 
 #define LISP_ADJ_SET_KEY(_key, _itf, _nh)       \
 {                                              \
-  _key.key[0] = (_nh)->ip.v6.as_u64[0];                \
-  _key.key[1] = (_nh)->ip.v6.as_u64[1];                \
+  _key.key[0] = ip_addr_v6((_nh)).as_u64[0];    \
+  _key.key[1] = ip_addr_v6((_nh)).as_u64[1];    \
   _key.key[2] = (_itf);                                \
 }
 
@@ -96,9 +99,9 @@ lisp_gpe_adj_get_fib_chain_type (const lisp_gpe_adjacency_t * ladj)
 {
   switch (ip_addr_version (&ladj->remote_rloc))
     {
-    case IP4:
+    case AF_IP4:
       return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
-    case IP6:
+    case AF_IP6:
       return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
     default:
       ASSERT (0);
@@ -112,12 +115,12 @@ 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));
-      ip_address_set (b, &a->ip4, IP4);
+      clib_memset (b, 0, sizeof (*b));
+      ip_address_set (b, &a->ip4, AF_IP4);
     }
   else
     {
-      ip_address_set (b, &a->ip6, IP6);
+      ip_address_set (b, &a->ip6, AF_IP6);
     }
 }
 
@@ -128,48 +131,13 @@ static void
 lisp_gpe_adj_stack_one (lisp_gpe_adjacency_t * ladj, adj_index_t ai)
 {
   const lisp_gpe_tunnel_t *lgt;
-  dpo_id_t tmp = DPO_INVALID;
 
   lgt = lisp_gpe_tunnel_get (ladj->tunnel_index);
-  fib_entry_contribute_forwarding (lgt->fib_entry_index,
-                                  lisp_gpe_adj_get_fib_chain_type (ladj),
-                                  &tmp);
 
-  if (DPO_LOAD_BALANCE == tmp.dpoi_type)
-    {
-      /*
-       * post LISP rewrite we will load-balance. However, the LISP encap
-       * is always the same for this adjacency/tunnel and hence the IP/UDP src,dst
-       * hash is always the same result too. So we do that hash now and
-       * stack on the choice.
-       * If the choice is an incomplete adj then we will need a poke when
-       * it becomes complete. This happens since the adj update walk propagates
-       * as far a recursive paths.
-       */
-      const dpo_id_t *choice;
-      load_balance_t *lb;
-      int hash;
-
-      lb = load_balance_get (tmp.dpoi_index);
-
-      if (IP4 == ip_addr_version (&ladj->remote_rloc))
-       {
-         hash = ip4_compute_flow_hash ((ip4_header_t *) adj_get_rewrite (ai),
-                                       lb->lb_hash_config);
-       }
-      else
-       {
-         hash = ip6_compute_flow_hash ((ip6_header_t *) adj_get_rewrite (ai),
-                                       lb->lb_hash_config);
-       }
-
-      choice =
-       load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
-      dpo_copy (&tmp, choice);
-    }
-
-  adj_nbr_midchain_stack (ai, &tmp);
-  dpo_reset (&tmp);
+  adj_nbr_midchain_stack_on_fib_entry (ai,
+                                      lgt->fib_entry_index,
+                                      lisp_gpe_adj_get_fib_chain_type
+                                      (ladj));
 }
 
 /**
@@ -191,7 +159,7 @@ lisp_gpe_adj_stack (lisp_gpe_adjacency_t * ladj)
   fib_protocol_t nh_proto;
   ip46_address_t nh;
 
-  ip_address_to_46 (&ladj->remote_rloc, &nh, &nh_proto);
+  nh_proto = ip_address_to_46 (&ladj->remote_rloc, &nh);
 
   /*
    * walk all the adjacencies on th lisp interface and restack them
@@ -221,9 +189,99 @@ 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,
+                                  const 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);
+  ALWAYS_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,
+               const 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)));
@@ -241,6 +299,7 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
   ip_adjacency_t *adj;
   ip_address_t rloc;
   vnet_link_t linkt;
+  adj_flags_t af;
   index_t lai;
 
   adj = adj_get (ai);
@@ -256,11 +315,12 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
   ladj = pool_elt_at_index (lisp_adj_pool, lai);
   lgt = lisp_gpe_tunnel_get (ladj->tunnel_index);
   linkt = adj_get_link_type (ai);
+  af = ADJ_FLAG_MIDCHAIN_IP_STACK;
+  if (VNET_LINK_ETHERNET == linkt)
+    af |= ADJ_FLAG_MIDCHAIN_NO_COUNT;
+
   adj_nbr_midchain_update_rewrite
-    (ai, lisp_gpe_fixup,
-     (VNET_LINK_ETHERNET == linkt ?
-      ADJ_MIDCHAIN_FLAG_NO_COUNT :
-      ADJ_MIDCHAIN_FLAG_NONE),
+    (ai, lisp_gpe_fixup, NULL, af,
      lisp_gpe_tunnel_build_rewrite (lgt, ladj,
                                    lisp_gpe_adj_proto_from_vnet_link_type
                                    (linkt)));
@@ -303,7 +363,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);
@@ -514,7 +574,7 @@ lisp_gpe_adjacency_show (vlib_main_t * vm,
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) =
 {
-  .path = "show lisp gpe adjacency",
+  .path = "show gpe adjacency",
   .function = lisp_gpe_adjacency_show,
 };
 /* *INDENT-ON* */
@@ -534,7 +594,7 @@ lisp_gpe_adj_module_init (vlib_main_t * vm)
   return (NULL);
 }
 
-VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init)
+VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init);
 /*
  * fd.io coding-style-patch-verification: ON
  *