Edit eid table dump
[vpp.git] / vnet / vnet / lisp-cp / control.c
index 53e8a75..4e955c4 100644 (file)
@@ -601,7 +601,7 @@ vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
     {
       if (table_id || vnip)
         {
-          clib_warning ("vni %d or vrf %d already used in any vrf/vni "
+          clib_warning ("vni %d or vrf %d already used in vrf/vni "
                         "mapping!", vni, vrf);
           return -1;
         }
@@ -692,14 +692,16 @@ compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
 /**
  * Adds/removes/updates mapping. Does not program forwarding.
  *
- * @param deid destination EID
+ * @param eid end-host identifier
  * @param rlocs vector of remote locators
  * @param action action for negative map-reply
  * @param is_add add mapping if non-zero, delete otherwise
+ * @param res_map_index the map-index that was created/updated/removed. It is
+ *                      set to ~0 if no action is taken.
  * @return return code
  */
 int
-vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
+vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
                            u8 authoritative, u32 ttl, u8 is_add,
                            u32 * res_map_index)
 {
@@ -723,14 +725,14 @@ vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
 
   ls_args->locators = rlocs;
 
-  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, deid);
+  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
   old_map = ((u32) ~0 != mi) ? pool_elt_at_index(lcm->mapping_pool, mi) : 0;
 
   if (is_add)
     {
       /* overwrite: if mapping already exists, decide if locators should be
        * updated and be done */
-      if (old_map && gid_address_cmp (&old_map->eid, deid) == 0)
+      if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
         {
           locator_set_t * old_ls;
 
@@ -761,7 +763,7 @@ vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
           vnet_lisp_add_del_locator_set (ls_args, &ls_index);
 
           /* add mapping */
-          gid_address_copy (&m_args->eid, deid);
+          gid_address_copy (&m_args->eid, eid);
           m_args->is_add = 1;
           m_args->action = action;
           m_args->locator_set_index = ls_index;
@@ -773,15 +775,15 @@ vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
     }
   else
     {
-      if (old_map == 0 || gid_address_cmp (&old_map->eid, deid) != 0)
+      if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
         {
           clib_warning("cannot delete mapping for eid %U", format_gid_address,
-                       deid);
+                       eid);
           return -1;
         }
 
       m_args->is_add = 0;
-      gid_address_copy (&m_args->eid, deid);
+      gid_address_copy (&m_args->eid, eid);
       m_args->locator_set_index = old_map->locator_set_index;
 
       /* delete mapping associated from map-cache */
@@ -791,6 +793,10 @@ vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * rlocs, u8 action,
       ls_args->index = old_map->locator_set_index;
       /* delete locator set */
       vnet_lisp_add_del_locator_set (ls_args, 0);
+
+      /* return old mapping index */
+      if (res_map_index)
+        res_map_index[0] = mi;
     }
 
   /* success */
@@ -842,15 +848,15 @@ cleanup:
 }
 
 /**
- * Adds remote mapping and sets it as adjacency for local eid or removes
- * forwarding entry associated to remote mapping. Note that adjacencies
- * are not stored, they only result in forwarding entries being created.
+ * Adds adjacency or removes forwarding entry associated to remote mapping.
+ * Note that adjacencies are not stored, they only result in forwarding entries
+ * being created.
  */
 int
-lisp_add_del_adjacency (lisp_cp_main_t * lcm,
-                             vnet_lisp_add_del_adjacency_args_t * a)
+lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid,
+                        gid_address_t * remote_eid, u8 is_add)
 {
-  u32 src_map_index, dst_map_index = ~0;
+  u32 local_mi, remote_mi = ~0;
 
   if (vnet_lisp_enable_disable_status () == 0)
     {
@@ -858,36 +864,39 @@ lisp_add_del_adjacency (lisp_cp_main_t * lcm,
       return VNET_API_ERROR_LISP_DISABLED;
     }
 
-  /* insert/update mappings cache */
-  vnet_lisp_add_del_mapping (&a->deid, a->locators, a->action,
-                             a->authoritative, a->ttl, a->is_add,
-                             &dst_map_index);
+  remote_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, remote_eid);
+  if (GID_LOOKUP_MISS == remote_mi)
+    {
+      clib_warning("Remote eid %U not found. Cannot add adjacency!",
+                   format_gid_address, remote_eid);
 
-  if (a->is_add)
+      return -1;
+    }
+
+  if (is_add)
     {
       /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
        * delete*/
 
       /* check if source eid has an associated mapping. If pitr mode is on,
        * just use the pitr's mapping */
-      src_map_index = lcm->lisp_pitr ? lcm->pitr_map_index :
-              gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->seid);
+      local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
+              gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
 
 
-      if (GID_LOOKUP_MISS == src_map_index)
+      if (GID_LOOKUP_MISS == local_mi)
         {
-          clib_warning("seid %U not found. Cannot program forwarding!",
-                       format_gid_address, &a->seid);
+          clib_warning("Local eid %U not found. Cannot add adjacency!",
+                       format_gid_address, local_eid);
 
           return -1;
         }
 
-      /* update forwarding if a destination mapping index was found */
-      if ((u32) ~0 != dst_map_index)
-        dp_add_fwd_entry (lcm, src_map_index, dst_map_index);
+      /* update forwarding */
+      dp_add_fwd_entry (lcm, local_mi, remote_mi);
     }
   else
-    dp_del_fwd_entry (lcm, 0, dst_map_index);
+    dp_del_fwd_entry (lcm, 0, remote_mi);
 
   return 0;
 }
@@ -896,7 +905,7 @@ int
 vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
 {
   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
-  return lisp_add_del_adjacency(lcm, a);
+  return lisp_add_del_adjacency(lcm, &a->seid, &a->deid, a->is_add);
 }
 
 /**
@@ -915,26 +924,23 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   clib_error_t * error = 0;
   unformat_input_t _line_input, * line_input = &_line_input;
   u8 is_add = 1, del_all = 0;
-  locator_t rloc, * rlocs = 0;
-  ip_prefix_t * deid_ippref, * seid_ippref;
-  gid_address_t seid, deid;
-  u8 * dmac = gid_address_mac (&deid);
-  u8 * smac = gid_address_mac (&seid);
-  u8 deid_set = 0, seid_set = 0;
+  locator_t rloc, * rlocs = 0, * curr_rloc = 0;
+  ip_prefix_t * eid_ippref;
+  gid_address_t eid;
+  u8 * dmac = gid_address_mac (&eid);
+  u8 eid_set = 0;
   u8 * s = 0;
-  u32 vni, action = ~0;
+  u32 vni, action = ~0, p, w;
   int rv;
 
   /* Get a line of input. */
   if (! unformat_user (input, unformat_line_input, line_input))
     return 0;
 
-  memset(&deid, 0, sizeof(deid));
-  memset(&seid, 0, sizeof(seid));
+  memset(&eid, 0, sizeof(eid));
   memset(&rloc, 0, sizeof(rloc));
 
-  seid_ippref = &gid_address_ippref(&seid);
-  deid_ippref = &gid_address_ippref(&deid);
+  eid_ippref = &gid_address_ippref(&eid);
 
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
@@ -944,37 +950,38 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
         is_add = 0;
       else if (unformat (line_input, "add"))
         ;
-      else if (unformat (line_input, "deid %U",
-                         unformat_ip_prefix, deid_ippref))
+      else if (unformat (line_input, "eid %U",
+                         unformat_ip_prefix, eid_ippref))
         {
-          gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
-          deid_set = 1;
+          gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
+          eid_set = 1;
         }
-      else if (unformat (line_input, "deid %U",
+      else if (unformat (line_input, "eid %U",
                          unformat_mac_address, dmac))
         {
-          gid_address_type (&deid) = GID_ADDR_MAC;
-          deid_set = 1;
+          gid_address_type (&eid) = GID_ADDR_MAC;
+          eid_set = 1;
         }
       else if (unformat (line_input, "vni %u", &vni))
         {
-          gid_address_vni (&seid) = vni;
-          gid_address_vni (&deid) = vni;
+          gid_address_vni (&eid) = vni;
         }
-      else if (unformat (line_input, "seid %U",
-                         unformat_ip_prefix, seid_ippref))
+      else if (unformat (line_input, "p %d w %d", &p, &w))
         {
-          gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
-          seid_set = 1;
+          if (!curr_rloc)
+            {
+              clib_warning ("No RLOC configured for setting priority/weight!");
+              goto done;
+            }
+          curr_rloc->priority = p;
+          curr_rloc->weight = w;
         }
-      else if (unformat (line_input, "seid %U",
-                         unformat_mac_address, smac))
+      else if (unformat (line_input, "rloc %U", unformat_ip_address,
+                         &rloc.address))
         {
-          gid_address_type (&seid) = GID_ADDR_MAC;
-          seid_set = 1;
+          vec_add1 (rlocs, rloc);
+          curr_rloc = &rlocs[vec_len (rlocs) - 1];
         }
-      else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc.address))
-        vec_add1 (rlocs, rloc);
       else if (unformat (line_input, "action %s", &s))
         {
           if (!strcmp ((char *)s, "no-action"))
@@ -998,31 +1005,15 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
         }
     }
 
-  if (!del_all)
+  if (!eid_set)
     {
-      if (!deid_set)
-        {
-          clib_warning ("missing deid!");
-          goto done;
-        }
+      clib_warning ("missing eid!");
+      goto done;
+    }
 
-      if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
-        {
-          /* if seid not set, make sure the ip version is the same as that
-           * of the deid. This ensures the seid to be configured will be
-           * either 0/0 or ::/0 */
-          if (!seid_set)
-            ip_prefix_version(seid_ippref) = ip_prefix_version(deid_ippref);
+  if (!del_all)
+    {
 
-          if (is_add &&
-              (ip_prefix_version (deid_ippref)
-               != ip_prefix_version(seid_ippref)))
-            {
-              clib_warning ("source and destination EIDs are not"
-                            " in the same IP family!");
-              goto done;
-            }
-        }
 
       if (is_add && (~0 == action)
           && 0 == vec_len (rlocs))
@@ -1043,22 +1034,22 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   if (!is_add)
     {
       lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
-      vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
-      gid_address_copy(&a->deid, &deid);
-      a->is_add = 0;
-      rv = lisp_add_del_adjacency (lcm, a);
-    }
-  else
-    {
-      /* add as static remote mapping, i.e., not authoritative and infinite
-       * ttl */
-      rv = vnet_lisp_add_del_mapping (&deid, rlocs, action, 0, ~0, is_add, 0);
+      rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0);
+      if (rv)
+        {
+          goto done;
+        }
     }
 
+  /* add as static remote mapping, i.e., not authoritative and infinite
+   * ttl */
+  rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, 0);
+
   if (rv)
     clib_warning("failed to %s remote mapping!", is_add ? "add" : "delete");
 
 done:
+  vec_free (rlocs);
   unformat_free (line_input);
   if (s)
     vec_free (s);
@@ -1067,8 +1058,8 @@ done:
 
 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = {
     .path = "lisp remote-mapping",
-    .short_help = "lisp remote-mapping add|del [del-all] vni <vni>"
-     "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
+    .short_help = "lisp remote-mapping add|del [del-all] vni <vni> "
+     "eid <est-eid> [action <no-action|natively-forward|"
      "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
     .function = lisp_add_del_remote_mapping_command_fn,
 };
@@ -1140,24 +1131,6 @@ lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
           gid_address_type (&seid) = GID_ADDR_MAC;
           seid_set = 1;
         }
-      else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc.address))
-        vec_add1 (rlocs, rloc);
-      else if (unformat (line_input, "action %s", &s))
-        {
-          if (!strcmp ((char *)s, "no-action"))
-            action = ACTION_NONE;
-          if (!strcmp ((char *)s, "natively-forward"))
-            action = ACTION_NATIVELY_FORWARDED;
-          if (!strcmp ((char *)s, "send-map-request"))
-            action = ACTION_SEND_MAP_REQUEST;
-          else if (!strcmp ((char *)s, "drop"))
-            action = ACTION_DROP;
-          else
-            {
-              clib_warning ("invalid action: '%s'", s);
-              goto done;
-            }
-        }
       else
         {
           clib_warning ("parse error");
@@ -1197,14 +1170,10 @@ lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
     }
 
   memset(a, 0, sizeof(a[0]));
-  a->action = action;
-  a->is_add = is_add;
-
-  /* NOTE: the remote mapping is static, i.e.,  not authoritative and
-   * ttl is infinite. */
-  a->authoritative = 0;
-  a->ttl = ~0;
+  gid_address_copy (&a->seid, &deid);
+  gid_address_copy (&a->deid, &seid);
 
+  a->is_add = is_add;
   rv = vnet_lisp_add_del_adjacency (a);
 
   if (rv)
@@ -1340,14 +1309,61 @@ VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
     .function = lisp_pitr_set_locator_set_command_fn,
 };
 
+static clib_error_t *
+lisp_show_pitr_command_fn (vlib_main_t * vm,
+                           unformat_input_t * input,
+                           vlib_cli_command_t * cmd)
+{
+  lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+  mapping_t * m;
+  locator_set_t * ls;
+  u8 * tmp_str = 0;
+
+  vlib_cli_output (vm, "%=20s%=16s",
+                   "pitr", lcm->lisp_pitr ? "locator-set" : "");
+
+  if (!lcm->lisp_pitr) {
+    vlib_cli_output (vm, "%=20s", "disable");
+    return 0;
+  }
+
+  if (~0 == lcm->pitr_map_index) {
+    tmp_str = format(0, "N/A");
+  } else {
+    m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
+    if (~0 != m->locator_set_index) {
+      ls = pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
+      tmp_str = format(0, "%s", ls->name);
+    } else {
+      tmp_str = format(0, "N/A");
+    }
+  }
+  vec_add1(tmp_str, 0);
+
+  vlib_cli_output (vm, "%=20s%=16s",
+                   "enable", tmp_str);
+
+  vec_free(tmp_str);
+
+  return 0;
+}
+
+VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
+    .path = "show lisp pitr",
+    .short_help = "Show pitr",
+    .function = lisp_show_pitr_command_fn,
+};
 
 static u8 *
 format_eid_entry (u8 * s, va_list * args)
 {
   vnet_main_t * vnm = va_arg (*args, vnet_main_t *);
   lisp_cp_main_t * lcm = va_arg (*args, lisp_cp_main_t *);
-  gid_address_t * gid = va_arg (*args, gid_address_t *);
+  mapping_t * mapit = va_arg (*args, mapping_t *);
   locator_set_t * ls = va_arg (*args, locator_set_t *);
+  gid_address_t * gid = &mapit->eid;
+  u32 ttl = mapit->ttl;
+  u8 aut = mapit->authoritative;
   u32 * loc_index;
   u8 first_line = 1;
   u8 * loc;
@@ -1357,7 +1373,8 @@ format_eid_entry (u8 * s, va_list * args)
 
   if (vec_len (ls->locator_indices) == 0)
     {
-      s = format (s, "%-35U%-20s", format_gid_address, gid, type);
+      s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
+                                           type, ttl, aut);
     }
   else
     {
@@ -1373,8 +1390,8 @@ format_eid_entry (u8 * s, va_list * args)
 
           if (first_line)
             {
-              s = format (s, "%-35U%-20s%-v\n", format_gid_address,
-                          gid, type, loc);
+              s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
+                          gid, type, loc, ttl, aut);
               first_line = 0;
             }
           else
@@ -1395,6 +1412,7 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm,
   u32 mi;
   gid_address_t eid;
   u8 print_all = 1;
+  u8 filter = 0;
 
   memset (&eid, 0, sizeof(eid));
 
@@ -1406,12 +1424,17 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm,
     {
       if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
         print_all = 0;
+      else if (unformat (line_input, "local"))
+        filter = 1;
+      else if (unformat(line_input, "remote"))
+        filter = 2;
       else
         return clib_error_return (0, "parse error: '%U'",
                                   format_unformat_error, line_input);
     }
 
-  vlib_cli_output (vm, "%-35s%-20s%-s", "EID", "type", "locators");
+  vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
+                   "EID", "type", "locators", "ttl", "autoritative");
 
   if (print_all)
     {
@@ -1419,8 +1442,13 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm,
       ({
         locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
                                                 mapit->locator_set_index);
+        if (filter && !((1 == filter && ls->local) ||
+          (2 == filter && !ls->local)))
+          {
+            continue;
+          }
         vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
-                         lcm, &mapit->eid, ls);
+                         lcm, mapit, ls);
       }));
     }
   else
@@ -1432,8 +1460,15 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm,
       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
       locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
                                               mapit->locator_set_index);
-      vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
-                       lcm, &mapit->eid, ls);
+
+      if (filter && !((1 == filter && ls->local) ||
+        (2 == filter && !ls->local)))
+        {
+          return 0;
+        }
+
+      vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
+                       lcm, mapit, ls);
     }
 
   return 0;
@@ -1520,8 +1555,8 @@ is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
   vec_foreach(locit, ls->locator_indices)
     {
       itloc = pool_elt_at_index(lcm->locator_pool, locit[0]);
-      if (itloc->sw_if_index == loc->sw_if_index ||
-          !gid_address_cmp(&itloc->address, &loc->address))
+      if ((ls->local && itloc->sw_if_index == loc->sw_if_index) ||
+          (!ls->local && !gid_address_cmp(&itloc->address, &loc->address)))
         {
           clib_warning("Duplicate locator");
           return VNET_API_ERROR_VALUE_EXIST;
@@ -2057,7 +2092,14 @@ lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
   ({
     u8 * msg = 0;
     int next_line = 0;
-    msg = format (msg, "%=16v", lsit->name);
+    if (lsit->local)
+      {
+        msg = format (msg, "%=16v", lsit->name);
+      }
+    else
+      {
+        msg = format (msg, "%=16s", "remote");
+      }
     vec_foreach (locit, lsit->locator_indices)
       {
         if (next_line)
@@ -2070,7 +2112,7 @@ lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
                         loc->weight);
         else
           msg = format (msg, "%16U%16d%16d\n", format_ip_address,
-                        gid_address_ip(&loc->address), loc->priority,
+                        &gid_address_ip(&loc->address), loc->priority,
                         loc->weight);
         next_line = 1;
       }
@@ -2133,7 +2175,7 @@ lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
                                       vlib_cli_command_t * cmd)
 {
   unformat_input_t _line_input, * line_input = &_line_input;
-  u8 is_add = 1;
+  u8 is_add = 1, addr_set = 0;
   ip_address_t ip_addr;
   clib_error_t * error = 0;
   int rv = 0;
@@ -2150,13 +2192,20 @@ lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
       else if (unformat (line_input, "del"))
         is_add = 0;
       else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
-        ;
+        addr_set = 1;
       else
         {
           error = unformat_parse_error(line_input);
           goto done;
         }
     }
+
+  if (!addr_set)
+    {
+      error = clib_error_return(0, "Map-resolver address must be set!");
+      goto done;
+    }
+
   a->is_add = is_add;
   a->address = ip_addr;
   rv = vnet_lisp_add_del_map_resolver (a);
@@ -2385,6 +2434,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
        addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
        ip_address_set (rloc, addr, IP4);
         ip_prefix_len (ippref) = 32;
+        ip_prefix_normalize (ippref);
         vec_add1 (rlocs, gid[0]);
       }));
 
@@ -2395,6 +2445,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
         addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
         ip_address_set (rloc, addr, IP6);
         ip_prefix_len (ippref) = 128;
+        ip_prefix_normalize (ippref);
         vec_add1 (rlocs, gid[0]);
       }));
     }
@@ -2752,7 +2803,7 @@ format_lisp_cp_input_trace (u8 * s, va_list * args)
 void
 process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
 {
-  u32 len = 0, i, ttl;
+  u32 len = 0, i, ttl, dst_map_index = 0;
   void * h;
   pending_map_request_t * pmr;
   locator_t probed;
@@ -2762,7 +2813,6 @@ process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
   uword * pmr_index;
   u8 authoritative, action;
   locator_t * locators = 0, * loc;
-  vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
 
   mrep_hdr = vlib_buffer_get_current (b);
 
@@ -2798,16 +2848,13 @@ process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
           return;
         }
 
-      memset(a, 0, sizeof(*a));
-      a->action = action;
-      a->authoritative = authoritative;
-      a->ttl = ttl;
-      a->locators = locators;
-      gid_address_copy(&a->seid, &pmr->src);
-      gid_address_copy(&a->deid, &deid);
-      a->is_add = 1;
+      /* insert/update mappings cache */
+      vnet_lisp_add_del_mapping (&deid, locators, action, authoritative, ttl, 1,
+                                 &dst_map_index);
 
-      lisp_add_del_adjacency (lcm, a);
+      /* try to program forwarding only if mapping saved or updated*/
+      if ((u32) ~0 != dst_map_index)
+        lisp_add_del_adjacency (lcm, &pmr->src, &deid, 1);
 
       vec_free(locators);
     }