MAP - add the domain struct directly into the dat-path and avoid the indirectiob...
[vpp.git] / src / vnet / map / map.c
index 6823a46..811a0ab 100644 (file)
@@ -177,7 +177,6 @@ map_create_domain (ip4_address_t * ip4_prefix,
   map_main_t *mm = &map_main;
   dpo_id_t dpo_v4 = DPO_INVALID;
   dpo_id_t dpo_v6 = DPO_INVALID;
-  fib_node_index_t fei;
   map_domain_t *d;
 
   /* Sanity check on the src prefix length */
@@ -268,57 +267,28 @@ map_create_domain (ip4_address_t * ip4_prefix,
   dpo_reset (&dpo_v4);
 
   /*
-   * Multiple MAP domains may share same source IPv6 TEP.
-   * In this case the route will exist and be MAP sourced.
-   * Find the adj (if any) already contributed and modify it
+   * construct a DPO to use the v6 domain
    */
-  fib_prefix_t pfx6 = {
-    .fp_proto = FIB_PROTOCOL_IP6,
-    .fp_len = d->ip6_src_len,
-    .fp_addr = {
-               .ip6 = d->ip6_src,
-               }
-    ,
-  };
-  fei = fib_table_lookup_exact_match (0, &pfx6);
-
-  if (FIB_NODE_INDEX_INVALID != fei)
-    {
-      dpo_id_t dpo = DPO_INVALID;
-
-      if (fib_entry_get_dpo_for_source (fei, FIB_SOURCE_MAP, &dpo))
-       {
-         /*
-          * modify the existing MAP to indicate it's shared
-          * skip to route add.
-          */
-         const dpo_id_t *md_dpo;
-         map_dpo_t *md;
-
-         ASSERT (DPO_LOAD_BALANCE == dpo.dpoi_type);
-
-         md_dpo = load_balance_get_bucket (dpo.dpoi_index, 0);
-         md = map_dpo_get (md_dpo->dpoi_index);
-
-         md->md_domain = ~0;
-         dpo_copy (&dpo_v6, md_dpo);
-         dpo_reset (&dpo);
-
-         goto route_add;
-       }
-    }
-
   if (d->flags & MAP_DOMAIN_TRANSLATION)
     map_t_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
   else
     map_dpo_create (DPO_PROTO_IP6, *map_domain_index, &dpo_v6);
 
-route_add:
   /*
+   * Multiple MAP domains may share same source IPv6 TEP. Which is just dandy.
+   * We are not tracking the sharing. So a v4 lookup to find the correct
+   * domain post decap/trnaslate is always done
+   *
    * Create ip6 route. This is a reference counted add. If the prefix
    * already exists and is MAP sourced, it is now MAP source n+1 times
    * and will need to be removed n+1 times.
    */
+  fib_prefix_t pfx6 = {
+    .fp_proto = FIB_PROTOCOL_IP6,
+    .fp_len = d->ip6_src_len,
+    .fp_addr.ip6 = d->ip6_src,
+  };
+
   fib_table_entry_special_dpo_add (0, &pfx6,
                                   FIB_SOURCE_MAP,
                                   FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v6);
@@ -556,23 +526,51 @@ map_fib_resolve (map_main_pre_resolved_t * pr,
 }
 
 static void
-map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6)
+map_fib_unresolve (map_main_pre_resolved_t * pr,
+                  fib_protocol_t proto, u8 len, const ip46_address_t * addr)
+{
+  fib_prefix_t pfx = {
+    .fp_proto = proto,
+    .fp_len = len,
+    .fp_addr = *addr,
+  };
+
+  fib_entry_child_remove (pr->fei, pr->sibling);
+
+  fib_table_entry_special_remove (0,   // default fib
+                                 &pfx, FIB_SOURCE_RR);
+  dpo_reset (&pr->dpo);
+
+  pr->fei = FIB_NODE_INDEX_INVALID;
+  pr->sibling = FIB_NODE_INDEX_INVALID;
+}
+
+static void
+map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, int is_del)
 {
   if (ip6 && (ip6->as_u64[0] != 0 || ip6->as_u64[1] != 0))
     {
       ip46_address_t addr = {
        .ip6 = *ip6,
       };
-      map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
-                      FIB_PROTOCOL_IP6, 128, &addr);
+      if (is_del)
+       map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP6],
+                          FIB_PROTOCOL_IP6, 128, &addr);
+      else
+       map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP6],
+                        FIB_PROTOCOL_IP6, 128, &addr);
     }
   if (ip4 && (ip4->as_u32 != 0))
     {
       ip46_address_t addr = {
        .ip4 = *ip4,
       };
-      map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
-                      FIB_PROTOCOL_IP4, 32, &addr);
+      if (is_del)
+       map_fib_unresolve (&pre_resolved[FIB_PROTOCOL_IP4],
+                          FIB_PROTOCOL_IP4, 32, &addr);
+      else
+       map_fib_resolve (&pre_resolved[FIB_PROTOCOL_IP4],
+                        FIB_PROTOCOL_IP4, 32, &addr);
     }
 }
 #endif
@@ -817,6 +815,7 @@ map_pre_resolve_command_fn (vlib_main_t * vm,
   ip4_address_t ip4nh, *p_v4 = NULL;
   ip6_address_t ip6nh, *p_v6 = NULL;
   clib_error_t *error = NULL;
+  int is_del = 0;
 
   memset (&ip4nh, 0, sizeof (ip4nh));
   memset (&ip6nh, 0, sizeof (ip6nh));
@@ -832,6 +831,8 @@ map_pre_resolve_command_fn (vlib_main_t * vm,
       else
        if (unformat (line_input, "ip6-nh %U", unformat_ip6_address, &ip6nh))
        p_v6 = &ip6nh;
+      else if (unformat (line_input, "del"))
+       is_del = 1;
       else
        {
          error = clib_error_return (0, "unknown input `%U'",
@@ -840,7 +841,7 @@ map_pre_resolve_command_fn (vlib_main_t * vm,
        }
     }
 
-  map_pre_resolve (p_v4, p_v6);
+  map_pre_resolve (p_v4, p_v6, is_del);
 
 done:
   unformat_free (line_input);
@@ -1273,7 +1274,7 @@ show_map_stats_command_fn (vlib_main_t * vm, unformat_input_t * input,
   {
     which = cm - mm->domain_counters;
 
-    for (i = 0; i < vec_len (cm->maxi); i++)
+    for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
       {
        vlib_get_combined_counter (cm, i, &v);
        total_pkts[which] += v.packets;