API support for src/dst based routing policy in LISP
[vpp.git] / vnet / vnet / lisp-cp / control.c
index 824046c..9b86da5 100644 (file)
@@ -142,20 +142,32 @@ ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
 }
 
 static int
-dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_add)
+dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
 {
-  uword * table_id, * intf;
+  uword * dp_table, * intf;
   vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
 
-  table_id = hash_get(lcm->table_id_by_vni, vni);
+  if (!is_l2)
+    {
+      dp_table = hash_get(lcm->table_id_by_vni, vni);
 
-  if (!table_id)
+      if (!dp_table)
+        {
+          clib_warning("vni %d not associated to a vrf!", vni);
+          return VNET_API_ERROR_INVALID_VALUE;
+        }
+    }
+  else
     {
-      clib_warning ("vni %d not associated to a vrf!", vni);
-      return VNET_API_ERROR_INVALID_VALUE;
+      dp_table = hash_get(lcm->bd_id_by_vni, vni);
+      if (!dp_table)
+        {
+          clib_warning("vni %d not associated to a bridge domain!", vni);
+          return VNET_API_ERROR_INVALID_VALUE;
+        }
     }
 
-  intf = hash_get(lcm->dp_intf_by_vni, vni);
+  intf = hash_get(is_l2 ? lcm->l2_dp_intf_by_vni :lcm->dp_intf_by_vni, vni);
 
   /* enable/disable data-plane interface */
   if (is_add)
@@ -165,7 +177,9 @@ dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_add)
         {
           ai->is_add = 1;
           ai->vni = vni;
-          ai->table_id = table_id[0];
+          ai->is_l2 = is_l2;
+          ai->dp_table = dp_table[0];
+
           vnet_lisp_gpe_add_del_iface (ai, 0);
 
           /* keep track of vnis for which interfaces have been created */
@@ -182,7 +196,7 @@ dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_add)
 
       ai->is_add = 0;
       ai->vni = vni;
-      ai->table_id = table_id[0];
+      ai->dp_table = dp_table[0];
       vnet_lisp_gpe_add_del_iface (ai, 0);
       hash_unset(lcm->dp_intf_by_vni, vni);
     }
@@ -207,10 +221,10 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
   /* delete dp fwd entry */
   u32 sw_if_index;
   a->is_add = 0;
-  a->dlocator = fe->dst_loc;
-  a->slocator = fe->src_loc;
-  a->vni = gid_address_vni(&a->deid);
-  gid_address_copy(&a->deid, &fe->deid);
+  a->rmt_loc = fe->dst_loc;
+  a->lcl_loc = fe->src_loc;
+  a->vni = gid_address_vni(&a->rmt_eid);
+  gid_address_copy(&a->rmt_eid, &fe->deid);
 
   vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
 
@@ -305,11 +319,12 @@ get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map,
 static void
 dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
 {
+  vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
   mapping_t * src_map, * dst_map;
   u32 sw_if_index;
-  uword * feip = 0, * tidp;
+  uword * feip = 0, * dpid;
   fwd_entry_t* fe;
-  vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
+  u8 type;
 
   memset (a, 0, sizeof(*a));
 
@@ -321,22 +336,37 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
   src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
   dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
 
-  gid_address_copy (&a->deid, &dst_map->eid);
-  a->vni = gid_address_vni(&a->deid);
+  /* insert data plane forwarding entry */
+  a->is_add = 1;
+
+  gid_address_copy (&a->rmt_eid, &dst_map->eid);
+  a->vni = gid_address_vni(&a->rmt_eid);
 
-  tidp = hash_get(lcm->table_id_by_vni, a->vni);
-  if (!tidp)
+  /* get vrf or bd_index associated to vni */
+  type = gid_address_type(&dst_map->eid);
+  if (GID_ADDR_IP_PREFIX == type)
     {
-      clib_warning("vni %d not associated to a vrf!", a->vni);
-      return;
+      dpid = hash_get(lcm->table_id_by_vni, a->vni);
+      if (!dpid)
+        {
+          clib_warning("vni %d not associated to a vrf!", a->vni);
+          return;
+        }
+      a->table_id = dpid[0];
+    }
+  else if (GID_ADDR_MAC == type)
+    {
+      dpid = hash_get(lcm->bd_id_by_vni, a->vni);
+      if (!dpid)
+        {
+          clib_warning("vni %d not associated to a bridge domain !", a->vni);
+          return;
+        }
+      a->bd_id = dpid[0];
     }
-  a->table_id = tidp[0];
-
-  /* insert data plane forwarding entry */
-  a->is_add = 1;
 
   /* find best locator pair that 1) verifies LISP policy 2) are connected */
-  if (0 == get_locator_pair (lcm, src_map, dst_map, &a->slocator, &a->dlocator))
+  if (0 == get_locator_pair (lcm, src_map, dst_map, &a->lcl_loc, &a->rmt_loc))
     {
       /* negative entry */
       a->is_negative = 1;
@@ -344,7 +374,7 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
     }
 
   /* TODO remove */
-  u8 ipver = ip_prefix_version(&gid_address_ippref(&a->deid));
+  u8 ipver = ip_prefix_version(&gid_address_ippref(&a->rmt_eid));
   a->decap_next_index = (ipver == IP4) ?
           LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
 
@@ -352,9 +382,9 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
 
   /* add tunnel to fwd entry table XXX check return value from DP insertion */
   pool_get (lcm->fwd_entry_pool, fe);
-  fe->dst_loc = a->dlocator;
-  fe->src_loc = a->slocator;
-  gid_address_copy (&fe->deid, &a->deid);
+  fe->dst_loc = a->rmt_loc;
+  fe->src_loc = a->lcl_loc;
+  gid_address_copy (&fe->deid, &a->rmt_eid);
   hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
             fe - lcm->fwd_entry_pool);
 }
@@ -465,8 +495,9 @@ int
 vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
                                  u32 * map_index_result)
 {
-  uword * table_id;
+  uword * dp_table = 0;
   u32 vni;
+  u8 type;
 
   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
 
@@ -477,11 +508,16 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
     }
 
   vni = gid_address_vni(&a->eid);
-  table_id = hash_get(lcm->table_id_by_vni, vni);
+  type = gid_address_type(&a->eid);
+  if (GID_ADDR_IP_PREFIX == type)
+    dp_table = hash_get(lcm->table_id_by_vni, vni);
+  else if (GID_ADDR_MAC == type)
+    dp_table = hash_get(lcm->bd_id_by_vni, vni);
 
-  if (!table_id)
+  if (!dp_table)
     {
-      clib_warning ("vni %d not associated to a vrf!", vni);
+      clib_warning("vni %d not associated to a %s!", vni,
+                   GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
       return VNET_API_ERROR_INVALID_VALUE;
     }
 
@@ -497,8 +533,6 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
   unformat_input_t _line_input, * line_input = &_line_input;
   u8 is_add = 1;
   gid_address_t eid;
-  ip_prefix_t * prefp = &gid_address_ippref(&eid);
-  u8 * mac = gid_address_mac(&eid);
   gid_address_t * eids = 0;
   clib_error_t * error = 0;
   u8 * locator_set_name = 0;
@@ -509,6 +543,8 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
   u32 vni = 0;
 
   memset (&eid, 0, sizeof (eid));
+  memset (a, 0, sizeof (*a));
+
   /* Get a line of input. */
   if (! unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -519,18 +555,10 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
         is_add = 1;
       else if (unformat (line_input, "del"))
         is_add = 0;
+      else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
+        ;
       else if (unformat (line_input, "vni %d", &vni))
         gid_address_vni (&eid) = vni;
-      else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp))
-        {
-          gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
-          vec_add1(eids, eid);
-        }
-      else if (unformat (line_input, "eid %U", unformat_mac_address, mac))
-        {
-          gid_address_type (&eid) = GID_ADDR_MAC;
-          vec_add1(eids, eid);
-        }
       else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
         {
           p = hash_get_mem(lcm->locator_set_index_by_name, locator_set_name);
@@ -550,7 +578,13 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
     }
   /* XXX treat batch configuration */
 
-  a->eid = eid;
+  if (GID_ADDR_SRC_DST == gid_address_type(&eid))
+    {
+      error = clib_error_return(0, "src/dst is not supported for local EIDs!");
+      goto done;
+    }
+
+  gid_address_copy(&a->eid, &eid);
   a->is_add = is_add;
   a->locator_set_index = locator_set_index;
   a->local = 1;
@@ -577,10 +611,10 @@ VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
 };
 
 int
-vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
+vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
 {
   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
-  uword * table_id, * vnip;
+  uword * dp_idp, * vnip, ** dp_table_by_vni, ** vni_by_dp_table;
 
   if (vnet_lisp_enable_disable_status () == 0)
     {
@@ -588,44 +622,48 @@ vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
       return -1;
     }
 
-  if (vni == 0 || vrf == 0)
+  dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
+  vni_by_dp_table = is_l2 ? &lcm->vni_by_bd_id : &lcm->vni_by_table_id;
+
+  if (!is_l2 && (vni == 0 || dp_id == 0))
     {
       clib_warning ("can't add/del default vni-vrf mapping!");
       return -1;
     }
 
-  table_id = hash_get (lcm->table_id_by_vni, vni);
-  vnip = hash_get (lcm->vni_by_table_id, vrf);
+  dp_idp = hash_get (dp_table_by_vni[0], vni);
+  vnip = hash_get (vni_by_dp_table[0], dp_id);
 
   if (is_add)
     {
-      if (table_id || vnip)
+      if (dp_idp || vnip)
         {
-          clib_warning ("vni %d or vrf %d already used in any vrf/vni "
-                        "mapping!", vni, vrf);
+          clib_warning ("vni %d or vrf %d already used in vrf/vni "
+                        "mapping!", vni, dp_id);
           return -1;
         }
-      hash_set (lcm->table_id_by_vni, vni, vrf);
-      hash_set (lcm->vni_by_table_id, vrf, vni);
+      hash_set (dp_table_by_vni[0], vni, dp_id);
+      hash_set (vni_by_dp_table[0], dp_id, vni);
 
       /* create dp iface */
-      dp_add_del_iface (lcm, vni, 1);
+      dp_add_del_iface (lcm, vni, is_l2, 1);
     }
   else
     {
-      if (!table_id || !vnip)
+      if (!dp_idp || !vnip)
         {
           clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
-                        "mapping!", vni, vrf);
+                        "mapping!", vni, dp_id);
           return -1;
         }
-      hash_unset (lcm->table_id_by_vni, vni);
-      hash_unset (lcm->vni_by_table_id, vrf);
+      hash_unset (dp_table_by_vni[0], vni);
+      hash_unset (vni_by_dp_table[0], dp_id);
 
       /* remove dp iface */
-      dp_add_del_iface (lcm, vni, 0);
+      dp_add_del_iface (lcm, vni, is_l2, 0);
     }
   return 0;
+
 }
 
 static clib_error_t *
@@ -633,8 +671,8 @@ lisp_eid_table_map_command_fn (vlib_main_t * vm,
                                unformat_input_t * input,
                                vlib_cli_command_t * cmd)
 {
-  u8 is_add = 1;
-  u32 vni = 0, vrf = 0;
+  u8 is_add = 1, is_l2 = 0;
+  u32 vni = 0, dp_id = 0;
   unformat_input_t _line_input, * line_input = &_line_input;
 
   /* Get a line of input. */
@@ -647,20 +685,22 @@ lisp_eid_table_map_command_fn (vlib_main_t * vm,
         is_add = 0;
       else if (unformat (line_input, "vni %d", &vni))
         ;
-      else if (unformat (line_input, "vrf %d", &vrf))
+      else if (unformat (line_input, "vrf %d", &dp_id))
         ;
+      else if (unformat (line_input, "bd %d", &dp_id))
+        is_l2 = 1;
       else
         {
           return unformat_parse_error (line_input);
         }
     }
-  vnet_lisp_eid_table_map (vni, vrf, is_add);
+  vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
   return 0;
 }
 
 VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
     .path = "lisp eid-table map",
-    .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf>",
+    .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
     .function = lisp_eid_table_map_command_fn,
 };
 
@@ -795,7 +835,8 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
       vnet_lisp_add_del_locator_set (ls_args, 0);
 
       /* return old mapping index */
-      res_map_index[0] = mi;
+      if (res_map_index)
+        res_map_index[0] = mi;
     }
 
   /* success */
@@ -924,12 +965,8 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   unformat_input_t _line_input, * line_input = &_line_input;
   u8 is_add = 1, del_all = 0;
   locator_t rloc, * rlocs = 0, * curr_rloc = 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;
-  u8 * s = 0;
+  gid_address_t eid;
+  u8 eid_set = 0;
   u32 vni, action = ~0, p, w;
   int rv;
 
@@ -937,13 +974,9 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   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);
-
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (line_input, "del-all"))
@@ -952,34 +985,11 @@ 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))
-        {
-          gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
-          deid_set = 1;
-        }
-      else if (unformat (line_input, "deid %U",
-                         unformat_mac_address, dmac))
-        {
-          gid_address_type (&deid) = GID_ADDR_MAC;
-          deid_set = 1;
-        }
+      else if (unformat (line_input, "%U", unformat_gid_address, &eid))
+        eid_set = 1;
       else if (unformat (line_input, "vni %u", &vni))
         {
-          gid_address_vni (&seid) = vni;
-          gid_address_vni (&deid) = vni;
-        }
-      else if (unformat (line_input, "seid %U",
-                         unformat_ip_prefix, seid_ippref))
-        {
-          gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
-          seid_set = 1;
-        }
-      else if (unformat (line_input, "seid %U",
-                         unformat_mac_address, smac))
-        {
-          gid_address_type (&seid) = GID_ADDR_MAC;
-          seid_set = 1;
+          gid_address_vni (&eid) = vni;
         }
       else if (unformat (line_input, "p %d w %d", &p, &w))
         {
@@ -997,22 +1007,9 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
           vec_add1 (rlocs, rloc);
           curr_rloc = &rlocs[vec_len (rlocs) - 1];
         }
-      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 if (unformat (line_input, "action %U",
+                         unformat_negative_mapping_action, &action))
+        ;
       else
         {
           clib_warning ("parse error");
@@ -1020,31 +1017,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))
@@ -1065,31 +1046,32 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
   if (!is_add)
     {
       lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
-      rv = lisp_add_del_adjacency (lcm, 0, &deid, /* is_add */ 0);
-    }
-  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);
   return error;
 }
 
 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|"
-     "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
+    .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> p <prio> w <weight> "
+     "[rloc <dst-locator> ... ]",
     .function = lisp_add_del_remote_mapping_command_fn,
 };
 
@@ -1338,14 +1320,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;
@@ -1355,7 +1384,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
     {
@@ -1371,8 +1401,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
@@ -1393,6 +1423,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));
 
@@ -1404,12 +1435,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)
     {
@@ -1417,8 +1453,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
@@ -1430,8 +1471,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;
@@ -1518,8 +1566,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;
@@ -1774,7 +1822,7 @@ vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a,
 clib_error_t *
 vnet_lisp_enable_disable (u8 is_enable)
 {
-  u32 vni, table_id;
+  u32 vni, dp_table;
   clib_error_t * error = 0;
   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
   vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
@@ -1789,9 +1837,13 @@ vnet_lisp_enable_disable (u8 is_enable)
 
   if (is_enable)
     {
-      /* enable all ifaces */
-      hash_foreach(vni, table_id, lcm->table_id_by_vni, ({
-        dp_add_del_iface(lcm, vni, 1);
+      /* enable all l2 and l3 ifaces */
+      hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({
+        dp_add_del_iface(lcm, vni, 0, 1);
+      }));
+
+      hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({
+        dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1);
       }));
     }
   else
@@ -2055,7 +2107,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)
@@ -2131,7 +2190,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;
@@ -2148,13 +2207,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);
@@ -2383,6 +2449,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]);
       }));
 
@@ -2393,6 +2460,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]);
       }));
     }
@@ -2524,7 +2592,7 @@ send_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
 }
 
 static void
-get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst)
+get_src_and_dst_ip (void *hdr, ip_address_t * src, ip_address_t *dst)
 {
   ip4_header_t * ip4 = hdr;
   ip6_header_t * ip6;
@@ -2543,11 +2611,11 @@ get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst)
 }
 
 static u32
-lisp_get_vni_from_buffer (vlib_buffer_t * b, u8 version)
+lisp_get_vni_from_buffer_ip (lisp_cp_main_t * lcm, vlib_buffer_t * b,
+                             u8 version)
 {
   uword * vnip;
   u32 vni = ~0, table_id = ~0, fib_index;
-  lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
 
   if (version == IP4)
     {
@@ -2579,6 +2647,79 @@ lisp_get_vni_from_buffer (vlib_buffer_t * b, u8 version)
   return vni;
 }
 
+always_inline u32
+lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
+{
+  uword * vnip;
+  u32 vni = ~0;
+  u32 sw_if_index0;
+
+  l2input_main_t * l2im = &l2input_main;
+  l2_input_config_t * config;
+  l2_bridge_domain_t * bd_config;
+
+  sw_if_index0 = vnet_buffer(b)->sw_if_index[VLIB_RX];
+  config = vec_elt_at_index(l2im->configs, sw_if_index0);
+  bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
+
+  vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id);
+  if (vnip)
+    vni = vnip[0];
+  else
+    clib_warning("bridge domain %d is not mapped to any vni!",
+                 config->bd_index);
+
+  return vni;
+}
+
+always_inline void
+get_src_and_dst_eids_from_buffer (lisp_cp_main_t *lcm, vlib_buffer_t * b,
+                                  gid_address_t * src, gid_address_t * dst)
+{
+  u32 vni = 0;
+  u16 type;
+
+  type = vnet_buffer(b)->lisp.overlay_afi;
+
+  if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
+    {
+      ip4_header_t * ip;
+      u8 version, preflen;
+
+      gid_address_type(src) = GID_ADDR_IP_PREFIX;
+      gid_address_type(dst) = GID_ADDR_IP_PREFIX;
+
+      ip = vlib_buffer_get_current (b);
+      get_src_and_dst_ip (ip, &gid_address_ip(src), &gid_address_ip(dst));
+
+      version = gid_address_ip_version(src);
+      preflen = ip_address_max_len (version);
+      gid_address_ippref_len(src) = preflen;
+      gid_address_ippref_len(dst) = preflen;
+
+      vni = lisp_get_vni_from_buffer_ip (lcm, b, version);
+      gid_address_vni (dst) = vni;
+      gid_address_vni (src) = vni;
+    }
+  else if (LISP_AFI_MAC == type)
+    {
+      ethernet_header_t * eh;
+
+      eh = vlib_buffer_get_current (b);
+
+      gid_address_type(src) = GID_ADDR_MAC;
+      gid_address_type(dst) = GID_ADDR_MAC;
+      mac_copy(&gid_address_mac(src), eh->src_address);
+      mac_copy(&gid_address_mac(dst), eh->dst_address);
+
+      /* get vni */
+      vni = lisp_get_vni_from_buffer_eth (lcm, b);
+
+      gid_address_vni (dst) = vni;
+      gid_address_vni (src) = vni;
+    }
+}
+
 static uword
 lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
               vlib_frame_t * from_frame)
@@ -2598,16 +2739,9 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
 
       while (n_left_from > 0 && n_left_to_next_drop > 0)
         {
-          u32 pi0, vni;
-          vlib_buffer_t * p0;
-          ip4_header_t * ip0;
+          u32 pi0;
+          vlib_buffer_t * b0;
           gid_address_t src, dst;
-          ip_prefix_t * spref, * dpref;
-
-          gid_address_type (&src) = GID_ADDR_IP_PREFIX;
-          spref = &gid_address_ippref(&src);
-          gid_address_type (&dst) = GID_ADDR_IP_PREFIX;
-          dpref = &gid_address_ippref(&dst);
 
           pi0 = from[0];
           from += 1;
@@ -2616,18 +2750,11 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
           to_next_drop += 1;
           n_left_to_next_drop -= 1;
 
-          p0 = vlib_get_buffer (vm, pi0);
-          p0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
+          b0 = vlib_get_buffer (vm, pi0);
+          b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
 
           /* src/dst eid pair */
-          ip0 = vlib_buffer_get_current (p0);
-          get_src_and_dst (ip0, &ip_prefix_addr(spref), &ip_prefix_addr(dpref));
-          ip_prefix_len(spref) = ip_address_max_len (ip_prefix_version(spref));
-          ip_prefix_len(dpref) = ip_address_max_len (ip_prefix_version(dpref));
-
-          vni = lisp_get_vni_from_buffer (p0, ip_prefix_version (spref));
-          gid_address_vni (&dst) = vni;
-          gid_address_vni (&src) = vni;
+          get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
 
           /* if we have remote mapping for destination already in map-chache
              add forwarding tunnel directly. If not send a map-request */
@@ -2637,7 +2764,7 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
               mapping_t * m =  vec_elt_at_index (lcm->mapping_pool, di);
               /* send a map-request also in case of negative mapping entry
                 with corresponding action */
-              if (m->action == ACTION_SEND_MAP_REQUEST)
+              if (m->action == LISP_SEND_MAP_REQUEST)
                 {
                   /* send map-request */
                   send_encapsulated_map_request (vm, lcm, &src, &dst, 0);
@@ -2660,9 +2787,9 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
               pkts_mapped++;
             }
 
-          if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
+          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
             {
-              lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, p0,
+              lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
                                                           sizeof(*tr));
 
               memset(tr, 0, sizeof(*tr));