API: Add service definitions for events and singleton messages.
[vpp.git] / src / vnet / map / map.c
index d246f6c..702b5f8 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "map.h"
 
+map_main_t map_main;
+
 /*
  * This code supports the following MAP modes:
  *
@@ -83,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
     {
@@ -98,7 +106,8 @@ map_create_domain (ip4_address_t * ip4_prefix,
   /* How many, and which bits to grab from the IPv4 DA */
   if (ip4_prefix_len + ea_bits_len < 32)
     {
-      flags |= MAP_DOMAIN_PREFIX;
+      if (!(flags & MAP_DOMAIN_TRANSLATION))
+       flags |= MAP_DOMAIN_PREFIX;
       suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
       suffix_len = ea_bits_len;
     }
@@ -118,6 +127,12 @@ map_create_domain (ip4_address_t * ip4_prefix,
       return -1;
     }
 
+  if (mm->is_ce && !(flags & MAP_DOMAIN_TRANSLATION))
+    {
+      clib_warning ("MAP-E CE is not supported yet");
+      return -1;
+    }
+
   /* Get domain index */
   pool_get_aligned (mm->domains, d, CLIB_CACHE_LINE_BYTES);
   memset (d, 0, sizeof (*d));
@@ -149,11 +164,23 @@ map_create_domain (ip4_address_t * ip4_prefix,
     map_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4);
 
   /* Create ip4 route */
+  u8 ip4_pfx_len;
+  ip4_address_t ip4_pfx;
+  if (mm->is_ce)
+    {
+      ip4_pfx_len = 0;
+      ip4_pfx.as_u32 = 0;
+    }
+  else
+    {
+      ip4_pfx_len = d->ip4_prefix_len;
+      ip4_pfx = d->ip4_prefix;
+    }
   fib_prefix_t pfx = {
     .fp_proto = FIB_PROTOCOL_IP4,
-    .fp_len = d->ip4_prefix_len,
+    .fp_len = ip4_pfx_len,
     .fp_addr = {
-               .ip4 = d->ip4_prefix,
+               .ip4 = ip4_pfx,
                }
     ,
   };
@@ -179,10 +206,22 @@ map_create_domain (ip4_address_t * ip4_prefix,
    * already exists and is MAP sourced, it is now MAP source n+1 times
    * and will need to be removed n+1 times.
    */
+  u8 ip6_pfx_len;
+  ip6_address_t ip6_pfx;
+  if (mm->is_ce)
+    {
+      ip6_pfx_len = d->ip6_prefix_len;
+      ip6_pfx = d->ip6_prefix;
+    }
+  else
+    {
+      ip6_pfx_len = d->ip6_src_len;
+      ip6_pfx = d->ip6_src;
+    }
   fib_prefix_t pfx6 = {
     .fp_proto = FIB_PROTOCOL_IP6,
-    .fp_len = d->ip6_src_len,
-    .fp_addr.ip6 = d->ip6_src,
+    .fp_len = ip6_pfx_len,
+    .fp_addr.ip6 = ip6_pfx,
   };
 
   fib_table_entry_special_dpo_add (0, &pfx6,
@@ -317,9 +356,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)
     {
@@ -354,9 +393,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)));
@@ -586,6 +623,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'",
@@ -919,6 +958,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)
 {
@@ -933,13 +984,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)
     {
@@ -1106,7 +1158,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, ({
@@ -2122,7 +2177,7 @@ VLIB_CLI_COMMAND(map_add_domain_command, static) = {
   .path = "map add domain",
   .short_help = "map add domain ip4-pfx <ip4-pfx> ip6-pfx <ip6-pfx> "
       "ip6-src <ip6-pfx> ea-bits-len <n> psid-offset <n> psid-len <n> "
-      "[map-t] [mtu <mtu>]",
+      "[map-t] [map-ce] [mtu <mtu>]",
   .function = map_add_domain_command_fn,
 };
 
@@ -2192,6 +2247,28 @@ VLIB_CLI_COMMAND(show_map_fragments_command, static) = {
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+map_config (vlib_main_t * vm, unformat_input_t * input)
+{
+  map_main_t *mm = &map_main;
+  u8 is_ce = false;
+
+  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (input, "customer edge"))
+       is_ce = true;
+      else
+       return clib_error_return (0, "unknown input '%U'",
+                                 format_unformat_error, input);
+    }
+
+  mm->is_ce = is_ce;
+
+  return 0;
+}
+
+VLIB_CONFIG_FUNCTION (map_config, "map");
+
 /*
  * map_init
  */
@@ -2222,6 +2299,8 @@ map_init (vlib_main_t * vm)
   /* ICMP6 Type 1, Code 5 for security check failure */
   mm->icmp6_enabled = false;
 
+  mm->is_ce = false;
+
   /* Inner or outer fragmentation */
   mm->frag_inner = false;
   mm->frag_ignore_df = false;
@@ -2238,6 +2317,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;
@@ -2253,6 +2333,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;