2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/lisp-cp/control.h>
17 #include <vnet/lisp-cp/packets.h>
18 #include <vnet/lisp-cp/lisp_msg_serdes.h>
19 #include <vnet/lisp-gpe/lisp_gpe.h>
22 add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index);
25 del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index);
28 compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
29 locator_t * new_locators);
31 /* Stores mapping in map-cache. It does NOT program data plane forwarding for
32 * remote/learned mappings. */
34 vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
35 u32 * map_index_result)
37 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
38 u32 mi, * map_indexp, map_index, i;
42 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->deid);
45 /* TODO check if overwriting and take appropriate actions */
46 if (mi != GID_LOOKUP_MISS)
48 clib_warning("eid %U found in the eid-table", format_ip_address,
50 return VNET_API_ERROR_VALUE_EXIST;
53 pool_get(lcm->mapping_pool, m);
55 m->locator_set_index = a->locator_set_index;
59 map_index = m - lcm->mapping_pool;
60 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, map_index,
63 if (pool_is_free_index(lcm->locator_set_pool, a->locator_set_index))
65 clib_warning("Locator set with index %d doesn't exist",
66 a->locator_set_index);
67 return VNET_API_ERROR_INVALID_VALUE;
70 /* add eid to list of eids supported by locator-set */
71 vec_validate (lcm->locator_set_to_eids, a->locator_set_index);
72 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids,
73 a->locator_set_index);
74 vec_add1(eid_indexes[0], map_index);
79 vec_add1(lcm->local_mappings_indexes, map_index);
81 map_index_result[0] = map_index;
85 if (mi == GID_LOOKUP_MISS)
87 clib_warning("eid %U not found in the eid-table", format_ip_address,
89 return VNET_API_ERROR_INVALID_VALUE;
92 /* clear locator-set to eids binding */
93 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids,
94 a->locator_set_index);
95 for (i = 0; i < vec_len(eid_indexes[0]); i++)
97 map_indexp = vec_elt_at_index(eid_indexes[0], i);
98 if (map_indexp[0] == mi)
101 vec_del1(eid_indexes[0], i);
103 /* remove local mark if needed */
104 m = pool_elt_at_index(lcm->mapping_pool, mi);
108 for (k = 0; k < vec_len(lcm->local_mappings_indexes); k++)
110 lm_indexp = vec_elt_at_index(lcm->local_mappings_indexes, k);
111 if (lm_indexp[0] == mi)
114 vec_del1(lcm->local_mappings_indexes, k);
118 /* remove tunnel ??? */
121 /* remove mapping from dictionary */
122 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, 0, 0);
123 pool_put_index (lcm->mapping_pool, mi);
129 /* Stores mapping in map-cache and programs data plane for local mappings. */
131 vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
132 u32 * map_index_result)
134 uword * table_id, * refc;
136 vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
137 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
139 vni = gid_address_vni(&a->deid);
141 /* store/remove mapping from map-cache */
142 rv = vnet_lisp_add_del_mapping (a, map_index_result);
146 table_id = hash_get(lcm->table_id_by_vni, vni);
150 clib_warning ("vni %d not associated to a vrf!", vni);
151 return VNET_API_ERROR_INVALID_VALUE;
154 refc = hash_get(lcm->dp_if_refcount_by_vni, vni);
156 /* enable/disable data-plane interface */
159 /* create interface or update refcount */
164 ai->table_id = table_id[0];
165 vnet_lisp_gpe_add_del_iface (ai, 0);
167 /* counts the number of eids in a vni that use the interface */
168 hash_set(lcm->dp_if_refcount_by_vni, vni, 1);
177 /* since this is a remove for an existing eid, the iface should exist */
181 /* remove iface if needed */
186 ai->table_id = table_id[0];
187 vnet_lisp_gpe_add_del_iface (ai, 0);
194 static clib_error_t *
195 lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
196 vlib_cli_command_t * cmd)
198 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
199 unformat_input_t _line_input, * line_input = &_line_input;
202 ip_prefix_t * prefp = &gid_address_ippref(&eid);
203 gid_address_t * eids = 0;
204 clib_error_t * error = 0;
205 u8 * locator_set_name;
206 u32 locator_set_index = 0, map_index = 0;
208 vnet_lisp_add_del_mapping_args_t _a, * a = &_a;
210 gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
212 /* Get a line of input. */
213 if (! unformat_user (input, unformat_line_input, line_input))
216 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
218 if (unformat (line_input, "add"))
220 else if (unformat (line_input, "del"))
222 else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp))
226 else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
228 p = hash_get_mem(lcm->locator_set_index_by_name, locator_set_name);
231 error = clib_error_return(0, "locator-set %s doesn't exist",
235 locator_set_index = p[0];
239 error = unformat_parse_error(line_input);
244 /* XXX treat batch configuration */
247 a->locator_set_index = locator_set_index;
250 vnet_lisp_add_del_local_mapping (a, &map_index);
256 VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
257 .path = "lisp eid-table",
258 .short_help = "lisp eid-table add/del eid <eid> locator-set <locator-set>",
259 .function = lisp_add_del_local_eid_command_fn,
263 * Adds/removes/updates static remote mapping.
265 * This function also modifies forwarding entries if needed.
267 * @param deid destination EID
268 * @param seid source EID
269 * @param rlocs vector of remote locators
270 * @param action action for negative map-reply
271 * @param is_add add mapping if non-zero, delete otherwise
272 * @return return code
275 vnet_lisp_add_del_remote_mapping (gid_address_t * deid, gid_address_t * seid,
276 ip_address_t * rlocs, u8 action, u8 is_add)
278 vnet_lisp_add_del_mapping_args_t _dm_args, * dm_args = &_dm_args;
279 vnet_lisp_add_del_mapping_args_t _sm_args, * sm_args = &_sm_args;
280 vnet_lisp_add_del_locator_set_args_t _ls, * ls = &_ls;
281 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
282 u32 mi, ls_index = 0, dst_map_index, src_map_index;
287 memset (sm_args, 0, sizeof (sm_args[0]));
288 memset (dm_args, 0, sizeof (dm_args[0]));
289 memset (ls, 0, sizeof (ls[0]));
291 /* prepare remote locator set */
292 vec_foreach (dl, rlocs)
294 memset (&loc, 0, sizeof (loc));
295 gid_address_ip (&loc.address) = dl[0];
296 vec_add1 (ls->locators, loc);
298 src_map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
300 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, deid);
304 if ((u32)~0 == src_map_index)
306 clib_warning ("seid %U not found!", format_gid_address, seid);
312 clib_warning ("deid %U marked for removal but not "
313 "found!", format_gid_address, deid);
319 vnet_lisp_add_del_locator_set (ls, &ls_index);
322 gid_address_copy (&dm_args->deid, deid);
324 dm_args->action = action;
325 dm_args->locator_set_index = ls_index;
326 vnet_lisp_add_del_mapping (dm_args, &dst_map_index);
329 add_fwd_entry (lcm, src_map_index, dst_map_index);
336 /* delete forwarding entry */
337 del_fwd_entry (lcm, 0, mi);
339 gid_address_copy (&dm_args->deid, deid);
340 mapping_t * map = pool_elt_at_index (lcm->mapping_pool, mi);
341 dm_args->locator_set_index = map->locator_set_index;
343 /* delete mapping associated to fwd entry */
344 vnet_lisp_add_del_mapping (dm_args, 0);
347 ls->index = map->locator_set_index;
348 /* delete locator set */
349 vnet_lisp_add_del_locator_set (ls, 0);
351 /* update existing locator set */
354 if ((u32)~0 == src_map_index)
356 clib_warning ("seid %U not found!", format_gid_address, seid);
361 locator_set_t * old_ls;
362 old_map = pool_elt_at_index (lcm->mapping_pool, mi);
364 /* update mapping attributes */
365 old_map->action = action;
367 old_ls = pool_elt_at_index(lcm->locator_set_pool,
368 old_map->locator_set_index);
369 if (compare_locators (lcm, old_ls->locator_indices,
372 /* set locator-set index to overwrite */
374 ls->index = old_map->locator_set_index;
375 vnet_lisp_add_del_locator_set (ls, 0);
376 add_fwd_entry (lcm, src_map_index, mi);
383 vec_free (ls->locators);
388 * Handler for add/del remote mapping CLI.
390 * @param vm vlib context
391 * @param input input from user
393 * @return pointer to clib error structure
395 static clib_error_t *
396 lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
397 unformat_input_t * input,
398 vlib_cli_command_t * cmd)
400 clib_error_t * error = 0;
401 unformat_input_t _line_input, * line_input = &_line_input;
403 ip_address_t rloc, * rlocs = 0;
404 ip_prefix_t * deid_ippref, * seid_ippref;
405 gid_address_t seid, deid;
406 u8 deid_set = 0, seid_set = 0;
407 u32 vni, action = ~0;
409 /* Get a line of input. */
410 if (! unformat_user (input, unformat_line_input, line_input))
413 memset (&deid, 0, sizeof (deid));
414 memset (&seid, 0, sizeof (seid));
416 seid_ippref = &gid_address_ippref(&seid);
417 deid_ippref = &gid_address_ippref(&deid);
419 gid_address_type (&deid) = GID_ADDR_IP_PREFIX;
420 gid_address_type (&seid) = GID_ADDR_IP_PREFIX;
422 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
424 if (unformat (line_input, "del"))
426 if (unformat (line_input, "add"))
428 else if (unformat (line_input, "deid %U",
429 unformat_ip_prefix, deid_ippref))
433 else if (unformat (line_input, "vni %u", &vni))
435 gid_address_set_vni (&seid, vni);
436 gid_address_set_vni (&deid, vni);
438 else if (unformat (line_input, "seid %U",
439 unformat_ip_prefix, seid_ippref))
441 else if (unformat (line_input, "rloc %U", unformat_ip_address, &rloc))
442 vec_add1 (rlocs, rloc);
443 else if (unformat (line_input, "action %d", &action))
447 clib_warning ("parse error");
452 if (is_add && (!deid_set || !seid_set))
454 clib_warning ("missing paramete(s)!");
458 if (!is_add && !deid_set)
460 clib_warning ("missing deid!");
465 && (ip_prefix_version (deid_ippref)
466 != ip_prefix_version (seid_ippref)))
468 clib_warning ("source and destination EIDs are not"
469 " in the same IP family!");
473 if (is_add && (~0 == action)
474 && 0 == vec_len (rlocs))
476 clib_warning ("no action set for negative map-reply!");
480 int rv = vnet_lisp_add_del_remote_mapping (&deid, &seid, rlocs,
483 clib_warning ("failed to %s remote mapping!",
484 is_add ? "add" : "delete");
487 unformat_free (line_input);
491 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = {
492 .path = "lisp remote-mapping",
493 .short_help = "lisp remote-mapping add|del vni <vni> deid <dest-eid> "
494 "seid <src-eid> rloc <dst-locator> [rloc <dst-locator> ... ]",
495 .function = lisp_add_del_remote_mapping_command_fn,
498 static clib_error_t *
499 lisp_show_local_eid_table_command_fn (vlib_main_t * vm,
500 unformat_input_t * input,
501 vlib_cli_command_t * cmd)
503 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
506 vlib_cli_output (vm, "%=20s%=16s", "EID", "Locator");
507 pool_foreach (mapit, lcm->mapping_pool,
510 locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
511 mapit->locator_set_index);
512 vlib_cli_output (vm, "%-16U%16v", format_gid_address, &mapit->eid,
520 VLIB_CLI_COMMAND (lisp_cp_show_local_eid_table_command) = {
521 .path = "show lisp eid-table",
522 .short_help = "Shows local EID table",
523 .function = lisp_show_local_eid_table_command_fn,
526 /* cleans locator to locator-set data and removes locators not part of
529 clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi)
531 u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes;
532 locator_set_t * ls = pool_elt_at_index(lcm->locator_set_pool, lsi);
533 for (i = 0; i < vec_len(ls->locator_indices); i++)
535 loc_indexp = vec_elt_at_index(ls->locator_indices, i);
536 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
538 for (j = 0; j < vec_len(ls_indexes[0]); j++)
540 ls_indexp = vec_elt_at_index(ls_indexes[0], j);
541 if (ls_indexp[0] == lsi)
545 /* delete index for removed locator-set*/
546 vec_del1(ls_indexes[0], j);
548 /* delete locator if it's part of no locator-set */
549 if (vec_len (ls_indexes[0]) == 0)
550 pool_put_index(lcm->locator_pool, loc_indexp[0]);
554 vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a,
557 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
559 locator_t * loc, * itloc;
560 uword _p = (u32)~0, * p = &_p;
561 u32 loc_index, ls_index, ** ls_indexes;
566 /* check if overwrite */
568 p = hash_get_mem(lcm->locator_set_index_by_name, a->name);
573 if (p && p[0] != (u32)~0)
575 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
578 clib_warning("locator-set %d to be overwritten doesn't exist!",
583 /* clean locator to locator-set vectors and remove locators if
584 * they're not part of another locator-set */
585 clean_locator_to_locator_set (lcm, p[0]);
587 /* remove locator indices from locator set */
588 vec_free(ls->locator_indices);
595 /* new locator-set */
598 pool_get(lcm->locator_set_pool, ls);
599 ls_index = ls - lcm->locator_set_pool;
603 ls->name = vec_dup(a->name);
605 if (!lcm->locator_set_index_by_name)
606 lcm->locator_set_index_by_name = hash_create_vec(
607 /* size */0, sizeof(ls->name[0]), sizeof(uword));
608 hash_set_mem(lcm->locator_set_index_by_name, ls->name, ls_index);
610 /* mark as local locator-set */
611 vec_add1(lcm->local_locator_set_indexes, ls_index);
613 ls->local = a->local;
615 ls_result[0] = ls_index;
618 /* allocate locators */
619 vec_foreach (itloc, a->locators)
621 pool_get(lcm->locator_pool, loc);
623 loc_index = loc - lcm->locator_pool;
625 vec_add1(ls->locator_indices, loc_index);
627 vec_validate (lcm->locator_to_locator_sets, loc_index);
628 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
630 vec_add1(ls_indexes[0], ls_index);
635 /* find locator-set */
638 p = hash_get_mem(lcm->locator_set_index_by_name, a->name);
641 clib_warning("locator-set %v doesn't exists", a->name);
648 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
651 clib_warning("locator-set with index %d doesn't exists", p[0]);
654 // /* XXX what happens when a mapping is configured to use the loc-set ? */
655 // if (vec_len (vec_elt_at_index(lcm->locator_set_to_eids, p[0])) != 0)
657 // clib_warning ("Can't delete a locator that supports a mapping!");
661 if (vec_len(lcm->locator_set_to_eids) != 0)
663 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids, p[0]);
664 if (vec_len(eid_indexes[0]) != 0)
666 clib_warning ("Can't delete a locator that supports a mapping!");
671 /* clean locator to locator-sets data */
672 clean_locator_to_locator_set (lcm, p[0]);
678 vec_foreach_index(it, lcm->local_locator_set_indexes)
680 lsi = vec_elt(lcm->local_locator_set_indexes, it);
683 vec_del1(lcm->local_locator_set_indexes, it);
687 hash_unset_mem(lcm->locator_set_index_by_name, ls->name);
690 pool_put(lcm->locator_set_pool, ls);
696 uword *vnet_lisp_get_locator(vnet_lisp_add_del_locator_set_args_t * a,
699 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
704 /* find locator-set */
707 p = hash_get_mem(lcm->locator_set_index_by_name, a->name);
718 vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a,
721 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
723 uword _p = (u32)~0, * p = &_p;
725 u32 **eid_indexes = NULL;
728 ASSERT(ls_result != NULL);
730 p = vnet_lisp_get_locator(a, p);
735 if (p && p[0] != (u32)~0)
737 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
740 clib_warning("locator-set %d to be overwritten doesn't exist!",
742 return VNET_API_ERROR_UNSPECIFIED;
745 /* clean locator to locator-set vectors and remove locators if
746 * they're not part of another locator-set */
747 clean_locator_to_locator_set (lcm, p[0]);
749 /* remove locator indices from locator set */
750 vec_free(ls->locator_indices);
757 /* new locator-set */
760 pool_get(lcm->locator_set_pool, ls);
761 ls_index = ls - lcm->locator_set_pool;
765 ls->name = vec_dup(a->name);
767 if (!lcm->locator_set_index_by_name)
768 lcm->locator_set_index_by_name = hash_create_vec(
769 /* size */0, sizeof(ls->name[0]), sizeof(uword));
770 hash_set_mem(lcm->locator_set_index_by_name, ls->name, ls_index);
772 /* mark as local locator-set */
773 vec_add1(lcm->local_locator_set_indexes, ls_index);
775 ls->local = a->local;
776 ls->locator_indices = NULL;
778 ls_result[0] = ls_index;
785 clib_warning("locator-set %v doesn't exists", a->name);
786 return VNET_API_ERROR_INVALID_ARGUMENT;
789 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
792 clib_warning("locator-set with index %d doesn't exists", p[0]);
793 return VNET_API_ERROR_INVALID_ARGUMENT;
796 if (vec_len(lcm->locator_set_to_eids) != 0)
798 eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids, p[0]);
799 if (vec_len(eid_indexes[0]) != 0)
801 clib_warning ("Can't delete a locator that supports a mapping!");
806 /* clean locator to locator-sets data */
807 clean_locator_to_locator_set (lcm, p[0]);
813 vec_foreach_index(it, lcm->local_locator_set_indexes)
815 lsi = vec_elt(lcm->local_locator_set_indexes, it);
818 vec_del1(lcm->local_locator_set_indexes, it);
822 hash_unset_mem(lcm->locator_set_index_by_name, ls->name);
825 pool_put(lcm->locator_set_pool, ls);
831 vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t *a,
834 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
835 locator_set_t *ls = NULL;
836 locator_t *loc = NULL, *itloc = NULL;
837 uword _p = (u32)~0, * p = &_p;
838 u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL;
842 ASSERT(ls_result != NULL);
844 p = vnet_lisp_get_locator(a, p);
846 clib_warning("locator-set %v doesn't exists", a->name);
847 return VNET_API_ERROR_INVALID_ARGUMENT;
854 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
857 clib_warning("locator-set %d to be overwritten doesn't exist!",
859 return VNET_API_ERROR_INVALID_ARGUMENT;
865 /* allocate locators */
867 pool_get(lcm->locator_pool, loc);
869 loc_index = loc - lcm->locator_pool;
871 vec_add1(ls->locator_indices, loc_index);
873 vec_validate (lcm->locator_to_locator_sets, loc_index);
874 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
876 vec_add1(ls_indexes[0], ls_index);
880 ls = pool_elt_at_index(lcm->locator_set_pool, p[0]);
883 clib_warning("locator-set with index %d doesn't exists", p[0]);
884 return VNET_API_ERROR_INVALID_ARGUMENT;
891 vec_foreach (locit, ls->locator_indices)
893 loc = pool_elt_at_index(lcm->locator_pool, locit[0]);
894 if (loc->local && loc->sw_if_index == itloc->sw_if_index)
896 ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets,
898 pool_put_index(lcm->locator_pool, locit[0]);
899 vec_del1(ls->locator_indices, i);
900 vec_del1(ls_indexes[0], ls_index);
910 vnet_lisp_enable_disable (u8 is_enabled)
912 vnet_lisp_gpe_add_del_iface_args_t _ai, * ai= &_ai;
913 uword * table_id, * refc;
915 clib_error_t * error = 0;
916 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
917 vnet_lisp_gpe_enable_disable_args_t _a, * a = &_a;
919 a->is_en = is_enabled;
920 error = vnet_lisp_gpe_enable_disable (a);
923 return clib_error_return (0, "failed to %s data-plane!",
924 a->is_en ? "enable" : "disable");
929 /* enable all ifaces */
930 for (i = 0; i < vec_len (lcm->local_mappings_indexes); i++)
932 mapping_t * m = vec_elt_at_index (lcm->mapping_pool, i);
934 ai->vni = gid_address_vni (&m->eid);
936 refc = hash_get (lcm->dp_if_refcount_by_vni, ai->vni);
939 table_id = hash_get (lcm->table_id_by_vni, ai->vni);
942 ai->table_id = table_id[0];
943 /* enables interface and adds defaults */
944 vnet_lisp_gpe_add_del_iface (ai, 0);
947 return clib_error_return (0, "no table_id found for vni %u!",
950 hash_set (lcm->dp_if_refcount_by_vni, ai->vni, 1);
960 /* clear refcount table */
961 hash_free (lcm->dp_if_refcount_by_vni);
962 hash_free (lcm->fwd_entry_by_mapping_index);
963 pool_free (lcm->fwd_entry_pool);
966 /* update global flag */
967 lcm->is_enabled = is_enabled;
972 static clib_error_t *
973 lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
974 vlib_cli_command_t * cmd)
976 unformat_input_t _line_input, * line_input = &_line_input;
980 /* Get a line of input. */
981 if (! unformat_user (input, unformat_line_input, line_input))
984 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
986 if (unformat (line_input, "enable"))
991 else if (unformat (line_input, "disable"))
995 return clib_error_return (0, "parse error: '%U'",
996 format_unformat_error, line_input);
1001 return clib_error_return (0, "state not set");
1003 return vnet_lisp_enable_disable (is_enabled);
1006 VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
1008 .short_help = "lisp [enable|disable]",
1009 .function = lisp_enable_disable_command_fn,
1013 vnet_lisp_enable_disable_status (void)
1015 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1016 return lcm->is_enabled;
1020 format_lisp_status (u8 * s, va_list * args)
1022 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
1023 return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
1026 static clib_error_t *
1027 lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input,
1028 vlib_cli_command_t * cmd)
1031 msg = format (msg, "feature: %U\ngpe: %U\n",
1032 format_lisp_status, format_vnet_lisp_gpe_status);
1033 vlib_cli_output (vm, "%v", msg);
1038 VLIB_CLI_COMMAND (lisp_show_status_command) = {
1039 .path = "show lisp status",
1040 .short_help = "show lisp status",
1041 .function = lisp_show_status_command_fn,
1043 static clib_error_t *
1044 lisp_add_del_locator_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
1045 vlib_cli_command_t * cmd)
1047 lisp_gpe_main_t * lgm = &lisp_gpe_main;
1048 vnet_main_t * vnm = lgm->vnet_main;
1049 unformat_input_t _line_input, * line_input = &_line_input;
1051 clib_error_t * error = 0;
1052 u8 * locator_set_name = 0;
1053 locator_t locator, * locators = 0;
1054 vnet_lisp_add_del_locator_set_args_t _a, * a = &_a;
1057 memset(&locator, 0, sizeof(locator));
1058 memset(a, 0, sizeof(a[0]));
1060 /* Get a line of input. */
1061 if (! unformat_user (input, unformat_line_input, line_input))
1064 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1066 if (unformat (line_input, "add %_%v%_", &locator_set_name))
1068 else if (unformat (line_input, "del %_%v%_", &locator_set_name))
1070 else if (unformat (line_input, "iface %U p %d w %d",
1071 unformat_vnet_sw_interface, vnm, &locator.sw_if_index,
1072 &locator.priority, &locator.weight))
1075 vec_add1(locators, locator);
1079 error = unformat_parse_error(line_input);
1084 a->name = locator_set_name;
1085 a->locators = locators;
1089 vnet_lisp_add_del_locator_set(a, &ls_index);
1093 vec_free(locator_set_name);
1097 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
1098 .path = "lisp locator-set",
1099 .short_help = "lisp locator-set add/del <name> iface <iface-name> "
1100 "p <priority> w <weight>",
1101 .function = lisp_add_del_locator_set_command_fn,
1104 static clib_error_t *
1105 lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
1106 unformat_input_t * input,
1107 vlib_cli_command_t * cmd)
1109 locator_set_t * lsit;
1112 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1114 vlib_cli_output (vm, "%=20s%=16s%=16s%=16s", "Locator-set", "Locator",
1115 "Priority", "Weight");
1116 pool_foreach (lsit, lcm->locator_set_pool,
1119 msg = format (msg, "%-16v", lsit->name);
1120 vec_foreach (locit, lsit->locator_indices)
1122 loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1124 msg = format (msg, "%16d%16d%16d", loc->sw_if_index, loc->priority,
1127 msg = format (msg, "%16U%16d%16d", format_gid_address, &loc->address,
1128 loc->priority, loc->weight);
1130 vlib_cli_output (vm, "%v", msg);
1136 VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
1137 .path = "show lisp locator-set",
1138 .short_help = "Shows locator-sets",
1139 .function = lisp_cp_show_locator_sets_command_fn,
1143 vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a)
1145 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
1146 ip_address_t * addr;
1151 vec_foreach(addr, lcm->map_resolvers)
1153 if (!ip_address_cmp (addr, &a->address))
1155 clib_warning("map-resolver %U already exists!", format_ip_address,
1160 vec_add1(lcm->map_resolvers, a->address);
1164 for (i = 0; i < vec_len(lcm->map_resolvers); i++)
1166 addr = vec_elt_at_index(lcm->map_resolvers, i);
1167 if (!ip_address_cmp (addr, &a->address))
1169 vec_delete(lcm->map_resolvers, 1, i);
1177 static clib_error_t *
1178 lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
1179 unformat_input_t * input,
1180 vlib_cli_command_t * cmd)
1182 unformat_input_t _line_input, * line_input = &_line_input;
1184 ip_address_t ip_addr;
1185 clib_error_t * error = 0;
1186 vnet_lisp_add_del_map_resolver_args_t _a, * a = &_a;
1188 /* Get a line of input. */
1189 if (! unformat_user (input, unformat_line_input, line_input))
1192 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1194 if (unformat (line_input, "add"))
1196 else if (unformat (line_input, "del"))
1198 else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
1202 error = unformat_parse_error(line_input);
1207 a->address = ip_addr;
1208 vnet_lisp_add_del_map_resolver (a);
1214 VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
1215 .path = "lisp map-resolver",
1216 .short_help = "lisp map-resolver add/del <ip_address>",
1217 .function = lisp_add_del_map_resolver_command_fn,
1220 /* Statistics (not really errors) */
1221 #define foreach_lisp_cp_lookup_error \
1223 _(MAP_REQUESTS_SENT, "map-request sent")
1225 static char * lisp_cp_lookup_error_strings[] = {
1226 #define _(sym,string) string,
1227 foreach_lisp_cp_lookup_error
1233 #define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
1234 foreach_lisp_cp_lookup_error
1236 LISP_CP_LOOKUP_N_ERROR,
1237 } lisp_cp_lookup_error_t;
1241 LISP_CP_LOOKUP_NEXT_DROP,
1242 LISP_CP_LOOKUP_NEXT_IP4_LOOKUP,
1243 LISP_CP_LOOKUP_NEXT_IP6_LOOKUP,
1244 LISP_CP_LOOKUP_N_NEXT,
1245 } lisp_cp_lookup_next_t;
1249 gid_address_t dst_eid;
1250 ip4_address_t map_resolver_ip;
1251 } lisp_cp_lookup_trace_t;
1254 format_lisp_cp_lookup_trace (u8 * s, va_list * args)
1256 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1257 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1258 lisp_cp_lookup_trace_t * t = va_arg (*args, lisp_cp_lookup_trace_t *);
1260 s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
1261 format_ip_address, &t->map_resolver_ip, format_gid_address,
1267 ip_fib_lookup_with_table (lisp_cp_main_t * lcm, u32 fib_index,
1270 if (ip_addr_version (dst) == IP4)
1271 return ip4_fib_lookup_with_table (lcm->im4, fib_index, &ip_addr_v4(dst),
1274 return ip6_fib_lookup_with_table (lcm->im6, fib_index, &ip_addr_v6(dst));
1278 get_mr_and_local_iface_ip (lisp_cp_main_t *lcm, ip_address_t * mr_ip,
1279 ip_address_t * sloc)
1282 ip_adjacency_t * adj;
1283 ip_interface_address_t * ia = 0;
1284 ip_lookup_main_t * lm;
1285 ip4_address_t * l4 = 0;
1286 ip6_address_t * l6 = 0;
1287 ip_address_t * mrit;
1289 if (vec_len(lcm->map_resolvers) == 0)
1291 clib_warning("No map-resolver configured");
1295 /* find the first mr ip we have a route to and the ip of the
1296 * iface that has a route to it */
1297 vec_foreach(mrit, lcm->map_resolvers)
1299 lm = ip_addr_version (mrit) == IP4 ?
1300 &lcm->im4->lookup_main : &lcm->im6->lookup_main;
1302 adj_index = ip_fib_lookup_with_table (lcm, 0, mrit);
1303 adj = ip_get_adjacency (lm, adj_index);
1308 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP)
1310 ia = pool_elt_at_index(lm->if_address_pool, adj->if_address_index);
1311 if (ip_addr_version(mrit) == IP4)
1313 l4 = ip_interface_address_get_address (lm, ia);
1317 l6 = ip_interface_address_get_address (lm, ia);
1320 else if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE)
1322 /* find sw_if_index in rewrite header */
1323 u32 sw_if_index = adj->rewrite_header.sw_if_index;
1325 /* find suitable address */
1326 if (ip_addr_version(mrit) == IP4)
1328 /* find the first ip address */
1329 foreach_ip_interface_address (&lcm->im4->lookup_main, ia,
1330 sw_if_index, 1 /* unnumbered */,
1332 l4 = ip_interface_address_get_address (&lcm->im4->lookup_main,
1339 /* find the first ip address */
1340 foreach_ip_interface_address (&lcm->im6->lookup_main, ia,
1341 sw_if_index, 1 /* unnumbered */,
1343 l6 = ip_interface_address_get_address (&lcm->im6->lookup_main,
1352 ip_addr_v4(sloc).as_u32 = l4->as_u32;
1353 ip_addr_version(sloc) = IP4;
1354 ip_address_copy(mr_ip, mrit);
1359 clib_memcpy (&ip_addr_v6(sloc), l6, sizeof(*l6));
1360 ip_addr_version(sloc) = IP6;
1361 ip_address_copy(mr_ip, mrit);
1366 clib_warning("Can't find map-resolver and local interface ip!");
1370 static gid_address_t *
1371 build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
1378 ip_interface_address_t * ia = 0;
1379 gid_address_t gid_data, * gid = &gid_data;
1380 gid_address_t * rlocs = 0;
1381 ip_prefix_t * ippref = &gid_address_ippref (gid);
1382 ip_address_t * rloc = &ip_prefix_addr (ippref);
1384 gid_address_type (gid) = GID_ADDR_IP_PREFIX;
1385 for (i = 0; i < vec_len(loc_set->locator_indices); i++)
1387 loc_indexp = vec_elt_at_index(loc_set->locator_indices, i);
1388 loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
1390 ip_addr_version(rloc) = IP4;
1391 /* Add ipv4 locators first TODO sort them */
1392 foreach_ip_interface_address (&lcm->im4->lookup_main, ia,
1393 loc->sw_if_index, 1 /* unnumbered */,
1395 l4 = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
1396 ip_addr_v4 (rloc) = l4[0];
1397 ip_prefix_len (ippref) = 32;
1398 vec_add1 (rlocs, gid[0]);
1401 ip_addr_version(rloc) = IP6;
1402 /* Add ipv6 locators */
1403 foreach_ip_interface_address (&lcm->im6->lookup_main, ia,
1404 loc->sw_if_index, 1 /* unnumbered */,
1406 l6 = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
1407 ip_addr_v6 (rloc) = l6[0];
1408 ip_prefix_len (ippref) = 128;
1409 vec_add1 (rlocs, gid[0]);
1415 static vlib_buffer_t *
1416 build_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
1417 gid_address_t * seid, gid_address_t * deid,
1418 locator_set_t * loc_set, ip_address_t * mr_ip,
1419 ip_address_t * sloc, u8 is_smr_invoked,
1420 u64 *nonce_res, u32 * bi_res)
1424 gid_address_t * rlocs = 0;
1426 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
1428 clib_warning ("Can't allocate buffer for Map-Request!");
1432 b = vlib_get_buffer (vm, bi);
1434 /* leave some space for the encap headers */
1435 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
1438 rlocs = build_itr_rloc_list (lcm, loc_set);
1441 lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked, nonce_res);
1443 /* push ecm: udp-ip-lisp */
1444 lisp_msg_push_ecm (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, seid, deid);
1446 /* push outer ip header */
1447 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
1458 send_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm,
1459 gid_address_t * seid, gid_address_t * deid,
1462 u32 next_index, bi = 0, * to_next, map_index;
1466 locator_set_t * loc_set;
1468 pending_map_request_t * pmr;
1469 ip_address_t mr_ip, sloc;
1471 /* get locator-set for seid */
1472 map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
1473 if (map_index == ~0)
1475 clib_warning("No local mapping found in eid-table for %U!",
1476 format_gid_address, seid);
1480 map = pool_elt_at_index (lcm->mapping_pool, map_index);
1484 clib_warning("Mapping found for src eid %U is not marked as local!",
1485 format_gid_address, seid);
1488 loc_set = pool_elt_at_index (lcm->locator_set_pool, map->locator_set_index);
1490 /* get local iface ip to use in map-request XXX fib 0 for now*/
1491 get_mr_and_local_iface_ip (lcm, &mr_ip, &sloc);
1493 /* build the encapsulated map request */
1494 b = build_encapsulated_map_request (vm, lcm, seid, deid, loc_set, &mr_ip,
1495 &sloc, is_smr_invoked, &nonce, &bi);
1500 /* set fib index and lookup node */
1501 vnet_buffer(b)->sw_if_index[VLIB_TX] = ~0;
1502 next_index = (ip_addr_version(&mr_ip) == IP4) ?
1503 ip4_lookup_node.index : ip6_lookup_node.index;
1505 f = vlib_get_frame_to_node (vm, next_index);
1507 /* Enqueue the packet */
1508 to_next = vlib_frame_vector_args (f);
1511 vlib_put_frame_to_node (vm, next_index, f);
1513 /* add map-request to pending requests table */
1514 pool_get(lcm->pending_map_requests_pool, pmr);
1515 gid_address_copy (&pmr->src, seid);
1516 gid_address_copy (&pmr->dst, deid);
1517 pmr->src_mapping_index = map_index;
1518 hash_set(lcm->pending_map_requests_by_nonce, nonce,
1519 pmr - lcm->pending_map_requests_pool);
1523 get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst)
1525 ip4_header_t * ip4 = hdr;
1528 if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
1530 ip_addr_v4(src).as_u32 = ip4->src_address.as_u32;
1531 ip_addr_version(src) = IP4;
1532 ip_addr_v4(dst).as_u32 = ip4->dst_address.as_u32;
1533 ip_addr_version(dst) = IP4;
1538 clib_memcpy (&ip_addr_v6(src), &ip6->src_address, sizeof(ip6->src_address));
1539 ip_addr_version(src) = IP6;
1540 clib_memcpy (&ip_addr_v6(dst), &ip6->dst_address, sizeof(ip6->dst_address));
1541 ip_addr_version(dst) = IP6;
1546 lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
1547 vlib_frame_t * from_frame)
1549 u32 * from, * to_next_drop, di, si;
1550 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main();
1551 u32 pkts_mapped = 0;
1552 uword n_left_from, n_left_to_next_drop;
1554 from = vlib_frame_vector_args (from_frame);
1555 n_left_from = from_frame->n_vectors;
1557 while (n_left_from > 0)
1559 vlib_get_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
1560 to_next_drop, n_left_to_next_drop);
1562 while (n_left_from > 0 && n_left_to_next_drop > 0)
1567 gid_address_t src, dst;
1568 ip_prefix_t * spref, * dpref;
1570 gid_address_type (&src) = GID_ADDR_IP_PREFIX;
1571 spref = &gid_address_ippref(&src);
1572 gid_address_type (&dst) = GID_ADDR_IP_PREFIX;
1573 dpref = &gid_address_ippref(&dst);
1578 to_next_drop[0] = pi0;
1580 n_left_to_next_drop -= 1;
1582 p0 = vlib_get_buffer (vm, pi0);
1583 p0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
1585 /* src/dst eid pair */
1586 ip0 = vlib_buffer_get_current (p0);
1587 get_src_and_dst (ip0, &ip_prefix_addr(spref), &ip_prefix_addr(dpref));
1588 ip_prefix_len(spref) = ip_address_max_len (ip_prefix_version(spref));
1589 ip_prefix_len(dpref) = ip_address_max_len (ip_prefix_version(dpref));
1591 /* if we have remote mapping for destination already in map-chache
1592 add forwarding tunnel directly. If not send a map-request */
1593 di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
1596 si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &src);
1599 add_fwd_entry (lcm, si, di);
1604 /* send map-request */
1605 send_encapsulated_map_request (vm, lcm, &src, &dst, 0);
1609 if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
1611 lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, p0,
1613 gid_address_copy (&tr->dst_eid, &dst);
1614 clib_memcpy (&tr->map_resolver_ip,
1615 vec_elt_at_index(lcm->map_resolvers, 0),
1616 sizeof(ip_address_t));
1620 vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, n_left_to_next_drop);
1622 vlib_node_increment_counter (vm, node->node_index,
1623 LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
1625 return from_frame->n_vectors;
1628 VLIB_REGISTER_NODE (lisp_cp_lookup_node) = {
1629 .function = lisp_cp_lookup,
1630 .name = "lisp-cp-lookup",
1631 .vector_size = sizeof (u32),
1632 .format_trace = format_lisp_cp_lookup_trace,
1633 .type = VLIB_NODE_TYPE_INTERNAL,
1635 .n_errors = LISP_CP_LOOKUP_N_ERROR,
1636 .error_strings = lisp_cp_lookup_error_strings,
1638 .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
1641 [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
1642 [LISP_CP_LOOKUP_NEXT_IP4_LOOKUP] = "ip4-lookup",
1643 [LISP_CP_LOOKUP_NEXT_IP6_LOOKUP] = "ip6-lookup",
1647 /* lisp_cp_input statistics */
1648 #define foreach_lisp_cp_input_error \
1650 _(MAP_REPLIES_RECEIVED, "map-replies received")
1652 static char * lisp_cp_input_error_strings[] = {
1653 #define _(sym,string) string,
1654 foreach_lisp_cp_input_error
1660 #define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
1661 foreach_lisp_cp_input_error
1663 LISP_CP_INPUT_N_ERROR,
1664 } lisp_cp_input_error_t;
1668 LISP_CP_INPUT_NEXT_DROP,
1669 LISP_CP_INPUT_N_NEXT,
1670 } lisp_cp_input_next_t;
1674 gid_address_t dst_eid;
1675 ip4_address_t map_resolver_ip;
1676 } lisp_cp_input_trace_t;
1679 format_lisp_cp_input_trace (u8 * s, va_list * args)
1681 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1682 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1683 CLIB_UNUSED(lisp_cp_input_trace_t * t) = va_arg (*args, lisp_cp_input_trace_t *);
1685 s = format (s, "LISP-CP-INPUT: TODO");
1689 ip_interface_address_t *
1690 ip_interface_get_first_interface_address (ip_lookup_main_t *lm, u32 sw_if_index,
1693 vnet_main_t *vnm = vnet_get_main ();
1694 vnet_sw_interface_t * swif = vnet_get_sw_interface (vnm, sw_if_index);
1695 if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
1696 sw_if_index = swif->unnumbered_sw_if_index;
1698 (vec_len((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
1699 vec_elt((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
1701 return pool_elt_at_index((lm)->if_address_pool, ia);
1705 ip_interface_get_first_ip_addres (ip_lookup_main_t *lm, u32 sw_if_index,
1708 ip_interface_address_t * ia = ip_interface_get_first_interface_address (
1709 lm, sw_if_index, loop);
1710 return ip_interface_address_get_address (lm, ia);
1714 del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index,
1717 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
1718 fwd_entry_t * fe = 0;
1720 memset(a, 0, sizeof(*a));
1722 feip = hash_get(lcm->fwd_entry_by_mapping_index, dst_map_index);
1726 fe = pool_elt_at_index(lcm->fwd_entry_pool, feip[0]);
1728 /* delete dp fwd entry */
1731 a->dlocator = fe->dst_loc;
1732 a->slocator = fe->src_loc;
1733 a->vni = gid_address_vni(&a->deid);
1734 gid_address_copy(&a->deid, &fe->deid);
1736 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
1738 /* delete entry in fwd table */
1739 hash_unset(lcm->fwd_entry_by_mapping_index, dst_map_index);
1740 pool_put(lcm->fwd_entry_pool, fe);
1744 add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index)
1746 mapping_t * src_map, * dst_map;
1747 locator_set_t * dst_ls, * src_ls;
1748 u32 i, minp = ~0, sw_if_index;
1750 uword * feip = 0, * tidp;
1752 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a;
1754 memset (a, 0, sizeof(*a));
1756 /* remove entry if it already exists */
1757 feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
1759 del_fwd_entry (lcm, src_map_index, dst_map_index);
1761 src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
1762 dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
1764 gid_address_copy (&a->deid, &dst_map->eid);
1765 a->vni = gid_address_vni(&a->deid);
1767 tidp = hash_get(lcm->table_id_by_vni, a->vni);
1770 clib_warning("vni %d not associated to a vrf!", a->vni);
1773 a->table_id = tidp[0];
1775 /* XXX simple forwarding policy: first lowest (value) priority locator */
1776 dst_ls = pool_elt_at_index (lcm->locator_set_pool,
1777 dst_map->locator_set_index);
1778 for (i = 0; i < vec_len (dst_ls->locator_indices); i++)
1780 u32 li = vec_elt (dst_ls->locator_indices, i);
1781 locator_t * l = pool_elt_at_index (lcm->locator_pool, li);
1782 if (l->priority < minp && gid_address_type(&l->address)
1783 == GID_ADDR_IP_PREFIX)
1791 src_ls = pool_elt_at_index(lcm->locator_set_pool,
1792 src_map->locator_set_index);
1793 for (i = 0; i < vec_len(src_ls->locator_indices); i++)
1795 u32 li = vec_elt (src_ls->locator_indices, i);
1796 locator_t * sl = pool_elt_at_index (lcm->locator_pool, li);
1798 if (ip_addr_version(&gid_address_ip(&dl->address)) == IP4)
1801 l4 = ip_interface_get_first_ip_addres (&lcm->im4->lookup_main,
1803 1 /* unnumbered */);
1804 ip_addr_v4(&a->slocator) = *l4;
1805 ip_addr_version(&a->slocator) = IP4;
1810 l6 = ip_interface_get_first_ip_addres (&lcm->im6->lookup_main,
1812 1 /* unnumbered */);
1813 ip_addr_v6(&a->slocator) = *l6;
1814 ip_addr_version(&a->slocator) = IP6;
1819 /* insert data plane forwarding entry */
1822 a->dlocator = gid_address_ip(&dl->address);
1826 a->action = dst_map->action;
1830 u8 ipver = ip_prefix_version(&gid_address_ippref(&a->deid));
1831 a->decap_next_index = (ipver == IP4) ?
1832 LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
1834 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
1836 /* add tunnel to fwd entry table XXX check return value from DP insertion */
1837 pool_get (lcm->fwd_entry_pool, fe);
1838 fe->dst_loc = a->dlocator;
1839 fe->src_loc = a->slocator;
1840 gid_address_copy (&fe->deid, &a->deid);
1841 hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
1842 fe - lcm->fwd_entry_pool);
1845 /* return 0 if the two locator sets are identical 1 otherwise */
1847 compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes,
1848 locator_t * new_locators)
1851 locator_t * old_loc, * new_loc;
1853 if (vec_len (old_ls_indexes) != vec_len(new_locators))
1856 for (i = 0; i < vec_len(new_locators); i++)
1858 old_li = vec_elt(old_ls_indexes, i);
1859 old_loc = pool_elt_at_index(lcm->locator_pool, old_li);
1861 new_loc = vec_elt_at_index(new_locators, i);
1863 if (locator_cmp (old_loc, new_loc))
1870 process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b)
1873 u32 len = 0, i, ls_index = 0;
1875 vnet_lisp_add_del_locator_set_args_t _ls_arg, * ls_arg = &_ls_arg;
1876 vnet_lisp_add_del_mapping_args_t _m_args, * m_args = &_m_args;
1877 pending_map_request_t * pmr;
1879 map_reply_hdr_t * mrep_hdr;
1881 u32 dst_map_index, mi;
1884 mrep_hdr = vlib_buffer_get_current (b);
1886 /* Check pending requests table and nonce */
1887 nonce = MREP_NONCE(mrep_hdr);
1888 pmr_index = hash_get(lcm->pending_map_requests_by_nonce, nonce);
1891 clib_warning("No pending map-request entry with nonce %lu!", nonce);
1894 pmr = pool_elt_at_index(lcm->pending_map_requests_pool, pmr_index[0]);
1896 vlib_buffer_pull (b, sizeof(*mrep_hdr));
1898 for (i = 0; i < MREP_REC_COUNT(mrep_hdr); i++)
1900 memset (ls_arg, 0, sizeof(*ls_arg));
1901 memset (m_args, 0, sizeof(*m_args));
1903 h = vlib_buffer_get_current (b);
1904 m_args->ttl = clib_net_to_host_u32 (MAP_REC_TTL(h));
1905 m_args->action = MAP_REC_ACTION(h);
1906 m_args->authoritative = MAP_REC_AUTH(h);
1908 len = lisp_msg_parse_mapping_record (b, &m_args->deid, &ls_arg->locators,
1912 clib_warning ("Failed to parse mapping record!");
1913 vec_foreach (loc, ls_arg->locators)
1917 vec_free(ls_arg->locators);
1921 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &m_args->deid);
1923 /* if mapping already exists, decide if locators (and forwarding) should
1924 * be updated and be done */
1927 mapping_t * old_map;
1928 locator_set_t * old_ls;
1929 old_map = pool_elt_at_index(lcm->mapping_pool, mi);
1931 /* update mapping attributes */
1932 old_map->action = m_args->action;
1933 old_map->authoritative = m_args->authoritative;
1934 old_map->ttl = m_args->ttl;
1936 old_ls = pool_elt_at_index(lcm->locator_set_pool,
1937 old_map->locator_set_index);
1938 /* if the two locators are not equal, update them and forwarding
1939 * otherwise there's nothing to be done */
1940 if (compare_locators (lcm, old_ls->locator_indices, ls_arg->locators))
1942 /* set locator-set index to overwrite */
1944 ls_arg->index = old_map->locator_set_index;
1945 vnet_lisp_add_del_locator_set (ls_arg, 0);
1946 add_fwd_entry (lcm, pmr->src_mapping_index, mi);
1952 /* add locator-set */
1955 vnet_lisp_add_del_locator_set (ls_arg, &ls_index);
1959 m_args->locator_set_index = ls_index;
1960 vnet_lisp_add_del_mapping (m_args, &dst_map_index);
1962 /* add forwarding tunnel */
1963 add_fwd_entry (lcm, pmr->src_mapping_index, dst_map_index);
1965 vec_free(ls_arg->locators);
1968 /* remove pending map request entry */
1969 hash_unset(lcm->pending_map_requests_by_nonce, nonce);
1970 pool_put(lcm->pending_map_requests_pool, pmr);
1974 process_map_request (vlib_main_t * vm, lisp_cp_main_t * lcm, vlib_buffer_t * b)
1976 map_request_hdr_t * mreq_hdr;
1977 gid_address_t src, dst;
1980 gid_address_t * itr_rlocs = 0, * rloc;
1982 mreq_hdr = vlib_buffer_get_current (b);
1983 vlib_buffer_pull (b, sizeof(*mreq_hdr));
1985 // nonce = MREQ_NONCE(mreq_hdr);
1987 if (!MREQ_SMR(mreq_hdr)) {
1988 clib_warning("Only SMR Map-Requests supported for now!");
1993 len = lisp_msg_parse_addr (b, &src);
1997 /* for now we don't do anything with the itr's rlocs */
1998 len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs, MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1);
2002 /* TODO: RLOCs are currently unused, so free them for now */
2003 vec_foreach (rloc, itr_rlocs)
2005 gid_address_free (rloc);
2008 /* parse eid records and send SMR-invoked map-requests */
2009 for (i = 0; i < MREQ_REC_COUNT(mreq_hdr); i++)
2011 memset(&dst, 0, sizeof(dst));
2012 len = lisp_msg_parse_eid_rec (b, &dst);
2015 clib_warning("Can't parse map-request EID-record");
2018 /* send SMR-invoked map-requests */
2019 send_encapsulated_map_request (vm, lcm, &dst, &src, /* invoked */ 1);
2024 lisp_cp_input (vlib_main_t * vm, vlib_node_runtime_t * node,
2025 vlib_frame_t * from_frame)
2027 u32 n_left_from, * from, * to_next_drop;
2028 lisp_msg_type_e type;
2029 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2031 from = vlib_frame_vector_args (from_frame);
2032 n_left_from = from_frame->n_vectors;
2035 while (n_left_from > 0)
2037 u32 n_left_to_next_drop;
2039 vlib_get_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP,
2040 to_next_drop, n_left_to_next_drop);
2041 while (n_left_from > 0 && n_left_to_next_drop > 0)
2049 to_next_drop[0] = bi0;
2051 n_left_to_next_drop -= 1;
2053 b0 = vlib_get_buffer (vm, bi0);
2055 type = lisp_msg_type(vlib_buffer_get_current (b0));
2058 case LISP_MAP_REPLY:
2059 process_map_reply (lcm, b0);
2061 case LISP_MAP_REQUEST:
2062 process_map_request(vm, lcm, b0);
2065 clib_warning("Unsupported LISP message type %d", type);
2069 b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
2071 if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
2077 vlib_put_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP, n_left_to_next_drop);
2079 return from_frame->n_vectors;
2082 VLIB_REGISTER_NODE (lisp_cp_input_node) = {
2083 .function = lisp_cp_input,
2084 .name = "lisp-cp-input",
2085 .vector_size = sizeof (u32),
2086 .format_trace = format_lisp_cp_input_trace,
2087 .type = VLIB_NODE_TYPE_INTERNAL,
2089 .n_errors = LISP_CP_INPUT_N_ERROR,
2090 .error_strings = lisp_cp_input_error_strings,
2092 .n_next_nodes = LISP_CP_INPUT_N_NEXT,
2095 [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
2100 lisp_cp_init (vlib_main_t *vm)
2102 lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
2103 clib_error_t * error = 0;
2105 if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
2108 lcm->im4 = &ip4_main;
2109 lcm->im6 = &ip6_main;
2110 lcm->vlib_main = vm;
2111 lcm->vnet_main = vnet_get_main();
2113 gid_dictionary_init (&lcm->mapping_index_by_gid);
2115 /* default vrf mapped to vni 0 */
2116 hash_set(lcm->table_id_by_vni, 0, 0);
2118 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
2119 lisp_cp_input_node.index, 1 /* is_ip4 */);
2120 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
2121 lisp_cp_input_node.index, 0 /* is_ip4 */);
2126 VLIB_INIT_FUNCTION(lisp_cp_init);