MAP: Add RFC6052 mapping to MAP-T
[vpp.git] / src / vnet / map / map.c
index 8579cdf..b2eefee 100644 (file)
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/adj/adj.h>
 #include <vnet/map/map_dpo.h>
+#include <vppinfra/crc32.h>
 
 #include "map.h"
 
-#ifdef __SSE4_2__
-static inline u32
-crc_u32 (u32 data, u32 value)
-{
-  __asm__ volatile ("crc32l %[data], %[value];":[value] "+r" (value):[data]
-                   "rm" (data));
-  return value;
-}
-#else
-#include <vppinfra/xxhash.h>
-
-static inline u32
-crc_u32 (u32 data, u32 value)
-{
-  u64 tmp = ((u64) data << 32) | (u64) value;
-  return (u32) clib_xxhash (tmp);
-}
-#endif
-
+map_main_t map_main;
 
 /*
  * This code supports the following MAP modes:
@@ -102,6 +85,12 @@ map_create_domain (ip4_address_t * ip4_prefix,
          clib_warning ("MAP-T only supports ip6_src_len = 96 for now.");
          return -1;
        }
+      if ((flags & MAP_DOMAIN_RFC6052) && ip6_prefix_len != 96)
+       {
+         clib_warning ("RFC6052 translation only supports ip6_prefix_len = "
+                       "96 for now");
+         return -1;
+       }
     }
   else
     {
@@ -336,9 +325,9 @@ map_pre_resolve_init (map_main_pre_resolved_t * pr)
 }
 
 static u8 *
-format_map_pre_resolve (u8 * s, va_list ap)
+format_map_pre_resolve (u8 * s, va_list ap)
 {
-  map_main_pre_resolved_t *pr = va_arg (ap, map_main_pre_resolved_t *);
+  map_main_pre_resolved_t *pr = va_arg (*ap, map_main_pre_resolved_t *);
 
   if (FIB_NODE_INDEX_INVALID != pr->fei)
     {
@@ -373,9 +362,7 @@ map_last_lock_gone (fib_node_t * node)
 static map_main_pre_resolved_t *
 map_from_fib_node (fib_node_t * node)
 {
-#if (CLIB_DEBUG > 0)
   ASSERT (FIB_NODE_TYPE_MAP_E == node->fn_type);
-#endif
   return ((map_main_pre_resolved_t *)
          (((char *) node) -
           STRUCT_OFFSET_OF (map_main_pre_resolved_t, node)));
@@ -605,6 +592,8 @@ map_add_domain_command_fn (vlib_main_t * vm,
        num_m_args++;
       else if (unformat (line_input, "map-t"))
        flags |= MAP_DOMAIN_TRANSLATION;
+      else if (unformat (line_input, "rfc6052"))
+       flags |= (MAP_DOMAIN_TRANSLATION | MAP_DOMAIN_RFC6052);
       else
        {
          error = clib_error_return (0, "unknown input `%U'",
@@ -938,6 +927,18 @@ done:
   return error;
 }
 
+static char *
+map_flags_to_string (u32 flags)
+{
+  if (flags & MAP_DOMAIN_RFC6052)
+    return "rfc6052";
+  if (flags & MAP_DOMAIN_PREFIX)
+    return "prefix";
+  if (flags & MAP_DOMAIN_TRANSLATION)
+    return "map-t";
+  return "";
+}
+
 static u8 *
 format_map_domain (u8 * s, va_list * args)
 {
@@ -952,13 +953,14 @@ format_map_domain (u8 * s, va_list * args)
     ip6_prefix = d->ip6_prefix;
 
   s = format (s,
-             "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d psid-offset %d psid-len %d mtu %d %s",
+             "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d "
+             "psid-offset %d psid-len %d mtu %d %s",
              d - mm->domains,
              format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len,
              format_ip6_address, &ip6_prefix, d->ip6_prefix_len,
              format_ip6_address, &d->ip6_src, d->ip6_src_len,
              d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu,
-             (d->flags & MAP_DOMAIN_TRANSLATION) ? "map-t" : "");
+             map_flags_to_string (d->flags));
 
   if (counters)
     {
@@ -1125,7 +1127,10 @@ show_map_stats_command_fn (vlib_main_t * vm, unformat_input_t * input,
   map_domain_t *d;
   int domains = 0, rules = 0, domaincount = 0, rulecount = 0;
   if (pool_elts (mm->domains) == 0)
-    vlib_cli_output (vm, "No MAP domains are configured...");
+    {
+      vlib_cli_output (vm, "No MAP domains are configured...");
+      return 0;
+    }
 
   /* *INDENT-OFF* */
   pool_foreach(d, mm->domains, ({
@@ -1488,10 +1493,12 @@ map_ip4_reass_get (u32 src, u32 dst, u16 fragment_id,
   };
 
   u32 h = 0;
-  h = crc_u32 (k.as_u32[0], h);
-  h = crc_u32 (k.as_u32[1], h);
-  h = crc_u32 (k.as_u32[2], h);
-  h = crc_u32 (k.as_u32[3], h);
+#ifdef clib_crc32c_uses_intrinsics
+  h = clib_crc32c ((u8 *) k.as_u32, 16);
+#else
+  u64 tmp = k.as_u32[0] ^ k.as_u32[1] ^ k.as_u32[2] ^ k.as_u32[3];
+  h = clib_xxhash (tmp);
+#endif
   h = h >> (32 - mm->ip4_reass_ht_log2len);
 
   f64 now = vlib_time_now (mm->vlib_main);
@@ -1660,8 +1667,15 @@ map_ip6_reass_get (ip6_address_t * src, ip6_address_t * dst, u32 fragment_id,
 
   u32 h = 0;
   int i;
-  for (i = 0; i < 10; i++)
-    h = crc_u32 (k.as_u32[i], h);
+
+#ifdef clib_crc32c_uses_intrinsics
+  h = clib_crc32c ((u8 *) k.as_u32, 40);
+#else
+  u64 tmp =
+    k.as_u64[0] ^ k.as_u64[1] ^ k.as_u64[2] ^ k.as_u64[3] ^ k.as_u64[4];
+  h = clib_xxhash (tmp);
+#endif
+
   h = h >> (32 - mm->ip6_reass_ht_log2len);
 
   f64 now = vlib_time_now (mm->vlib_main);
@@ -2248,6 +2262,7 @@ map_init (vlib_main_t * vm)
   mm->ip4_reass_pool = 0;
   mm->ip4_reass_lock =
     clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES);
+  *mm->ip4_reass_lock = 0;
   mm->ip4_reass_conf_ht_ratio = MAP_IP4_REASS_HT_RATIO_DEFAULT;
   mm->ip4_reass_conf_lifetime_ms = MAP_IP4_REASS_LIFETIME_DEFAULT;
   mm->ip4_reass_conf_pool_size = MAP_IP4_REASS_POOL_SIZE_DEFAULT;
@@ -2263,6 +2278,7 @@ map_init (vlib_main_t * vm)
   mm->ip6_reass_pool = 0;
   mm->ip6_reass_lock =
     clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES);
+  *mm->ip6_reass_lock = 0;
   mm->ip6_reass_conf_ht_ratio = MAP_IP6_REASS_HT_RATIO_DEFAULT;
   mm->ip6_reass_conf_lifetime_ms = MAP_IP6_REASS_LIFETIME_DEFAULT;
   mm->ip6_reass_conf_pool_size = MAP_IP6_REASS_POOL_SIZE_DEFAULT;