+ /* remove mapping from dictionary */
+ gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
+ gid_address_free (&m->eid);
+ pool_put_index (lcm->mapping_pool, mi);
+ }
+
+ return 0;
+}
+
+/**
+ * Add/update/delete mapping to/in/from map-cache.
+ */
+int
+vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
+ u32 * map_index_result)
+{
+ uword * dp_table = 0;
+ u32 vni;
+ u8 type;
+
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ vni = gid_address_vni(&a->eid);
+ 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 (!dp_table)
+ {
+ clib_warning("vni %d not associated to a %s!", vni,
+ GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ /* store/remove mapping from map-cache */
+ return vnet_lisp_map_cache_add_del (a, map_index_result);
+}
+
+static clib_error_t *
+lisp_add_del_local_eid_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();
+ unformat_input_t _line_input, * line_input = &_line_input;
+ u8 is_add = 1;
+ gid_address_t eid;
+ gid_address_t * eids = 0;
+ clib_error_t * error = 0;
+ u8 * locator_set_name = 0;
+ u32 locator_set_index = 0, map_index = 0;
+ uword * p;
+ vnet_lisp_add_del_mapping_args_t _a, * a = &_a;
+ int rv = 0;
+ 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;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "add"))
+ 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, "locator-set %_%v%_", &locator_set_name))
+ {
+ p = hash_get_mem(lcm->locator_set_index_by_name, locator_set_name);
+ if (!p)
+ {
+ error = clib_error_return(0, "locator-set %s doesn't exist",
+ locator_set_name);
+ goto done;
+ }
+ locator_set_index = p[0];
+ }
+ else
+ {
+ error = unformat_parse_error(line_input);
+ goto done;
+ }
+ }
+ /* XXX treat batch configuration */
+
+ 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;
+
+ rv = vnet_lisp_add_del_local_mapping (a, &map_index);
+ if (0 != rv)
+ {
+ error = clib_error_return(0, "failed to %s local mapping!",
+ is_add ? "add" : "delete");
+ }
+ done:
+ vec_free(eids);
+ if (locator_set_name)
+ vec_free (locator_set_name);
+ gid_address_free (&a->eid);
+ return error;
+}
+
+VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
+ .path = "lisp eid-table",
+ .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
+ "locator-set <locator-set>",
+ .function = lisp_add_del_local_eid_command_fn,
+};
+
+int
+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 * dp_idp, * vnip, ** dp_table_by_vni, ** vni_by_dp_table;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return -1;
+ }
+
+ 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;
+ }
+
+ dp_idp = hash_get (dp_table_by_vni[0], vni);
+ vnip = hash_get (vni_by_dp_table[0], dp_id);
+
+ if (is_add)
+ {
+ if (dp_idp || vnip)
+ {
+ clib_warning ("vni %d or vrf %d already used in vrf/vni "
+ "mapping!", vni, dp_id);
+ return -1;
+ }
+ 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, is_l2, 1);
+ }
+ else
+ {
+ if (!dp_idp || !vnip)
+ {
+ clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
+ "mapping!", vni, dp_id);
+ return -1;
+ }
+ 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, is_l2, 0);
+ }
+ return 0;
+
+}
+
+static clib_error_t *
+lisp_eid_table_map_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ 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. */
+ if (! unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "vni %d", &vni))
+ ;
+ 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, 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> | bd <bdi>",
+ .function = lisp_eid_table_map_command_fn,
+};
+
+
+/* return 0 if the two locator sets are identical 1 otherwise */
+static u8
+compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
+ locator_t * new_locators)
+{
+ u32 i, old_li;
+ locator_t * old_loc, * new_loc;
+
+ if (vec_len (old_ls_indexes) != vec_len(new_locators))
+ return 1;
+
+ for (i = 0; i < vec_len(new_locators); i++)
+ {
+ old_li = vec_elt(old_ls_indexes, i);
+ old_loc = pool_elt_at_index(lcm->locator_pool, old_li);
+
+ new_loc = vec_elt_at_index(new_locators, i);
+
+ if (locator_cmp (old_loc, new_loc))
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Adds/removes/updates mapping. Does not program forwarding.
+ *
+ * @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 * eid, locator_t * rlocs, u8 action,
+ u8 authoritative, u32 ttl, u8 is_add,
+ u32 * res_map_index)
+{
+ vnet_lisp_add_del_mapping_args_t _m_args, * m_args = &_m_args;
+ vnet_lisp_add_del_locator_set_args_t _ls_args, * ls_args = &_ls_args;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ u32 mi, ls_index = 0, dst_map_index;
+ mapping_t * old_map;
+
+ if (vnet_lisp_enable_disable_status() == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ if (res_map_index)
+ res_map_index[0] = ~0;
+
+ memset (m_args, 0, sizeof (m_args[0]));
+ memset (ls_args, 0, sizeof (ls_args[0]));
+
+ ls_args->locators = rlocs;
+
+ 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, eid) == 0)
+ {
+ locator_set_t * old_ls;
+
+ /* update mapping attributes */
+ old_map->action = action;
+ old_map->authoritative = authoritative;
+ old_map->ttl = ttl;
+
+ old_ls = pool_elt_at_index(lcm->locator_set_pool,
+ old_map->locator_set_index);
+ if (compare_locators (lcm, old_ls->locator_indices,
+ ls_args->locators))
+ {
+ /* set locator-set index to overwrite */
+ ls_args->is_add = 1;
+ ls_args->index = old_map->locator_set_index;
+ vnet_lisp_add_del_locator_set (ls_args, 0);
+ if (res_map_index)
+ res_map_index[0] = mi;
+ }
+ }
+ /* new mapping */
+ else
+ {
+ ls_args->is_add = 1;
+ ls_args->index = ~0;
+
+ vnet_lisp_add_del_locator_set (ls_args, &ls_index);
+
+ /* add mapping */
+ gid_address_copy (&m_args->eid, eid);
+ m_args->is_add = 1;
+ m_args->action = action;
+ m_args->locator_set_index = ls_index;
+ vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
+
+ if (res_map_index)
+ res_map_index[0] = dst_map_index;
+ }
+ }
+ else
+ {
+ if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
+ {
+ clib_warning("cannot delete mapping for eid %U", format_gid_address,
+ eid);
+ return -1;
+ }
+
+ m_args->is_add = 0;
+ gid_address_copy (&m_args->eid, eid);
+ m_args->locator_set_index = old_map->locator_set_index;
+
+ /* delete mapping associated from map-cache */
+ vnet_lisp_map_cache_add_del (m_args, 0);
+
+ ls_args->is_add = 0;
+ 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 */
+ return 0;
+}
+
+int
+vnet_lisp_clear_all_remote_adjacencies (void)
+{
+ int rv = 0;
+ u32 mi, * map_indices = 0, * map_indexp;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ vnet_lisp_add_del_mapping_args_t _dm_args, * dm_args = &_dm_args;
+ vnet_lisp_add_del_locator_set_args_t _ls, * ls = &_ls;
+
+ pool_foreach_index (mi, lcm->mapping_pool,
+ ({
+ vec_add1 (map_indices, mi);
+ }));
+
+ vec_foreach (map_indexp, map_indices)
+ {
+ mapping_t * map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
+ if (!map->local)
+ {
+ dp_del_fwd_entry (lcm, 0, map_indexp[0]);
+
+ dm_args->is_add = 0;
+ gid_address_copy (&dm_args->eid, &map->eid);
+ dm_args->locator_set_index = map->locator_set_index;
+
+ /* delete mapping associated to fwd entry */
+ vnet_lisp_map_cache_add_del (dm_args, 0);
+
+ ls->is_add = 0;
+ ls->local = 0;
+ ls->index = map->locator_set_index;
+ /* delete locator set */
+ rv = vnet_lisp_add_del_locator_set (ls, 0);
+ if (rv != 0)
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (map_indices)
+ vec_free (map_indices);
+ return rv;
+}
+
+/**
+ * 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, gid_address_t * local_eid,
+ gid_address_t * remote_eid, u8 is_add)
+{
+ u32 local_mi, remote_mi = ~0;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ 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);
+
+ 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 */
+ local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
+ gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
+
+
+ if (GID_LOOKUP_MISS == local_mi)
+ {
+ clib_warning("Local eid %U not found. Cannot add adjacency!",
+ format_gid_address, local_eid);
+
+ return -1;
+ }
+
+ /* update forwarding */
+ dp_add_fwd_entry (lcm, local_mi, remote_mi);
+ }
+ else
+ dp_del_fwd_entry (lcm, 0, remote_mi);
+
+ return 0;
+}
+
+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->seid, &a->deid, a->is_add);
+}
+
+/**
+ * Handler for add/del remote mapping CLI.
+ *
+ * @param vm vlib context
+ * @param input input from user
+ * @param cmd cmd
+ * @return pointer to clib error structure
+ */
+static clib_error_t *
+lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ 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, * curr_rloc = 0;
+ gid_address_t eid;
+ u8 eid_set = 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(&eid, 0, sizeof(eid));
+ memset(&rloc, 0, sizeof(rloc));
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del-all"))
+ del_all = 1;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "add"))
+ ;
+ else if (unformat (line_input, "%U", unformat_gid_address, &eid))
+ eid_set = 1;
+ else if (unformat (line_input, "vni %u", &vni))
+ {
+ gid_address_vni (&eid) = vni;
+ }
+ else if (unformat (line_input, "p %d w %d", &p, &w))
+ {
+ 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, "rloc %U", unformat_ip_address,
+ &rloc.address))
+ {
+ vec_add1 (rlocs, rloc);
+ curr_rloc = &rlocs[vec_len (rlocs) - 1];
+ }
+ else if (unformat (line_input, "action %U",
+ unformat_negative_mapping_action, &action))
+ ;
+ else
+ {
+ clib_warning ("parse error");
+ goto done;
+ }
+ }
+
+ if (!eid_set)
+ {
+ clib_warning ("missing eid!");
+ goto done;
+ }
+
+ if (!del_all)
+ {
+
+
+ if (is_add && (~0 == action)
+ && 0 == vec_len (rlocs))
+ {
+ clib_warning ("no action set for negative map-reply!");
+ goto done;
+ }
+ }
+ else
+ {
+ vnet_lisp_clear_all_remote_adjacencies ();
+ goto done;
+ }
+
+ /* TODO build src/dst with seid*/
+
+ /* if it's a delete, clean forwarding */
+ if (!is_add)
+ {
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ 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);
+ 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> "
+ "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,
+};
+
+/**
+ * Handler for add/del adjacency CLI.
+ */
+static clib_error_t *
+lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ clib_error_t * error = 0;
+ unformat_input_t _line_input, * line_input = &_line_input;
+ vnet_lisp_add_del_adjacency_args_t _a, * a = &_a;
+ u8 is_add = 1;
+ 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;
+ u8 * s = 0;
+ u32 vni, action = ~0;
+ 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(&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"))
+ 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, "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;
+ }
+ else
+ {
+ clib_warning ("parse error");
+ goto done;
+ }
+ }
+
+ if (!deid_set)
+ {
+ clib_warning ("missing deid!");
+ 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 (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))
+ {
+ clib_warning ("no action set for negative map-reply!");
+ goto done;
+ }
+
+ memset(a, 0, sizeof(a[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)
+ clib_warning("failed to %s adjacency!", is_add ? "add" : "delete");
+
+done:
+ unformat_free (line_input);
+ if (s)
+ vec_free (s);
+ return error;
+}
+
+VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
+ .path = "lisp adjacency",
+ .short_help = "lisp adjacency add|del vni <vni>"
+ "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
+ "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
+ .function = lisp_add_del_adjacency_command_fn,
+};
+
+
+static clib_error_t *
+lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ ip_address_t * addr;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+
+ vec_foreach (addr, lcm->map_resolvers)
+ {
+ vlib_cli_output (vm, "%U", format_ip_address, addr);
+ }
+ return 0;
+}
+
+VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
+ .path = "show lisp map-resolvers",
+ .short_help = "show lisp map-resolvers",
+ .function = lisp_show_map_resolvers_command_fn,
+};
+
+int
+vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
+{
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ u32 locator_set_index = ~0;
+ mapping_t * m;
+ uword * p;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
+ if (!p)
+ {
+ clib_warning ("locator-set %v doesn't exist", locator_set_name);
+ return -1;
+ }
+ locator_set_index = p[0];
+
+ if (is_add)
+ {
+ pool_get (lcm->mapping_pool, m);
+ m->locator_set_index = locator_set_index;
+ m->local = 1;
+ lcm->pitr_map_index = m - lcm->mapping_pool;
+
+ /* enable pitr mode */
+ lcm->lisp_pitr = 1;
+ }
+ else
+ {
+ /* remove pitr mapping */
+ pool_put_index (lcm->mapping_pool, lcm->pitr_map_index);
+
+ /* disable pitr mode */
+ lcm->lisp_pitr = 0;
+ }
+ return 0;
+}
+
+static clib_error_t *
+lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ u8 locator_name_set = 0;
+ u8 * locator_set_name = 0;
+ u8 is_add = 1;
+ unformat_input_t _line_input, * line_input = &_line_input;
+ clib_error_t * error = 0;
+ int rv = 0;
+
+ /* Get a line of input. */
+ if (! unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "ls %_%v%_", &locator_set_name))
+ locator_name_set = 1;
+ else if (unformat (line_input, "disable"))
+ is_add = 0;
+ else
+ return clib_error_return (0, "parse error");
+ }
+
+ if (!locator_name_set)
+ {
+ clib_warning ("No locator set specified!");
+ goto done;
+ }
+ rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
+ if (0 != rv)
+ {
+ error = clib_error_return(0, "failed to %s pitr!",
+ is_add ? "add" : "delete");
+ }
+
+done:
+ if (locator_set_name)
+ vec_free (locator_set_name);
+ return error;
+}
+
+VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
+ .path = "lisp pitr",
+ .short_help = "lisp pitr [disable] ls <locator-set-name>",
+ .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 *);
+ 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;
+
+ u8 * type = ls->local ? format(0, "local(%s)", ls->name)
+ : format(0, "remote");
+
+ if (vec_len (ls->locator_indices) == 0)
+ {
+ s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
+ type, ttl, aut);
+ }
+ else
+ {
+ vec_foreach (loc_index, ls->locator_indices)
+ {
+ locator_t * l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
+ if (l->local)
+ loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
+ l->sw_if_index);
+ else
+ loc = format (0, "%U", format_ip_address,
+ &gid_address_ip (&l->address));
+
+ if (first_line)
+ {
+ s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
+ gid, type, loc, ttl, aut);
+ first_line = 0;
+ }
+ else
+ s = format (s, "%55s%v\n", "", loc);
+ }