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 <vlibmemory/api.h>
17 #include <vnet/lisp-cp/control.h>
18 #include <vnet/lisp-cp/packets.h>
19 #include <vnet/lisp-cp/lisp_msg_serdes.h>
20 #include <vnet/lisp-gpe/lisp_gpe.h>
21 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
22 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
23 #include <vnet/fib/fib_entry.h>
24 #include <vnet/fib/fib_table.h>
26 #include <openssl/evp.h>
27 #include <openssl/hmac.h>
29 u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
33 LISP_CP_INPUT_NEXT_DROP,
35 } lisp_cp_input_next_t;
53 lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid,
54 gid_address_t * remote_eid, u8 is_add);
57 vnet_lisp_get_map_request_mode (void)
59 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
60 return lcm->map_request_mode;
64 auth_data_len_by_key_id (lisp_key_type_t key_id)
69 return SHA1_AUTH_DATA_LEN;
70 case HMAC_SHA_256_128:
71 return SHA256_AUTH_DATA_LEN;
73 clib_warning ("unsupported key type: %d!", key_id);
80 get_encrypt_fcn (lisp_key_type_t key_id)
86 case HMAC_SHA_256_128:
89 clib_warning ("unsupported encryption key type: %d!", key_id);
96 queue_map_request (gid_address_t * seid, gid_address_t * deid,
97 u8 smr_invoked, u8 is_resend);
99 ip_interface_address_t *
100 ip_interface_get_first_interface_address (ip_lookup_main_t * lm,
101 u32 sw_if_index, u8 loop)
103 vnet_main_t *vnm = vnet_get_main ();
104 vnet_sw_interface_t *swif = vnet_get_sw_interface (vnm, sw_if_index);
105 if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
106 sw_if_index = swif->unnumbered_sw_if_index;
108 (vec_len ((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
109 vec_elt ((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
111 return pool_elt_at_index ((lm)->if_address_pool, ia);
115 ip_interface_get_first_address (ip_lookup_main_t * lm, u32 sw_if_index,
118 ip_interface_address_t *ia;
120 ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
123 return ip_interface_address_get_address (lm, ia);
127 ip_interface_get_first_ip_address (lisp_cp_main_t * lcm, u32 sw_if_index,
128 u8 version, ip_address_t * result)
130 ip_lookup_main_t *lm;
133 lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
134 addr = ip_interface_get_first_address (lm, sw_if_index, version);
138 ip_address_set (result, addr, version);
143 * convert from a LISP address to a FIB prefix
146 ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
148 if (addr->version == IP4)
151 prefix->fp_proto = FIB_PROTOCOL_IP4;
152 memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
153 memcpy (&prefix->fp_addr.ip4, &addr->ip, sizeof (prefix->fp_addr.ip4));
157 prefix->fp_len = 128;
158 prefix->fp_proto = FIB_PROTOCOL_IP6;
159 memcpy (&prefix->fp_addr.ip6, &addr->ip, sizeof (prefix->fp_addr.ip6));
164 * convert from a LISP to a FIB prefix
167 ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
168 fib_prefix_t * fib_prefix)
170 ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
171 fib_prefix->fp_len = ip_prefix->len;
175 * Find the sw_if_index of the interface that would be used to egress towards
179 ip_fib_get_egress_iface_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst)
181 fib_node_index_t fei;
184 ip_address_to_fib_prefix (dst, &prefix);
186 fei = fib_table_lookup (0, &prefix);
188 return (fib_entry_get_resolving_interface (fei));
192 * Find first IP of the interface that would be used to egress towards dst.
193 * Returns 1 if the address is found 0 otherwise.
196 ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst,
197 ip_address_t * result)
200 ip_lookup_main_t *lm;
204 ASSERT (result != 0);
206 ipver = ip_addr_version (dst);
208 lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
209 si = ip_fib_get_egress_iface_for_dst (lcm, dst);
214 /* find the first ip address */
215 addr = ip_interface_get_first_address (lm, si, ipver);
219 ip_address_set (result, addr, ipver);
224 dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
230 dp_table = hash_get (lcm->table_id_by_vni, vni);
234 clib_warning ("vni %d not associated to a vrf!", vni);
235 return VNET_API_ERROR_INVALID_VALUE;
240 dp_table = hash_get (lcm->bd_id_by_vni, vni);
243 clib_warning ("vni %d not associated to a bridge domain!", vni);
244 return VNET_API_ERROR_INVALID_VALUE;
248 /* enable/disable data-plane interface */
252 lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table[0]);
254 lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0]);
259 lisp_gpe_tenant_l2_iface_unlock (vni);
261 lisp_gpe_tenant_l3_iface_unlock (vni);
268 dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
270 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
273 memset (a, 0, sizeof (*a));
275 feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
279 fe = pool_elt_at_index (lcm->fwd_entry_pool, feip[0]);
281 /* delete dp fwd entry */
284 a->locator_pairs = fe->locator_pairs;
285 a->vni = gid_address_vni (&fe->reid);
286 gid_address_copy (&a->rmt_eid, &fe->reid);
288 gid_address_copy (&a->lcl_eid, &fe->leid);
290 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
292 /* delete entry in fwd table */
293 hash_unset (lcm->fwd_entry_by_mapping_index, dst_map_index);
294 vec_free (fe->locator_pairs);
295 pool_put (lcm->fwd_entry_pool, fe);
299 * Finds first remote locator with best (lowest) priority that has a local
300 * peer locator with an underlying route to it.
304 get_locator_pairs (lisp_cp_main_t * lcm, mapping_t * lcl_map,
305 mapping_t * rmt_map, locator_pair_t ** locator_pairs)
307 u32 i, limitp = 0, li, found = 0, esi;
308 locator_set_t *rmt_ls, *lcl_ls;
309 ip_address_t _lcl_addr, *lcl_addr = &_lcl_addr;
310 locator_t *lp, *rmt = 0;
315 pool_elt_at_index (lcm->locator_set_pool, rmt_map->locator_set_index);
317 pool_elt_at_index (lcm->locator_set_pool, lcl_map->locator_set_index);
319 if (!rmt_ls || vec_len (rmt_ls->locator_indices) == 0)
326 /* find unvisited remote locator with best priority */
327 for (i = 0; i < vec_len (rmt_ls->locator_indices); i++)
329 if (0 != hash_get (checked, i))
332 li = vec_elt (rmt_ls->locator_indices, i);
333 lp = pool_elt_at_index (lcm->locator_pool, li);
335 /* we don't support non-IP locators for now */
336 if (gid_address_type (&lp->address) != GID_ADDR_IP_PREFIX)
339 if ((found && lp->priority == limitp)
340 || (!found && lp->priority >= limitp))
344 /* don't search for locators with lower priority and don't
345 * check this locator again*/
346 limitp = lp->priority;
347 hash_set (checked, i, 1);
351 /* check if a local locator with a route to remote locator exists */
354 /* find egress sw_if_index for rmt locator */
356 ip_fib_get_egress_iface_for_dst (lcm,
357 &gid_address_ip (&rmt->address));
358 if ((u32) ~ 0 == esi)
361 for (i = 0; i < vec_len (lcl_ls->locator_indices); i++)
363 li = vec_elt (lcl_ls->locator_indices, i);
364 locator_t *sl = pool_elt_at_index (lcm->locator_pool, li);
366 /* found local locator with the needed sw_if_index */
367 if (sl->sw_if_index == esi)
369 /* and it has an address */
370 if (0 == ip_interface_get_first_ip_address (lcm,
372 gid_address_ip_version
377 memset (&pair, 0, sizeof (pair));
378 ip_address_copy (&pair.rmt_loc,
379 &gid_address_ip (&rmt->address));
380 ip_address_copy (&pair.lcl_loc, lcl_addr);
381 pair.weight = rmt->weight;
382 pair.priority = rmt->priority;
383 vec_add1 (locator_pairs[0], pair);
397 gid_address_sd_to_flat (gid_address_t * dst, gid_address_t * src,
400 ASSERT (GID_ADDR_SRC_DST == gid_address_type (src));
404 switch (fid_addr_type (fid))
406 case FID_ADDR_IP_PREF:
407 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
408 gid_address_ippref (dst) = fid_addr_ippref (fid);
411 gid_address_type (dst) = GID_ADDR_MAC;
412 mac_copy (gid_address_mac (dst), fid_addr_mac (fid));
415 clib_warning ("Unsupported fid type %d!", fid_addr_type (fid));
421 vnet_lisp_map_register_state_get (void)
423 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
424 return lcm->map_registering;
428 vnet_lisp_rloc_probe_state_get (void)
430 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
431 return lcm->rloc_probing;
435 dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
437 vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
438 mapping_t *src_map, *dst_map;
440 uword *feip = 0, *dpid;
442 u8 type, is_src_dst = 0;
444 memset (a, 0, sizeof (*a));
446 /* remove entry if it already exists */
447 feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
449 dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
452 src_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
454 src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
455 dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
457 /* insert data plane forwarding entry */
460 if (MR_MODE_SRC_DST == lcm->map_request_mode)
462 if (GID_ADDR_SRC_DST == gid_address_type (&dst_map->eid))
464 gid_address_sd_to_flat (&a->rmt_eid, &dst_map->eid,
465 &gid_address_sd_dst (&dst_map->eid));
466 gid_address_sd_to_flat (&a->lcl_eid, &dst_map->eid,
467 &gid_address_sd_src (&dst_map->eid));
471 gid_address_copy (&a->rmt_eid, &dst_map->eid);
472 gid_address_copy (&a->lcl_eid, &src_map->eid);
477 gid_address_copy (&a->rmt_eid, &dst_map->eid);
479 a->vni = gid_address_vni (&a->rmt_eid);
481 /* get vrf or bd_index associated to vni */
482 type = gid_address_type (&a->rmt_eid);
483 if (GID_ADDR_IP_PREFIX == type)
485 dpid = hash_get (lcm->table_id_by_vni, a->vni);
488 clib_warning ("vni %d not associated to a vrf!", a->vni);
491 a->table_id = dpid[0];
493 else if (GID_ADDR_MAC == type)
495 dpid = hash_get (lcm->bd_id_by_vni, a->vni);
498 clib_warning ("vni %d not associated to a bridge domain !", a->vni);
504 /* find best locator pair that 1) verifies LISP policy 2) are connected */
505 if (0 == get_locator_pairs (lcm, src_map, dst_map, &a->locator_pairs))
509 a->action = dst_map->action;
513 u8 ipver = ip_prefix_version (&gid_address_ippref (&a->rmt_eid));
514 a->decap_next_index = (ipver == IP4) ?
515 LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
517 vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
519 /* add tunnel to fwd entry table XXX check return value from DP insertion */
520 pool_get (lcm->fwd_entry_pool, fe);
521 fe->locator_pairs = a->locator_pairs;
522 gid_address_copy (&fe->reid, &a->rmt_eid);
525 gid_address_copy (&fe->leid, &a->lcl_eid);
527 gid_address_copy (&fe->leid, &src_map->eid);
529 fe->is_src_dst = is_src_dst;
530 hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
531 fe - lcm->fwd_entry_pool);
538 } fwd_entry_mt_arg_t;
541 dp_add_fwd_entry_thread_fn (void *arg)
543 fwd_entry_mt_arg_t *a = arg;
544 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
545 dp_add_fwd_entry (lcm, a->si, a->di);
550 dp_add_fwd_entry_from_mt (u32 si, u32 di)
552 fwd_entry_mt_arg_t a;
554 memset (&a, 0, sizeof (a));
558 vl_api_rpc_call_main_thread (dp_add_fwd_entry_thread_fn,
559 (u8 *) & a, sizeof (a));
564 * Returns vector of adjacencies.
566 * The caller must free the vector returned by this function.
568 * @param vni virtual network identifier
569 * @return vector of adjacencies
572 vnet_lisp_adjacencies_get_by_vni (u32 vni)
574 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
576 lisp_adjacency_t *adjs = 0, adj;
579 pool_foreach(fwd, lcm->fwd_entry_pool,
581 if (gid_address_vni (&fwd->reid) != vni)
584 gid_address_copy (&adj.reid, &fwd->reid);
585 gid_address_copy (&adj.leid, &fwd->leid);
586 vec_add1 (adjs, adj);
593 static clib_error_t *
594 lisp_show_adjacencies_command_fn (vlib_main_t * vm,
595 unformat_input_t * input,
596 vlib_cli_command_t * cmd)
598 lisp_adjacency_t *adjs, *adj;
599 vlib_cli_output (vm, "%s %40s\n", "leid", "reid");
600 unformat_input_t _line_input, *line_input = &_line_input;
603 /* Get a line of input. */
604 if (!unformat_user (input, unformat_line_input, line_input))
607 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
609 if (unformat (line_input, "vni %d", &vni))
613 vlib_cli_output (vm, "parse error: '%U'",
614 format_unformat_error, line_input);
621 vlib_cli_output (vm, "error: no vni specified!");
625 adjs = vnet_lisp_adjacencies_get_by_vni (vni);
627 vec_foreach (adj, adjs)
629 vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid,
630 format_gid_address, &adj->reid);
638 VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = {
639 .path = "show lisp adjacencies",
640 .short_help = "show lisp adjacencies",
641 .function = lisp_show_adjacencies_command_fn,
646 get_map_server (ip_address_t * a)
648 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
651 vec_foreach (m, lcm->map_servers)
653 if (!ip_address_cmp (&m->address, a))
662 get_map_resolver (ip_address_t * a)
664 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
667 vec_foreach (m, lcm->map_resolvers)
669 if (!ip_address_cmp (&m->address, a))
678 vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add)
681 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
682 lisp_msmr_t _ms, *ms = &_ms;
684 if (vnet_lisp_enable_disable_status () == 0)
686 clib_warning ("LISP is disabled!");
687 return VNET_API_ERROR_LISP_DISABLED;
692 if (get_map_server (addr))
694 clib_warning ("map-server %U already exists!", format_ip_address,
699 memset (ms, 0, sizeof (*ms));
700 ip_address_copy (&ms->address, addr);
701 vec_add1 (lcm->map_servers, ms[0]);
705 for (i = 0; i < vec_len (lcm->map_servers); i++)
707 ms = vec_elt_at_index (lcm->map_servers, i);
708 if (!ip_address_cmp (&ms->address, addr))
710 vec_del1 (lcm->map_servers, i);
719 static clib_error_t *
720 lisp_add_del_map_server_command_fn (vlib_main_t * vm,
721 unformat_input_t * input,
722 vlib_cli_command_t * cmd)
725 u8 is_add = 1, ip_set = 0;
727 unformat_input_t _line_input, *line_input = &_line_input;
729 /* Get a line of input. */
730 if (!unformat_user (input, unformat_line_input, line_input))
733 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
735 if (unformat (line_input, "add"))
737 else if (unformat (line_input, "del"))
739 else if (unformat (line_input, "%U", unformat_ip_address, &ip))
743 vlib_cli_output (vm, "parse error: '%U'",
744 format_unformat_error, line_input);
751 vlib_cli_output (vm, "map-server ip address not set!");
755 rv = vnet_lisp_add_del_map_server (&ip, is_add);
757 vlib_cli_output (vm, "failed to %s map-server!",
758 is_add ? "add" : "delete");
764 VLIB_CLI_COMMAND (lisp_add_del_map_server_command) = {
765 .path = "lisp map-server",
766 .short_help = "lisp map-server add|del <ip>",
767 .function = lisp_add_del_map_server_command_fn,
772 * Add/remove mapping to/from map-cache. Overwriting not allowed.
775 vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a,
776 u32 * map_index_result)
778 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
779 u32 mi, *map_indexp, map_index, i;
780 mapping_t *m, *old_map;
783 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
784 old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
787 /* TODO check if overwriting and take appropriate actions */
788 if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid, &a->eid))
790 clib_warning ("eid %U found in the eid-table", format_gid_address,
792 return VNET_API_ERROR_VALUE_EXIST;
795 pool_get (lcm->mapping_pool, m);
796 gid_address_copy (&m->eid, &a->eid);
797 m->locator_set_index = a->locator_set_index;
799 m->action = a->action;
801 m->is_static = a->is_static;
802 m->key = vec_dup (a->key);
803 m->key_id = a->key_id;
805 map_index = m - lcm->mapping_pool;
806 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
809 if (pool_is_free_index (lcm->locator_set_pool, a->locator_set_index))
811 clib_warning ("Locator set with index %d doesn't exist",
812 a->locator_set_index);
813 return VNET_API_ERROR_INVALID_VALUE;
816 /* add eid to list of eids supported by locator-set */
817 vec_validate (lcm->locator_set_to_eids, a->locator_set_index);
818 eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
819 a->locator_set_index);
820 vec_add1 (eid_indexes[0], map_index);
825 vec_add1 (lcm->local_mappings_indexes, map_index);
827 map_index_result[0] = map_index;
831 if (mi == GID_LOOKUP_MISS)
833 clib_warning ("eid %U not found in the eid-table",
834 format_gid_address, &a->eid);
835 return VNET_API_ERROR_INVALID_VALUE;
838 /* clear locator-set to eids binding */
839 eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
840 a->locator_set_index);
841 for (i = 0; i < vec_len (eid_indexes[0]); i++)
843 map_indexp = vec_elt_at_index (eid_indexes[0], i);
844 if (map_indexp[0] == mi)
847 vec_del1 (eid_indexes[0], i);
849 /* remove local mark if needed */
850 m = pool_elt_at_index (lcm->mapping_pool, mi);
854 for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
856 lm_indexp = vec_elt_at_index (lcm->local_mappings_indexes, k);
857 if (lm_indexp[0] == mi)
860 vec_del1 (lcm->local_mappings_indexes, k);
863 /* remove mapping from dictionary */
864 gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
865 gid_address_free (&m->eid);
866 pool_put_index (lcm->mapping_pool, mi);
873 * Add/update/delete mapping to/in/from map-cache.
876 vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
877 u32 * map_index_result)
883 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
885 if (vnet_lisp_enable_disable_status () == 0)
887 clib_warning ("LISP is disabled!");
888 return VNET_API_ERROR_LISP_DISABLED;
891 vni = gid_address_vni (&a->eid);
892 type = gid_address_type (&a->eid);
893 if (GID_ADDR_IP_PREFIX == type)
894 dp_table = hash_get (lcm->table_id_by_vni, vni);
895 else if (GID_ADDR_MAC == type)
896 dp_table = hash_get (lcm->bd_id_by_vni, vni);
900 clib_warning ("vni %d not associated to a %s!", vni,
901 GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
902 return VNET_API_ERROR_INVALID_VALUE;
905 /* store/remove mapping from map-cache */
906 return vnet_lisp_map_cache_add_del (a, map_index_result);
909 static clib_error_t *
910 lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
911 vlib_cli_command_t * cmd)
913 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
914 unformat_input_t _line_input, *line_input = &_line_input;
917 gid_address_t *eids = 0;
918 clib_error_t *error = 0;
919 u8 *locator_set_name = 0;
920 u32 locator_set_index = 0, map_index = 0;
922 vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
928 memset (&eid, 0, sizeof (eid));
929 memset (a, 0, sizeof (*a));
931 /* Get a line of input. */
932 if (!unformat_user (input, unformat_line_input, line_input))
935 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
937 if (unformat (line_input, "add"))
939 else if (unformat (line_input, "del"))
941 else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
943 else if (unformat (line_input, "vni %d", &vni))
944 gid_address_vni (&eid) = vni;
945 else if (unformat (line_input, "secret-key %_%v%_", &key))
947 else if (unformat (line_input, "key-id %U", unformat_hmac_key_id,
950 else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
952 p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
955 error = clib_error_return (0, "locator-set %s doesn't exist",
959 locator_set_index = p[0];
963 error = unformat_parse_error (line_input);
967 /* XXX treat batch configuration */
969 if (GID_ADDR_SRC_DST == gid_address_type (&eid))
972 clib_error_return (0, "src/dst is not supported for local EIDs!");
976 if (key && (0 == key_id))
978 vlib_cli_output (vm, "invalid key_id!");
982 gid_address_copy (&a->eid, &eid);
984 a->locator_set_index = locator_set_index;
989 rv = vnet_lisp_add_del_local_mapping (a, &map_index);
992 error = clib_error_return (0, "failed to %s local mapping!",
993 is_add ? "add" : "delete");
997 if (locator_set_name)
998 vec_free (locator_set_name);
999 gid_address_free (&a->eid);
1005 VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
1006 .path = "lisp eid-table",
1007 .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
1008 "locator-set <locator-set> [key <secret-key> key-id sha1|sha256 ]",
1009 .function = lisp_add_del_local_eid_command_fn,
1014 vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
1016 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1017 uword *dp_idp, *vnip, **dp_table_by_vni, **vni_by_dp_table;
1019 if (vnet_lisp_enable_disable_status () == 0)
1021 clib_warning ("LISP is disabled!");
1025 dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
1026 vni_by_dp_table = is_l2 ? &lcm->vni_by_bd_id : &lcm->vni_by_table_id;
1028 if (!is_l2 && (vni == 0 || dp_id == 0))
1030 clib_warning ("can't add/del default vni-vrf mapping!");
1034 dp_idp = hash_get (dp_table_by_vni[0], vni);
1035 vnip = hash_get (vni_by_dp_table[0], dp_id);
1041 clib_warning ("vni %d or vrf %d already used in vrf/vni "
1042 "mapping!", vni, dp_id);
1045 hash_set (dp_table_by_vni[0], vni, dp_id);
1046 hash_set (vni_by_dp_table[0], dp_id, vni);
1048 /* create dp iface */
1049 dp_add_del_iface (lcm, vni, is_l2, 1);
1053 if (!dp_idp || !vnip)
1055 clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
1056 "mapping!", vni, dp_id);
1059 hash_unset (dp_table_by_vni[0], vni);
1060 hash_unset (vni_by_dp_table[0], dp_id);
1062 /* remove dp iface */
1063 dp_add_del_iface (lcm, vni, is_l2, 0);
1069 static clib_error_t *
1070 lisp_eid_table_map_command_fn (vlib_main_t * vm,
1071 unformat_input_t * input,
1072 vlib_cli_command_t * cmd)
1074 u8 is_add = 1, is_l2 = 0;
1075 u32 vni = 0, dp_id = 0;
1076 unformat_input_t _line_input, *line_input = &_line_input;
1078 /* Get a line of input. */
1079 if (!unformat_user (input, unformat_line_input, line_input))
1082 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1084 if (unformat (line_input, "del"))
1086 else if (unformat (line_input, "vni %d", &vni))
1088 else if (unformat (line_input, "vrf %d", &dp_id))
1090 else if (unformat (line_input, "bd %d", &dp_id))
1094 return unformat_parse_error (line_input);
1097 vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
1102 VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
1103 .path = "lisp eid-table map",
1104 .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
1105 .function = lisp_eid_table_map_command_fn,
1109 /* return 0 if the two locator sets are identical 1 otherwise */
1111 compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes,
1112 locator_t * new_locators)
1115 locator_t *old_loc, *new_loc;
1117 if (vec_len (old_ls_indexes) != vec_len (new_locators))
1120 for (i = 0; i < vec_len (new_locators); i++)
1122 old_li = vec_elt (old_ls_indexes, i);
1123 old_loc = pool_elt_at_index (lcm->locator_pool, old_li);
1125 new_loc = vec_elt_at_index (new_locators, i);
1127 if (locator_cmp (old_loc, new_loc))
1137 gid_address_t *eids_to_be_deleted;
1138 } remove_mapping_args_t;
1141 * Callback invoked when a sub-prefix is found
1144 remove_mapping_if_needed (u32 mi, void *arg)
1147 remove_mapping_args_t *a = arg;
1148 lisp_cp_main_t *lcm = a->lcm;
1152 m = pool_elt_at_index (lcm->mapping_pool, mi);
1156 ls = pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
1160 if (0 != vec_len (ls->locator_indices))
1165 if (0 == vec_len (ls->locator_indices))
1170 vec_add1 (a->eids_to_be_deleted, m->eid);
1174 * This function searches map cache and looks for IP prefixes that are subset
1175 * of the provided one. If such prefix is found depending on 'is_negative'
1178 * 1) if is_negative is true and found prefix points to positive mapping,
1179 * then the mapping is removed
1180 * 2) if is_negative is false and found prefix points to negative mapping,
1181 * then the mapping is removed
1184 remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid,
1188 remove_mapping_args_t a;
1189 memset (&a, 0, sizeof (a));
1191 /* do this only in src/dst mode ... */
1192 if (MR_MODE_SRC_DST != lcm->map_request_mode)
1195 /* ... and only for IP prefix */
1196 if (GID_ADDR_SRC_DST != gid_address_type (eid)
1197 || (FID_ADDR_IP_PREF != gid_address_sd_dst_type (eid)))
1200 a.is_negative = is_negative;
1203 gid_dict_foreach_subprefix (&lcm->mapping_index_by_gid, eid,
1204 remove_mapping_if_needed, &a);
1206 vec_foreach (e, a.eids_to_be_deleted)
1208 lisp_add_del_adjacency (lcm, 0, e, 0 /* is_add */ );
1209 vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0);
1212 vec_free (a.eids_to_be_deleted);
1216 mapping_delete_timer (lisp_cp_main_t * lcm, u32 mi)
1218 timing_wheel_delete (&lcm->wheel, mi);
1222 * Adds/removes/updates mapping. Does not program forwarding.
1224 * @param eid end-host identifier
1225 * @param rlocs vector of remote locators
1226 * @param action action for negative map-reply
1227 * @param is_add add mapping if non-zero, delete otherwise
1228 * @param res_map_index the map-index that was created/updated/removed. It is
1229 * set to ~0 if no action is taken.
1230 * @param is_static used for distinguishing between statically learned
1231 remote mappings and mappings obtained from MR
1232 * @return return code
1235 vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
1236 u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
1237 u32 * res_map_index)
1239 vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
1240 vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
1241 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1242 u32 mi, ls_index = 0, dst_map_index;
1245 if (vnet_lisp_enable_disable_status () == 0)
1247 clib_warning ("LISP is disabled!");
1248 return VNET_API_ERROR_LISP_DISABLED;
1252 res_map_index[0] = ~0;
1254 memset (m_args, 0, sizeof (m_args[0]));
1255 memset (ls_args, 0, sizeof (ls_args[0]));
1257 ls_args->locators = rlocs;
1259 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
1260 old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
1264 /* overwrite: if mapping already exists, decide if locators should be
1265 * updated and be done */
1266 if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
1268 if (!is_static && (old_map->is_static || old_map->local))
1270 /* do not overwrite local or static remote mappings */
1271 clib_warning ("mapping %U rejected due to collision with local "
1272 "or static remote mapping!", format_gid_address,
1277 locator_set_t *old_ls;
1279 /* update mapping attributes */
1280 old_map->action = action;
1281 old_map->authoritative = authoritative;
1284 old_ls = pool_elt_at_index (lcm->locator_set_pool,
1285 old_map->locator_set_index);
1286 if (compare_locators (lcm, old_ls->locator_indices,
1289 /* set locator-set index to overwrite */
1290 ls_args->is_add = 1;
1291 ls_args->index = old_map->locator_set_index;
1292 vnet_lisp_add_del_locator_set (ls_args, 0);
1294 res_map_index[0] = mi;
1300 remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators);
1302 ls_args->is_add = 1;
1303 ls_args->index = ~0;
1305 vnet_lisp_add_del_locator_set (ls_args, &ls_index);
1308 gid_address_copy (&m_args->eid, eid);
1310 m_args->action = action;
1311 m_args->locator_set_index = ls_index;
1312 m_args->is_static = is_static;
1314 vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
1317 res_map_index[0] = dst_map_index;
1322 if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
1324 clib_warning ("cannot delete mapping for eid %U",
1325 format_gid_address, eid);
1330 gid_address_copy (&m_args->eid, eid);
1331 m_args->locator_set_index = old_map->locator_set_index;
1333 /* delete mapping associated from map-cache */
1334 vnet_lisp_map_cache_add_del (m_args, 0);
1336 ls_args->is_add = 0;
1337 ls_args->index = old_map->locator_set_index;
1338 /* delete locator set */
1339 vnet_lisp_add_del_locator_set (ls_args, 0);
1341 /* delete timer associated to the mapping if any */
1342 if (old_map->timer_set)
1343 mapping_delete_timer (lcm, mi);
1345 /* return old mapping index */
1347 res_map_index[0] = mi;
1355 vnet_lisp_clear_all_remote_adjacencies (void)
1358 u32 mi, *map_indices = 0, *map_indexp;
1359 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1360 vnet_lisp_add_del_mapping_args_t _dm_args, *dm_args = &_dm_args;
1361 vnet_lisp_add_del_locator_set_args_t _ls, *ls = &_ls;
1364 pool_foreach_index (mi, lcm->mapping_pool,
1366 vec_add1 (map_indices, mi);
1370 vec_foreach (map_indexp, map_indices)
1372 mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
1375 dp_del_fwd_entry (lcm, 0, map_indexp[0]);
1377 dm_args->is_add = 0;
1378 gid_address_copy (&dm_args->eid, &map->eid);
1379 dm_args->locator_set_index = map->locator_set_index;
1381 /* delete mapping associated to fwd entry */
1382 vnet_lisp_map_cache_add_del (dm_args, 0);
1386 ls->index = map->locator_set_index;
1387 /* delete locator set */
1388 rv = vnet_lisp_add_del_locator_set (ls, 0);
1396 vec_free (map_indices);
1401 * Adds adjacency or removes forwarding entry associated to remote mapping.
1402 * Note that adjacencies are not stored, they only result in forwarding entries
1406 lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid,
1407 gid_address_t * remote_eid, u8 is_add)
1409 u32 local_mi, remote_mi = ~0;
1411 if (vnet_lisp_enable_disable_status () == 0)
1413 clib_warning ("LISP is disabled!");
1414 return VNET_API_ERROR_LISP_DISABLED;
1417 remote_mi = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid,
1418 remote_eid, local_eid);
1419 if (GID_LOOKUP_MISS == remote_mi)
1421 clib_warning ("Remote eid %U not found. Cannot add adjacency!",
1422 format_gid_address, remote_eid);
1429 /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
1432 /* check if source eid has an associated mapping. If pitr mode is on,
1433 * just use the pitr's mapping */
1434 local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
1435 gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
1438 if (GID_LOOKUP_MISS == local_mi)
1440 clib_warning ("Local eid %U not found. Cannot add adjacency!",
1441 format_gid_address, local_eid);
1446 /* update forwarding */
1447 dp_add_fwd_entry (lcm, local_mi, remote_mi);
1450 dp_del_fwd_entry (lcm, 0, remote_mi);
1456 vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
1458 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1459 return lisp_add_del_adjacency (lcm, &a->leid, &a->reid, a->is_add);
1463 * Handler for add/del remote mapping CLI.
1465 * @param vm vlib context
1466 * @param input input from user
1468 * @return pointer to clib error structure
1470 static clib_error_t *
1471 lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
1472 unformat_input_t * input,
1473 vlib_cli_command_t * cmd)
1475 clib_error_t *error = 0;
1476 unformat_input_t _line_input, *line_input = &_line_input;
1477 u8 is_add = 1, del_all = 0;
1478 locator_t rloc, *rlocs = 0, *curr_rloc = 0;
1481 u32 vni, action = ~0, p, w;
1484 /* Get a line of input. */
1485 if (!unformat_user (input, unformat_line_input, line_input))
1488 memset (&eid, 0, sizeof (eid));
1489 memset (&rloc, 0, sizeof (rloc));
1491 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1493 if (unformat (line_input, "del-all"))
1495 else if (unformat (line_input, "del"))
1497 else if (unformat (line_input, "add"))
1499 else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1501 else if (unformat (line_input, "vni %u", &vni))
1503 gid_address_vni (&eid) = vni;
1505 else if (unformat (line_input, "p %d w %d", &p, &w))
1510 ("No RLOC configured for setting priority/weight!");
1513 curr_rloc->priority = p;
1514 curr_rloc->weight = w;
1516 else if (unformat (line_input, "rloc %U", unformat_ip_address,
1517 &gid_address_ip (&rloc.address)))
1519 /* since rloc is stored in ip prefix we need to set prefix length */
1520 ip_prefix_t *pref = &gid_address_ippref (&rloc.address);
1522 u8 version = gid_address_ip_version (&rloc.address);
1523 ip_prefix_len (pref) = ip_address_max_len (version);
1525 vec_add1 (rlocs, rloc);
1526 curr_rloc = &rlocs[vec_len (rlocs) - 1];
1528 else if (unformat (line_input, "action %U",
1529 unformat_negative_mapping_action, &action))
1533 clib_warning ("parse error");
1540 clib_warning ("missing eid!");
1546 if (is_add && (~0 == action) && 0 == vec_len (rlocs))
1548 clib_warning ("no action set for negative map-reply!");
1554 vnet_lisp_clear_all_remote_adjacencies ();
1558 /* TODO build src/dst with seid */
1560 /* if it's a delete, clean forwarding */
1563 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1564 rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0);
1571 /* add as static remote mapping, i.e., not authoritative and infinite
1573 rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
1574 1 /* is_static */ , 0);
1577 clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
1581 unformat_free (line_input);
1585 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) =
1587 .path = "lisp remote-mapping",.short_help =
1588 "lisp remote-mapping add|del [del-all] vni <vni> "
1589 "eid <est-eid> [action <no-action|natively-forward|"
1590 "send-map-request|drop>] rloc <dst-locator> p <prio> w <weight> "
1591 "[rloc <dst-locator> ... ]",.function =
1592 lisp_add_del_remote_mapping_command_fn,};
1595 * Handler for add/del adjacency CLI.
1597 static clib_error_t *
1598 lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input,
1599 vlib_cli_command_t * cmd)
1601 clib_error_t *error = 0;
1602 unformat_input_t _line_input, *line_input = &_line_input;
1603 vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
1605 ip_prefix_t *reid_ippref, *leid_ippref;
1606 gid_address_t leid, reid;
1607 u8 *dmac = gid_address_mac (&reid);
1608 u8 *smac = gid_address_mac (&leid);
1609 u8 reid_set = 0, leid_set = 0;
1613 /* Get a line of input. */
1614 if (!unformat_user (input, unformat_line_input, line_input))
1617 memset (&reid, 0, sizeof (reid));
1618 memset (&leid, 0, sizeof (leid));
1620 leid_ippref = &gid_address_ippref (&leid);
1621 reid_ippref = &gid_address_ippref (&reid);
1623 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1625 if (unformat (line_input, "del"))
1627 else if (unformat (line_input, "add"))
1629 else if (unformat (line_input, "reid %U",
1630 unformat_ip_prefix, reid_ippref))
1632 gid_address_type (&reid) = GID_ADDR_IP_PREFIX;
1635 else if (unformat (line_input, "reid %U", unformat_mac_address, dmac))
1637 gid_address_type (&reid) = GID_ADDR_MAC;
1640 else if (unformat (line_input, "vni %u", &vni))
1642 gid_address_vni (&leid) = vni;
1643 gid_address_vni (&reid) = vni;
1645 else if (unformat (line_input, "leid %U",
1646 unformat_ip_prefix, leid_ippref))
1648 gid_address_type (&leid) = GID_ADDR_IP_PREFIX;
1651 else if (unformat (line_input, "leid %U", unformat_mac_address, smac))
1653 gid_address_type (&leid) = GID_ADDR_MAC;
1658 clib_warning ("parse error");
1663 if (!reid_set || !leid_set)
1665 clib_warning ("missing remote or local eid!");
1669 if ((gid_address_type (&leid) != gid_address_type (&reid))
1670 || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX
1671 && ip_prefix_version (reid_ippref)
1672 != ip_prefix_version (leid_ippref)))
1674 clib_warning ("remote and local EIDs are of different types!");
1678 memset (a, 0, sizeof (a[0]));
1679 gid_address_copy (&a->leid, &leid);
1680 gid_address_copy (&a->reid, &reid);
1683 rv = vnet_lisp_add_del_adjacency (a);
1686 clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete");
1689 unformat_free (line_input);
1694 VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
1695 .path = "lisp adjacency",
1696 .short_help = "lisp adjacency add|del vni <vni> reid <remote-eid> "
1698 .function = lisp_add_del_adjacency_command_fn,
1703 vnet_lisp_set_map_request_mode (u8 mode)
1705 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1707 if (vnet_lisp_enable_disable_status () == 0)
1709 clib_warning ("LISP is disabled!");
1710 return VNET_API_ERROR_LISP_DISABLED;
1713 if (mode >= _MR_MODE_MAX)
1715 clib_warning ("Invalid LISP map request mode %d!", mode);
1716 return VNET_API_ERROR_INVALID_ARGUMENT;
1719 lcm->map_request_mode = mode;
1723 static clib_error_t *
1724 lisp_map_request_mode_command_fn (vlib_main_t * vm,
1725 unformat_input_t * input,
1726 vlib_cli_command_t * cmd)
1728 unformat_input_t _i, *i = &_i;
1729 map_request_mode_t mr_mode = _MR_MODE_MAX;
1731 /* Get a line of input. */
1732 if (!unformat_user (input, unformat_line_input, i))
1735 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1737 if (unformat (i, "dst-only"))
1738 mr_mode = MR_MODE_DST_ONLY;
1739 else if (unformat (i, "src-dst"))
1740 mr_mode = MR_MODE_SRC_DST;
1743 clib_warning ("parse error '%U'", format_unformat_error, i);
1748 if (_MR_MODE_MAX == mr_mode)
1750 clib_warning ("No LISP map request mode entered!");
1754 vnet_lisp_set_map_request_mode (mr_mode);
1760 VLIB_CLI_COMMAND (lisp_map_request_mode_command) = {
1761 .path = "lisp map-request mode",
1762 .short_help = "lisp map-request mode dst-only|src-dst",
1763 .function = lisp_map_request_mode_command_fn,
1768 format_lisp_map_request_mode (u8 * s, va_list * args)
1770 u32 mode = va_arg (*args, u32);
1775 return format (0, "dst-only");
1777 return format (0, "src-dst");
1782 static clib_error_t *
1783 lisp_show_map_request_mode_command_fn (vlib_main_t * vm,
1784 unformat_input_t * input,
1785 vlib_cli_command_t * cmd)
1787 vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode,
1788 vnet_lisp_get_map_request_mode ());
1793 VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = {
1794 .path = "show lisp map-request mode",
1795 .short_help = "show lisp map-request mode",
1796 .function = lisp_show_map_request_mode_command_fn,
1800 static clib_error_t *
1801 lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
1802 unformat_input_t * input,
1803 vlib_cli_command_t * cmd)
1806 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1808 vec_foreach (mr, lcm->map_resolvers)
1810 vlib_cli_output (vm, "%U", format_ip_address, &mr->address);
1816 VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
1817 .path = "show lisp map-resolvers",
1818 .short_help = "show lisp map-resolvers",
1819 .function = lisp_show_map_resolvers_command_fn,
1824 vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
1826 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1827 u32 locator_set_index = ~0;
1831 if (vnet_lisp_enable_disable_status () == 0)
1833 clib_warning ("LISP is disabled!");
1834 return VNET_API_ERROR_LISP_DISABLED;
1837 p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1840 clib_warning ("locator-set %v doesn't exist", locator_set_name);
1843 locator_set_index = p[0];
1847 pool_get (lcm->mapping_pool, m);
1848 m->locator_set_index = locator_set_index;
1850 lcm->pitr_map_index = m - lcm->mapping_pool;
1852 /* enable pitr mode */
1857 /* remove pitr mapping */
1858 pool_put_index (lcm->mapping_pool, lcm->pitr_map_index);
1860 /* disable pitr mode */
1866 static clib_error_t *
1867 lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
1868 unformat_input_t * input,
1869 vlib_cli_command_t * cmd)
1871 u8 locator_name_set = 0;
1872 u8 *locator_set_name = 0;
1874 unformat_input_t _line_input, *line_input = &_line_input;
1875 clib_error_t *error = 0;
1878 /* Get a line of input. */
1879 if (!unformat_user (input, unformat_line_input, line_input))
1882 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1884 if (unformat (line_input, "ls %_%v%_", &locator_set_name))
1885 locator_name_set = 1;
1886 else if (unformat (line_input, "disable"))
1889 return clib_error_return (0, "parse error");
1892 if (!locator_name_set)
1894 clib_warning ("No locator set specified!");
1897 rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
1900 error = clib_error_return (0, "failed to %s pitr!",
1901 is_add ? "add" : "delete");
1905 if (locator_set_name)
1906 vec_free (locator_set_name);
1911 VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
1912 .path = "lisp pitr",
1913 .short_help = "lisp pitr [disable] ls <locator-set-name>",
1914 .function = lisp_pitr_set_locator_set_command_fn,
1918 static clib_error_t *
1919 lisp_show_pitr_command_fn (vlib_main_t * vm,
1920 unformat_input_t * input, vlib_cli_command_t * cmd)
1922 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
1927 vlib_cli_output (vm, "%=20s%=16s",
1928 "pitr", lcm->lisp_pitr ? "locator-set" : "");
1930 if (!lcm->lisp_pitr)
1932 vlib_cli_output (vm, "%=20s", "disable");
1936 if (~0 == lcm->pitr_map_index)
1938 tmp_str = format (0, "N/A");
1942 m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
1943 if (~0 != m->locator_set_index)
1946 pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
1947 tmp_str = format (0, "%s", ls->name);
1951 tmp_str = format (0, "N/A");
1954 vec_add1 (tmp_str, 0);
1956 vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
1964 VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
1965 .path = "show lisp pitr",
1966 .short_help = "Show pitr",
1967 .function = lisp_show_pitr_command_fn,
1972 format_eid_entry (u8 * s, va_list * args)
1974 vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
1975 lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *);
1976 mapping_t *mapit = va_arg (*args, mapping_t *);
1977 locator_set_t *ls = va_arg (*args, locator_set_t *);
1978 gid_address_t *gid = &mapit->eid;
1979 u32 ttl = mapit->ttl;
1980 u8 aut = mapit->authoritative;
1985 u8 *type = ls->local ? format (0, "local(%s)", ls->name)
1986 : format (0, "remote");
1988 if (vec_len (ls->locator_indices) == 0)
1990 s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
1995 vec_foreach (loc_index, ls->locator_indices)
1997 locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
1999 loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
2002 loc = format (0, "%U", format_ip_address,
2003 &gid_address_ip (&l->address));
2007 s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
2008 gid, type, loc, ttl, aut);
2012 s = format (s, "%55s%v\n", "", loc);
2018 static clib_error_t *
2019 lisp_show_eid_table_command_fn (vlib_main_t * vm,
2020 unformat_input_t * input,
2021 vlib_cli_command_t * cmd)
2023 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2025 unformat_input_t _line_input, *line_input = &_line_input;
2031 memset (&eid, 0, sizeof (eid));
2033 /* Get a line of input. */
2034 if (!unformat_user (input, unformat_line_input, line_input))
2037 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2039 if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
2041 else if (unformat (line_input, "local"))
2043 else if (unformat (line_input, "remote"))
2046 return clib_error_return (0, "parse error: '%U'",
2047 format_unformat_error, line_input);
2050 vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
2051 "EID", "type", "locators", "ttl", "autoritative");
2056 pool_foreach (mapit, lcm->mapping_pool,
2058 locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
2059 mapit->locator_set_index);
2060 if (filter && !((1 == filter && ls->local) ||
2061 (2 == filter && !ls->local)))
2065 vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
2072 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
2073 if ((u32) ~ 0 == mi)
2076 mapit = pool_elt_at_index (lcm->mapping_pool, mi);
2077 locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
2078 mapit->locator_set_index);
2080 if (filter && !((1 == filter && ls->local) ||
2081 (2 == filter && !ls->local)))
2086 vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
2094 VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = {
2095 .path = "show lisp eid-table",
2096 .short_help = "Shows EID table",
2097 .function = lisp_show_eid_table_command_fn,
2101 /* cleans locator to locator-set data and removes locators not part of
2102 * any locator-set */
2104 clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi)
2106 u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0;
2107 locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, lsi);
2108 for (i = 0; i < vec_len (ls->locator_indices); i++)
2110 loc_indexp = vec_elt_at_index (ls->locator_indices, i);
2111 ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
2113 for (j = 0; j < vec_len (ls_indexes[0]); j++)
2115 ls_indexp = vec_elt_at_index (ls_indexes[0], j);
2116 if (ls_indexp[0] == lsi)
2120 /* delete index for removed locator-set */
2121 vec_del1 (ls_indexes[0], j);
2123 /* delete locator if it's part of no locator-set */
2124 if (vec_len (ls_indexes[0]) == 0)
2126 pool_put_index (lcm->locator_pool, loc_indexp[0]);
2127 vec_add1 (to_be_deleted, i);
2133 for (i = 0; i < vec_len (to_be_deleted); i++)
2135 loc_indexp = vec_elt_at_index (to_be_deleted, i);
2136 vec_del1 (ls->locator_indices, loc_indexp[0]);
2138 vec_free (to_be_deleted);
2142 static inline uword *
2143 get_locator_set_index (vnet_lisp_add_del_locator_set_args_t * a, uword * p)
2145 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2150 /* find locator-set */
2153 p = hash_get_mem (lcm->locator_set_index_by_name, a->name);
2164 is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls,
2170 ASSERT (ls != NULL);
2171 ASSERT (loc != NULL);
2173 vec_foreach (locit, ls->locator_indices)
2175 itloc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2176 if ((ls->local && itloc->sw_if_index == loc->sw_if_index) ||
2177 (!ls->local && !gid_address_cmp (&itloc->address, &loc->address)))
2179 clib_warning ("Duplicate locator");
2180 return VNET_API_ERROR_VALUE_EXIST;
2188 remove_locator_from_locator_set (locator_set_t * ls, u32 * locit,
2189 u32 ls_index, u32 loc_id)
2191 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2192 u32 **ls_indexes = NULL;
2194 ASSERT (ls != NULL);
2195 ASSERT (locit != NULL);
2197 ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, locit[0]);
2198 pool_put_index (lcm->locator_pool, locit[0]);
2199 vec_del1 (ls->locator_indices, loc_id);
2200 vec_del1 (ls_indexes[0], ls_index);
2204 vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a,
2205 locator_set_t * ls, u32 * ls_result)
2207 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2208 locator_t *loc = NULL, *itloc = NULL;
2209 uword _p = (u32) ~ 0, *p = &_p;
2210 u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL;
2216 if (vnet_lisp_enable_disable_status () == 0)
2218 clib_warning ("LISP is disabled!");
2219 return VNET_API_ERROR_LISP_DISABLED;
2222 p = get_locator_set_index (a, p);
2225 clib_warning ("locator-set %v doesn't exist", a->name);
2226 return VNET_API_ERROR_INVALID_ARGUMENT;
2231 ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2234 clib_warning ("locator-set %d to be overwritten doesn't exist!",
2236 return VNET_API_ERROR_INVALID_ARGUMENT;
2243 ls_result[0] = p[0];
2245 /* allocate locators */
2246 vec_foreach (itloc, a->locators)
2248 ret = is_locator_in_locator_set (lcm, ls, itloc);
2254 pool_get (lcm->locator_pool, loc);
2256 loc_index = loc - lcm->locator_pool;
2258 vec_add1 (ls->locator_indices, loc_index);
2260 vec_validate (lcm->locator_to_locator_sets, loc_index);
2261 ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
2263 vec_add1 (ls_indexes[0], p[0]);
2270 itloc = a->locators;
2272 vec_foreach (locit, ls->locator_indices)
2274 loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2276 if (loc->local && loc->sw_if_index == itloc->sw_if_index)
2278 remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
2280 if (0 == loc->local &&
2281 !gid_address_cmp (&loc->address, &itloc->address))
2283 remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
2294 vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a,
2297 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2299 uword _p = (u32) ~ 0, *p = &_p;
2304 if (vnet_lisp_enable_disable_status () == 0)
2306 clib_warning ("LISP is disabled!");
2307 return VNET_API_ERROR_LISP_DISABLED;
2312 p = get_locator_set_index (a, p);
2315 if (p && p[0] != (u32) ~ 0)
2317 ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2320 clib_warning ("locator-set %d to be overwritten doesn't exist!",
2325 /* clean locator to locator-set vectors and remove locators if
2326 * they're not part of another locator-set */
2327 clean_locator_to_locator_set (lcm, p[0]);
2329 /* remove locator indices from locator set */
2330 vec_free (ls->locator_indices);
2335 ls_result[0] = p[0];
2337 /* new locator-set */
2340 pool_get (lcm->locator_set_pool, ls);
2341 memset (ls, 0, sizeof (*ls));
2342 ls_index = ls - lcm->locator_set_pool;
2346 ls->name = vec_dup (a->name);
2348 if (!lcm->locator_set_index_by_name)
2349 lcm->locator_set_index_by_name = hash_create_vec (
2357 hash_set_mem (lcm->locator_set_index_by_name, ls->name,
2360 /* mark as local locator-set */
2361 vec_add1 (lcm->local_locator_set_indexes, ls_index);
2363 ls->local = a->local;
2365 ls_result[0] = ls_index;
2368 ret = vnet_lisp_add_del_locator (a, ls, NULL);
2376 p = get_locator_set_index (a, p);
2379 clib_warning ("locator-set %v doesn't exists", a->name);
2383 ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2386 clib_warning ("locator-set with index %d doesn't exists", p[0]);
2390 if (lcm->mreq_itr_rlocs == p[0])
2392 clib_warning ("Can't delete the locator-set used to constrain "
2393 "the itr-rlocs in map-requests!");
2397 if (vec_len (lcm->locator_set_to_eids) != 0)
2399 eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]);
2400 if (vec_len (eid_indexes[0]) != 0)
2403 ("Can't delete a locator that supports a mapping!");
2408 /* clean locator to locator-sets data */
2409 clean_locator_to_locator_set (lcm, p[0]);
2415 vec_foreach_index (it, lcm->local_locator_set_indexes)
2417 lsi = vec_elt (lcm->local_locator_set_indexes, it);
2420 vec_del1 (lcm->local_locator_set_indexes, it);
2424 hash_unset_mem (lcm->locator_set_index_by_name, ls->name);
2426 vec_free (ls->name);
2427 vec_free (ls->locator_indices);
2428 pool_put (lcm->locator_set_pool, ls);
2434 vnet_lisp_rloc_probe_enable_disable (u8 is_enable)
2436 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2438 lcm->rloc_probing = is_enable;
2443 vnet_lisp_map_register_enable_disable (u8 is_enable)
2445 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2447 lcm->map_registering = is_enable;
2452 vnet_lisp_enable_disable (u8 is_enable)
2455 clib_error_t *error = 0;
2456 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2457 vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
2459 a->is_en = is_enable;
2460 error = vnet_lisp_gpe_enable_disable (a);
2463 return clib_error_return (0, "failed to %s data-plane!",
2464 a->is_en ? "enable" : "disable");
2469 /* enable all l2 and l3 ifaces */
2472 hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({
2473 dp_add_del_iface(lcm, vni, 0, 1);
2475 hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({
2476 dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1);
2482 /* clear interface table */
2483 hash_free (lcm->fwd_entry_by_mapping_index);
2484 pool_free (lcm->fwd_entry_pool);
2487 /* update global flag */
2488 lcm->is_enabled = is_enable;
2493 static clib_error_t *
2494 lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input,
2495 vlib_cli_command_t * cmd)
2497 unformat_input_t _line_input, *line_input = &_line_input;
2501 /* Get a line of input. */
2502 if (!unformat_user (input, unformat_line_input, line_input))
2505 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2507 if (unformat (line_input, "enable"))
2512 else if (unformat (line_input, "disable"))
2516 return clib_error_return (0, "parse error: '%U'",
2517 format_unformat_error, line_input);
2522 return clib_error_return (0, "state not set");
2524 vnet_lisp_enable_disable (is_enabled);
2529 VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
2531 .short_help = "lisp [enable|disable]",
2532 .function = lisp_enable_disable_command_fn,
2536 static clib_error_t *
2537 lisp_map_register_enable_disable_command_fn (vlib_main_t * vm,
2538 unformat_input_t * input,
2539 vlib_cli_command_t * cmd)
2541 unformat_input_t _line_input, *line_input = &_line_input;
2545 /* Get a line of input. */
2546 if (!unformat_user (input, unformat_line_input, line_input))
2549 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2551 if (unformat (line_input, "enable"))
2556 else if (unformat (line_input, "disable"))
2560 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
2568 vlib_cli_output (vm, "state not set!");
2572 vnet_lisp_map_register_enable_disable (is_enabled);
2577 VLIB_CLI_COMMAND (lisp_map_register_enable_disable_command) = {
2578 .path = "lisp map-register",
2579 .short_help = "lisp map-register [enable|disable]",
2580 .function = lisp_map_register_enable_disable_command_fn,
2584 static clib_error_t *
2585 lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm,
2586 unformat_input_t * input,
2587 vlib_cli_command_t * cmd)
2589 unformat_input_t _line_input, *line_input = &_line_input;
2593 /* Get a line of input. */
2594 if (!unformat_user (input, unformat_line_input, line_input))
2597 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2599 if (unformat (line_input, "enable"))
2604 else if (unformat (line_input, "disable"))
2608 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
2616 vlib_cli_output (vm, "state not set!");
2620 vnet_lisp_rloc_probe_enable_disable (is_enabled);
2625 VLIB_CLI_COMMAND (lisp_rloc_probe_enable_disable_command) = {
2626 .path = "lisp rloc-probe",
2627 .short_help = "lisp rloc-probe [enable|disable]",
2628 .function = lisp_rloc_probe_enable_disable_command_fn,
2633 vnet_lisp_enable_disable_status (void)
2635 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2636 return lcm->is_enabled;
2640 format_lisp_status (u8 * s, va_list * args)
2642 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2643 return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
2646 static clib_error_t *
2647 lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input,
2648 vlib_cli_command_t * cmd)
2651 msg = format (msg, "feature: %U\ngpe: %U\n",
2652 format_lisp_status, format_vnet_lisp_gpe_status);
2653 vlib_cli_output (vm, "%v", msg);
2659 VLIB_CLI_COMMAND (lisp_show_status_command) = {
2660 .path = "show lisp status",
2661 .short_help = "show lisp status",
2662 .function = lisp_show_status_command_fn,
2666 static clib_error_t *
2667 lisp_show_eid_table_map_command_fn (vlib_main_t * vm,
2668 unformat_input_t * input,
2669 vlib_cli_command_t * cmd)
2672 unformat_input_t _line_input, *line_input = &_line_input;
2673 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2674 uword *vni_table = 0;
2677 /* Get a line of input. */
2678 if (!unformat_user (input, unformat_line_input, line_input))
2681 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2683 if (unformat (line_input, "l2"))
2685 vni_table = lcm->bd_id_by_vni;
2688 else if (unformat (line_input, "l3"))
2690 vni_table = lcm->table_id_by_vni;
2694 return clib_error_return (0, "parse error: '%U'",
2695 format_unformat_error, line_input);
2700 vlib_cli_output (vm, "Error: expected l2|l3 param!\n");
2704 vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF");
2707 hash_foreach_pair (p, vni_table,
2709 vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
2717 VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
2718 .path = "show lisp eid-table map",
2719 .short_help = "show lisp eid-table l2|l3",
2720 .function = lisp_show_eid_table_map_command_fn,
2724 static clib_error_t *
2725 lisp_add_del_locator_set_command_fn (vlib_main_t * vm,
2726 unformat_input_t * input,
2727 vlib_cli_command_t * cmd)
2729 lisp_gpe_main_t *lgm = &lisp_gpe_main;
2730 vnet_main_t *vnm = lgm->vnet_main;
2731 unformat_input_t _line_input, *line_input = &_line_input;
2733 clib_error_t *error = 0;
2734 u8 *locator_set_name = 0;
2735 locator_t locator, *locators = 0;
2736 vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
2740 memset (&locator, 0, sizeof (locator));
2741 memset (a, 0, sizeof (a[0]));
2743 /* Get a line of input. */
2744 if (!unformat_user (input, unformat_line_input, line_input))
2747 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2749 if (unformat (line_input, "add %_%v%_", &locator_set_name))
2751 else if (unformat (line_input, "del %_%v%_", &locator_set_name))
2753 else if (unformat (line_input, "iface %U p %d w %d",
2754 unformat_vnet_sw_interface, vnm,
2755 &locator.sw_if_index, &locator.priority,
2759 vec_add1 (locators, locator);
2763 error = unformat_parse_error (line_input);
2768 a->name = locator_set_name;
2769 a->locators = locators;
2773 rv = vnet_lisp_add_del_locator_set (a, &ls_index);
2776 error = clib_error_return (0, "failed to %s locator-set!",
2777 is_add ? "add" : "delete");
2781 vec_free (locators);
2782 if (locator_set_name)
2783 vec_free (locator_set_name);
2788 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
2789 .path = "lisp locator-set",
2790 .short_help = "lisp locator-set add/del <name> [iface <iface-name> "
2791 "p <priority> w <weight>]",
2792 .function = lisp_add_del_locator_set_command_fn,
2796 static clib_error_t *
2797 lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm,
2798 unformat_input_t * input,
2799 vlib_cli_command_t * cmd)
2801 lisp_gpe_main_t *lgm = &lisp_gpe_main;
2802 vnet_main_t *vnm = lgm->vnet_main;
2803 unformat_input_t _line_input, *line_input = &_line_input;
2805 clib_error_t *error = 0;
2806 u8 *locator_set_name = 0;
2807 u8 locator_set_name_set = 0;
2808 locator_t locator, *locators = 0;
2809 vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
2812 memset (&locator, 0, sizeof (locator));
2813 memset (a, 0, sizeof (a[0]));
2815 /* Get a line of input. */
2816 if (!unformat_user (input, unformat_line_input, line_input))
2819 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2821 if (unformat (line_input, "add"))
2823 else if (unformat (line_input, "del"))
2825 else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
2826 locator_set_name_set = 1;
2827 else if (unformat (line_input, "iface %U p %d w %d",
2828 unformat_vnet_sw_interface, vnm,
2829 &locator.sw_if_index, &locator.priority,
2833 vec_add1 (locators, locator);
2837 error = unformat_parse_error (line_input);
2842 if (!locator_set_name_set)
2844 error = clib_error_return (0, "locator_set name not set!");
2848 a->name = locator_set_name;
2849 a->locators = locators;
2853 vnet_lisp_add_del_locator (a, 0, &ls_index);
2856 vec_free (locators);
2857 vec_free (locator_set_name);
2862 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = {
2863 .path = "lisp locator",
2864 .short_help = "lisp locator add/del locator-set <name> iface <iface-name> "
2865 "p <priority> w <weight>",
2866 .function = lisp_add_del_locator_in_set_command_fn,
2870 static clib_error_t *
2871 lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm,
2872 unformat_input_t * input,
2873 vlib_cli_command_t * cmd)
2875 locator_set_t *lsit;
2878 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2880 vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator",
2881 "Priority", "Weight");
2884 pool_foreach (lsit, lcm->locator_set_pool,
2890 msg = format (msg, "%v", lsit->name);
2894 msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool);
2896 vec_foreach (locit, lsit->locator_indices)
2900 msg = format (msg, "%16s", " ");
2902 loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2904 msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
2907 msg = format (msg, "%16U%16d%16d\n", format_ip_address,
2908 &gid_address_ip(&loc->address), loc->priority,
2912 vlib_cli_output (vm, "%v", msg);
2920 VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
2921 .path = "show lisp locator-set",
2922 .short_help = "Shows locator-sets",
2923 .function = lisp_cp_show_locator_sets_command_fn,
2928 vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a)
2930 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
2932 lisp_msmr_t _mr, *mr = &_mr;
2934 if (vnet_lisp_enable_disable_status () == 0)
2936 clib_warning ("LISP is disabled!");
2937 return VNET_API_ERROR_LISP_DISABLED;
2943 if (get_map_resolver (&a->address))
2945 clib_warning ("map-resolver %U already exists!", format_ip_address,
2950 memset (mr, 0, sizeof (*mr));
2951 ip_address_copy (&mr->address, &a->address);
2952 vec_add1 (lcm->map_resolvers, *mr);
2954 if (vec_len (lcm->map_resolvers) == 1)
2955 lcm->do_map_resolver_election = 1;
2959 for (i = 0; i < vec_len (lcm->map_resolvers); i++)
2961 mr = vec_elt_at_index (lcm->map_resolvers, i);
2962 if (!ip_address_cmp (&mr->address, &a->address))
2964 if (!ip_address_cmp (&mr->address, &lcm->active_map_resolver))
2965 lcm->do_map_resolver_election = 1;
2967 vec_del1 (lcm->map_resolvers, i);
2975 static clib_error_t *
2976 lisp_add_del_map_resolver_command_fn (vlib_main_t * vm,
2977 unformat_input_t * input,
2978 vlib_cli_command_t * cmd)
2980 unformat_input_t _line_input, *line_input = &_line_input;
2981 u8 is_add = 1, addr_set = 0;
2982 ip_address_t ip_addr;
2983 clib_error_t *error = 0;
2985 vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
2987 /* Get a line of input. */
2988 if (!unformat_user (input, unformat_line_input, line_input))
2991 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2993 if (unformat (line_input, "add"))
2995 else if (unformat (line_input, "del"))
2997 else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
3001 error = unformat_parse_error (line_input);
3008 error = clib_error_return (0, "Map-resolver address must be set!");
3013 a->address = ip_addr;
3014 rv = vnet_lisp_add_del_map_resolver (a);
3017 error = clib_error_return (0, "failed to %s map-resolver!",
3018 is_add ? "add" : "delete");
3026 VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
3027 .path = "lisp map-resolver",
3028 .short_help = "lisp map-resolver add/del <ip_address>",
3029 .function = lisp_add_del_map_resolver_command_fn,
3034 vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
3036 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3039 if (vnet_lisp_enable_disable_status () == 0)
3041 clib_warning ("LISP is disabled!");
3042 return VNET_API_ERROR_LISP_DISABLED;
3047 p = hash_get_mem (lcm->locator_set_index_by_name, a->locator_set_name);
3050 clib_warning ("locator-set %v doesn't exist", a->locator_set_name);
3051 return VNET_API_ERROR_INVALID_ARGUMENT;
3054 lcm->mreq_itr_rlocs = p[0];
3058 lcm->mreq_itr_rlocs = ~0;
3064 static clib_error_t *
3065 lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
3066 unformat_input_t * input,
3067 vlib_cli_command_t * cmd)
3069 unformat_input_t _line_input, *line_input = &_line_input;
3071 u8 *locator_set_name = 0;
3072 clib_error_t *error = 0;
3074 vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
3076 /* Get a line of input. */
3077 if (!unformat_user (input, unformat_line_input, line_input))
3080 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3082 if (unformat (line_input, "del"))
3084 else if (unformat (line_input, "add %_%v%_", &locator_set_name))
3088 error = unformat_parse_error (line_input);
3094 a->locator_set_name = locator_set_name;
3095 rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
3098 error = clib_error_return (0, "failed to %s map-request itr-rlocs!",
3099 is_add ? "add" : "delete");
3102 vec_free (locator_set_name);
3110 VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = {
3111 .path = "lisp map-request itr-rlocs",
3112 .short_help = "lisp map-request itr-rlocs add/del <locator_set_name>",
3113 .function = lisp_add_del_mreq_itr_rlocs_command_fn,
3117 static clib_error_t *
3118 lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm,
3119 unformat_input_t * input,
3120 vlib_cli_command_t * cmd)
3122 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3123 locator_set_t *loc_set;
3125 vlib_cli_output (vm, "%=20s", "itr-rlocs");
3127 if (~0 == lcm->mreq_itr_rlocs)
3132 loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
3134 vlib_cli_output (vm, "%=20s", loc_set->name);
3140 VLIB_CLI_COMMAND (lisp_show_map_request_command) = {
3141 .path = "show lisp map-request itr-rlocs",
3142 .short_help = "Shows map-request itr-rlocs",
3143 .function = lisp_show_mreq_itr_rlocs_command_fn,
3147 /* Statistics (not really errors) */
3148 #define foreach_lisp_cp_lookup_error \
3150 _(MAP_REQUESTS_SENT, "map-request sent")
3152 static char *lisp_cp_lookup_error_strings[] = {
3153 #define _(sym,string) string,
3154 foreach_lisp_cp_lookup_error
3160 #define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
3161 foreach_lisp_cp_lookup_error
3163 LISP_CP_LOOKUP_N_ERROR,
3164 } lisp_cp_lookup_error_t;
3168 LISP_CP_LOOKUP_NEXT_DROP,
3169 LISP_CP_LOOKUP_N_NEXT,
3170 } lisp_cp_lookup_next_t;
3174 gid_address_t dst_eid;
3175 ip_address_t map_resolver_ip;
3176 } lisp_cp_lookup_trace_t;
3179 format_lisp_cp_lookup_trace (u8 * s, va_list * args)
3181 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
3182 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
3183 lisp_cp_lookup_trace_t *t = va_arg (*args, lisp_cp_lookup_trace_t *);
3185 s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
3186 format_ip_address, &t->map_resolver_ip, format_gid_address,
3192 get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
3193 ip_address_t * sloc)
3198 if (vec_len (lcm->map_resolvers) == 0)
3200 clib_warning ("No map-resolver configured");
3204 /* find the first mr ip we have a route to and the ip of the
3205 * iface that has a route to it */
3206 vec_foreach (mrit, lcm->map_resolvers)
3209 if (0 != ip_fib_get_first_egress_ip_for_dst (lcm, a, sloc))
3211 ip_address_copy (mr_ip, a);
3213 /* also update globals */
3218 clib_warning ("Can't find map-resolver and local interface ip!");
3222 static gid_address_t *
3223 build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
3229 ip_interface_address_t *ia = 0;
3230 gid_address_t gid_data, *gid = &gid_data;
3231 gid_address_t *rlocs = 0;
3232 ip_prefix_t *ippref = &gid_address_ippref (gid);
3233 ip_address_t *rloc = &ip_prefix_addr (ippref);
3235 memset (gid, 0, sizeof (gid[0]));
3236 gid_address_type (gid) = GID_ADDR_IP_PREFIX;
3237 for (i = 0; i < vec_len (loc_set->locator_indices); i++)
3239 loc_indexp = vec_elt_at_index (loc_set->locator_indices, i);
3240 loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
3242 /* Add ipv4 locators first TODO sort them */
3245 foreach_ip_interface_address (&lcm->im4->lookup_main, ia,
3246 loc->sw_if_index, 1 /* unnumbered */,
3248 addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
3249 ip_address_set (rloc, addr, IP4);
3250 ip_prefix_len (ippref) = 32;
3251 ip_prefix_normalize (ippref);
3252 vec_add1 (rlocs, gid[0]);
3255 /* Add ipv6 locators */
3256 foreach_ip_interface_address (&lcm->im6->lookup_main, ia,
3257 loc->sw_if_index, 1 /* unnumbered */,
3259 addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
3260 ip_address_set (rloc, addr, IP6);
3261 ip_prefix_len (ippref) = 128;
3262 ip_prefix_normalize (ippref);
3263 vec_add1 (rlocs, gid[0]);
3271 static vlib_buffer_t *
3272 build_map_request (lisp_cp_main_t * lcm, gid_address_t * deid,
3273 ip_address_t * sloc, ip_address_t * rloc,
3274 gid_address_t * itr_rlocs, u64 * nonce_res, u32 * bi_res)
3278 vlib_main_t *vm = lcm->vlib_main;
3280 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3282 clib_warning ("Can't allocate buffer for Map-Request!");
3286 b = vlib_get_buffer (vm, bi);
3288 /* leave some space for the encap headers */
3289 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
3292 lisp_msg_put_mreq (lcm, b, NULL, deid, itr_rlocs, 0 /* smr invoked */ ,
3293 1 /* rloc probe */ , nonce_res);
3295 /* push outer ip header */
3296 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
3304 static vlib_buffer_t *
3305 build_encapsulated_map_request (lisp_cp_main_t * lcm,
3306 gid_address_t * seid, gid_address_t * deid,
3307 locator_set_t * loc_set, ip_address_t * mr_ip,
3308 ip_address_t * sloc, u8 is_smr_invoked,
3309 u64 * nonce_res, u32 * bi_res)
3313 gid_address_t *rlocs = 0;
3314 vlib_main_t *vm = lcm->vlib_main;
3316 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3318 clib_warning ("Can't allocate buffer for Map-Request!");
3322 b = vlib_get_buffer (vm, bi);
3324 /* leave some space for the encap headers */
3325 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
3328 rlocs = build_itr_rloc_list (lcm, loc_set);
3330 if (MR_MODE_SRC_DST == lcm->map_request_mode
3331 && GID_ADDR_SRC_DST != gid_address_type (deid))
3334 memset (&sd, 0, sizeof (sd));
3335 build_src_dst (&sd, seid, deid);
3336 lisp_msg_put_mreq (lcm, b, seid, &sd, rlocs, is_smr_invoked,
3337 0 /* rloc probe */ , nonce_res);
3342 lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked,
3343 0 /* rloc probe */ , nonce_res);
3346 /* push ecm: udp-ip-lisp */
3347 lisp_msg_push_ecm (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, seid, deid);
3349 /* push outer ip header */
3350 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
3360 reset_pending_mr_counters (pending_map_request_t * r)
3362 r->time_to_expire = PENDING_MREQ_EXPIRATION_TIME;
3367 elect_map_resolver (lisp_cp_main_t * lcm)
3371 vec_foreach (mr, lcm->map_resolvers)
3375 ip_address_copy (&lcm->active_map_resolver, &mr->address);
3376 lcm->do_map_resolver_election = 0;
3384 free_map_register_records (mapping_t * maps)
3387 vec_foreach (map, maps) vec_free (map->locators);
3393 add_locators (lisp_cp_main_t * lcm, mapping_t * m, u32 locator_set_index,
3394 ip_address_t * probed_loc)
3397 locator_t *loc, new;
3398 ip_interface_address_t *ia = 0;
3400 ip_address_t *new_ip = &gid_address_ip (&new.address);
3403 locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
3405 vec_foreach (li, ls->locator_indices)
3407 loc = pool_elt_at_index (lcm->locator_pool, li[0]);
3412 foreach_ip_interface_address (&lcm->im4->lookup_main, ia,
3413 loc->sw_if_index, 1 /* unnumbered */,
3415 addr = ip_interface_address_get_address (&lcm->im4->lookup_main,
3417 ip_address_set (new_ip, addr, IP4);
3420 /* Add ipv6 locators */
3421 foreach_ip_interface_address (&lcm->im6->lookup_main, ia,
3422 loc->sw_if_index, 1 /* unnumbered */,
3424 addr = ip_interface_address_get_address (&lcm->im6->lookup_main,
3426 ip_address_set (new_ip, addr, IP6);
3430 if (probed_loc && ip_address_cmp (probed_loc, new_ip) == 0)
3433 vec_add1 (m->locators, new);
3438 build_map_register_record_list (lisp_cp_main_t * lcm)
3440 mapping_t *recs = 0, rec, *m;
3443 pool_foreach(m, lcm->mapping_pool,
3445 /* for now build only local mappings */
3450 add_locators (lcm, &rec, m->locator_set_index, NULL);
3451 vec_add1 (recs, rec);
3459 update_map_register_auth_data (map_register_hdr_t * map_reg_hdr,
3460 lisp_key_type_t key_id, u8 * key,
3461 u16 auth_data_len, u32 msg_len)
3463 MREG_KEY_ID (map_reg_hdr) = clib_host_to_net_u16 (key_id);
3464 MREG_AUTH_DATA_LEN (map_reg_hdr) = clib_host_to_net_u16 (auth_data_len);
3466 unsigned char *result = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
3467 (unsigned char *) map_reg_hdr, msg_len, NULL,
3469 clib_memcpy (MREG_DATA (map_reg_hdr), result, auth_data_len);
3474 static vlib_buffer_t *
3475 build_map_register (lisp_cp_main_t * lcm, ip_address_t * sloc,
3476 ip_address_t * ms_ip, u64 * nonce_res, u8 want_map_notif,
3477 mapping_t * records, lisp_key_type_t key_id, u8 * key,
3482 u32 bi, auth_data_len = 0, msg_len = 0;
3483 vlib_main_t *vm = lcm->vlib_main;
3485 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3487 clib_warning ("Can't allocate buffer for Map-Register!");
3491 b = vlib_get_buffer (vm, bi);
3493 /* leave some space for the encap headers */
3494 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
3496 auth_data_len = auth_data_len_by_key_id (key_id);
3497 map_reg_hdr = lisp_msg_put_map_register (b, records, want_map_notif,
3498 auth_data_len, nonce_res,
3501 update_map_register_auth_data (map_reg_hdr, key_id, key, auth_data_len,
3504 /* push outer ip header */
3505 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
3513 get_egress_map_resolver_ip (lisp_cp_main_t * lcm, ip_address_t * ip)
3516 while (lcm->do_map_resolver_election
3517 | (0 == ip_fib_get_first_egress_ip_for_dst (lcm,
3518 &lcm->active_map_resolver,
3521 if (0 == elect_map_resolver (lcm))
3522 /* all map resolvers are down */
3524 /* restart MR checking by marking all of them up */
3525 vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0;
3532 /* CP output statistics */
3533 #define foreach_lisp_cp_output_error \
3534 _(MAP_REGISTERS_SENT, "map-registers sent") \
3535 _(RLOC_PROBES_SENT, "rloc-probes sent")
3537 static char *lisp_cp_output_error_strings[] = {
3538 #define _(sym,string) string,
3539 foreach_lisp_cp_output_error
3545 #define _(sym,str) LISP_CP_OUTPUT_ERROR_##sym,
3546 foreach_lisp_cp_output_error
3548 LISP_CP_OUTPUT_N_ERROR,
3549 } lisp_cp_output_error_t;
3552 lisp_cp_output (vlib_main_t * vm, vlib_node_runtime_t * node,
3553 vlib_frame_t * from_frame)
3558 /* dummy node used only for statistics */
3560 VLIB_REGISTER_NODE (lisp_cp_output_node) = {
3561 .function = lisp_cp_output,
3562 .name = "lisp-cp-output",
3563 .vector_size = sizeof (u32),
3564 .format_trace = format_lisp_cp_input_trace,
3565 .type = VLIB_NODE_TYPE_INTERNAL,
3567 .n_errors = LISP_CP_OUTPUT_N_ERROR,
3568 .error_strings = lisp_cp_output_error_strings,
3570 .n_next_nodes = LISP_CP_INPUT_N_NEXT,
3573 [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
3579 send_rloc_probe (lisp_cp_main_t * lcm, gid_address_t * deid,
3580 u32 local_locator_set_index, ip_address_t * sloc,
3581 ip_address_t * rloc)
3588 u32 next_index, *to_next;
3589 gid_address_t *itr_rlocs;
3591 ls = pool_elt_at_index (lcm->locator_set_pool, local_locator_set_index);
3592 itr_rlocs = build_itr_rloc_list (lcm, ls);
3594 b = build_map_request (lcm, deid, sloc, rloc, itr_rlocs, &nonce, &bi);
3595 vec_free (itr_rlocs);
3599 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3601 next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3602 ip4_lookup_node.index : ip6_lookup_node.index;
3604 f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3606 /* Enqueue the packet */
3607 to_next = vlib_frame_vector_args (f);
3610 vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3612 hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
3617 send_rloc_probes (lisp_cp_main_t * lcm)
3623 u32 si, rloc_probes_sent = 0;
3626 pool_foreach (e, lcm->fwd_entry_pool,
3628 if (vec_len (e->locator_pairs) == 0)
3631 si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &e->leid);
3634 clib_warning ("internal error: cannot find local eid %U in "
3635 "map-cache!", format_gid_address, &e->leid);
3638 lm = pool_elt_at_index (lcm->mapping_pool, si);
3640 /* get the best (lowest) priority */
3641 lprio = e->locator_pairs[0].priority;
3643 /* send rloc-probe for pair(s) with the best remote locator priority */
3644 vec_foreach (lp, e->locator_pairs)
3646 if (lp->priority != lprio)
3649 /* get first remote locator */
3650 send_rloc_probe (lcm, &e->reid, lm->locator_set_index, &lp->lcl_loc,
3657 vlib_node_increment_counter (vlib_get_main (), lisp_cp_output_node.index,
3658 LISP_CP_OUTPUT_ERROR_RLOC_PROBES_SENT,
3664 send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif)
3666 u32 bi, map_registers_sent = 0;
3671 u32 next_index, *to_next;
3672 ip_address_t *ms = 0;
3673 mapping_t *records, *r, *g;
3675 // TODO: support multiple map servers and do election
3676 if (0 == vec_len (lcm->map_servers))
3679 ms = &lcm->map_servers[0].address;
3681 if (0 == ip_fib_get_first_egress_ip_for_dst (lcm, ms, &sloc))
3683 clib_warning ("no eligible interface address found for %U!",
3684 format_ip_address, &lcm->map_servers[0]);
3688 records = build_map_register_record_list (lcm);
3692 vec_foreach (r, records)
3695 u8 key_id = r->key_id;
3698 continue; /* no secret key -> map-register cannot be sent */
3701 // TODO: group mappings that share common key
3703 b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, g,
3709 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3711 next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3712 ip4_lookup_node.index : ip6_lookup_node.index;
3714 f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3716 /* Enqueue the packet */
3717 to_next = vlib_frame_vector_args (f);
3720 vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3721 map_registers_sent++;
3723 hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
3725 free_map_register_records (records);
3727 vlib_node_increment_counter (vlib_get_main (), lisp_cp_output_node.index,
3728 LISP_CP_OUTPUT_ERROR_MAP_REGISTERS_SENT,
3729 map_registers_sent);
3734 #define send_encapsulated_map_request(lcm, seid, deid, smr) \
3735 _send_encapsulated_map_request(lcm, seid, deid, smr, 0)
3737 #define resend_encapsulated_map_request(lcm, seid, deid, smr) \
3738 _send_encapsulated_map_request(lcm, seid, deid, smr, 1)
3741 _send_encapsulated_map_request (lisp_cp_main_t * lcm,
3742 gid_address_t * seid, gid_address_t * deid,
3743 u8 is_smr_invoked, u8 is_resend)
3745 u32 next_index, bi = 0, *to_next, map_index;
3749 locator_set_t *loc_set;
3751 pending_map_request_t *pmr, *duplicate_pmr = 0;
3755 /* if there is already a pending request remember it */
3758 pool_foreach(pmr, lcm->pending_map_requests_pool,
3760 if (!gid_address_cmp (&pmr->src, seid)
3761 && !gid_address_cmp (&pmr->dst, deid))
3763 duplicate_pmr = pmr;
3769 if (!is_resend && duplicate_pmr)
3771 /* don't send the request if there is a pending map request already */
3775 /* get locator-set for seid */
3776 if (!lcm->lisp_pitr)
3778 map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
3779 if (map_index == ~0)
3781 clib_warning ("No local mapping found in eid-table for %U!",
3782 format_gid_address, seid);
3786 map = pool_elt_at_index (lcm->mapping_pool, map_index);
3791 ("Mapping found for src eid %U is not marked as local!",
3792 format_gid_address, seid);
3795 ls_index = map->locator_set_index;
3799 map_index = lcm->pitr_map_index;
3800 map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
3801 ls_index = map->locator_set_index;
3804 /* overwrite locator set if map-request itr-rlocs configured */
3805 if (~0 != lcm->mreq_itr_rlocs)
3807 ls_index = lcm->mreq_itr_rlocs;
3810 loc_set = pool_elt_at_index (lcm->locator_set_pool, ls_index);
3812 if (get_egress_map_resolver_ip (lcm, &sloc) < 0)
3815 duplicate_pmr->to_be_removed = 1;
3819 /* build the encapsulated map request */
3820 b = build_encapsulated_map_request (lcm, seid, deid, loc_set,
3821 &lcm->active_map_resolver,
3822 &sloc, is_smr_invoked, &nonce, &bi);
3827 /* set fib index to default and lookup node */
3828 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3829 next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3830 ip4_lookup_node.index : ip6_lookup_node.index;
3832 f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3834 /* Enqueue the packet */
3835 to_next = vlib_frame_vector_args (f);
3838 vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3841 /* if there is a pending request already update it */
3843 if (clib_fifo_elts (duplicate_pmr->nonces) >= PENDING_MREQ_QUEUE_LEN)
3845 /* remove the oldest nonce */
3846 u64 CLIB_UNUSED (tmp), *nonce_del;
3847 nonce_del = clib_fifo_head (duplicate_pmr->nonces);
3848 hash_unset (lcm->pending_map_requests_by_nonce, nonce_del[0]);
3849 clib_fifo_sub1 (duplicate_pmr->nonces, tmp);
3852 clib_fifo_add1 (duplicate_pmr->nonces, nonce);
3853 hash_set (lcm->pending_map_requests_by_nonce, nonce,
3854 duplicate_pmr - lcm->pending_map_requests_pool);
3858 /* add map-request to pending requests table */
3859 pool_get (lcm->pending_map_requests_pool, pmr);
3860 memset (pmr, 0, sizeof (*pmr));
3861 gid_address_copy (&pmr->src, seid);
3862 gid_address_copy (&pmr->dst, deid);
3863 clib_fifo_add1 (pmr->nonces, nonce);
3864 pmr->is_smr_invoked = is_smr_invoked;
3865 reset_pending_mr_counters (pmr);
3866 hash_set (lcm->pending_map_requests_by_nonce, nonce,
3867 pmr - lcm->pending_map_requests_pool);
3874 get_src_and_dst_ip (void *hdr, ip_address_t * src, ip_address_t * dst)
3876 ip4_header_t *ip4 = hdr;
3879 if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
3881 ip_address_set (src, &ip4->src_address, IP4);
3882 ip_address_set (dst, &ip4->dst_address, IP4);
3887 ip_address_set (src, &ip6->src_address, IP6);
3888 ip_address_set (dst, &ip6->dst_address, IP6);
3893 lisp_get_vni_from_buffer_ip (lisp_cp_main_t * lcm, vlib_buffer_t * b,
3897 u32 vni = ~0, table_id = ~0;
3899 table_id = fib_table_get_table_id_for_sw_if_index ((version ==
3900 IP4 ? FIB_PROTOCOL_IP4 :
3906 vnip = hash_get (lcm->vni_by_table_id, table_id);
3910 clib_warning ("vrf %d is not mapped to any vni!", table_id);
3916 lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
3922 l2input_main_t *l2im = &l2input_main;
3923 l2_input_config_t *config;
3924 l2_bridge_domain_t *bd_config;
3926 sw_if_index0 = vnet_buffer (b)->sw_if_index[VLIB_RX];
3927 config = vec_elt_at_index (l2im->configs, sw_if_index0);
3928 bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
3930 vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id);
3934 clib_warning ("bridge domain %d is not mapped to any vni!",
3941 get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
3942 gid_address_t * src, gid_address_t * dst)
3947 memset (src, 0, sizeof (*src));
3948 memset (dst, 0, sizeof (*dst));
3949 type = vnet_buffer (b)->lisp.overlay_afi;
3951 if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
3954 u8 version, preflen;
3956 gid_address_type (src) = GID_ADDR_IP_PREFIX;
3957 gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3959 ip = vlib_buffer_get_current (b);
3960 get_src_and_dst_ip (ip, &gid_address_ip (src), &gid_address_ip (dst));
3962 version = gid_address_ip_version (src);
3963 preflen = ip_address_max_len (version);
3964 gid_address_ippref_len (src) = preflen;
3965 gid_address_ippref_len (dst) = preflen;
3967 vni = lisp_get_vni_from_buffer_ip (lcm, b, version);
3968 gid_address_vni (dst) = vni;
3969 gid_address_vni (src) = vni;
3971 else if (LISP_AFI_MAC == type)
3973 ethernet_header_t *eh;
3975 eh = vlib_buffer_get_current (b);
3977 gid_address_type (src) = GID_ADDR_MAC;
3978 gid_address_type (dst) = GID_ADDR_MAC;
3979 mac_copy (&gid_address_mac (src), eh->src_address);
3980 mac_copy (&gid_address_mac (dst), eh->dst_address);
3983 vni = lisp_get_vni_from_buffer_eth (lcm, b);
3985 gid_address_vni (dst) = vni;
3986 gid_address_vni (src) = vni;
3991 lisp_cp_lookup_inline (vlib_main_t * vm,
3992 vlib_node_runtime_t * node,
3993 vlib_frame_t * from_frame, int overlay)
3995 u32 *from, *to_next_drop, di, si;
3996 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3997 u32 pkts_mapped = 0;
3998 uword n_left_from, n_left_to_next_drop;
4000 from = vlib_frame_vector_args (from_frame);
4001 n_left_from = from_frame->n_vectors;
4003 while (n_left_from > 0)
4005 vlib_get_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
4006 to_next_drop, n_left_to_next_drop);
4008 while (n_left_from > 0 && n_left_to_next_drop > 0)
4012 gid_address_t src, dst;
4017 to_next_drop[0] = pi0;
4019 n_left_to_next_drop -= 1;
4021 b0 = vlib_get_buffer (vm, pi0);
4022 b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
4023 vnet_buffer (b0)->lisp.overlay_afi = overlay;
4025 /* src/dst eid pair */
4026 get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
4028 /* if we have remote mapping for destination already in map-chache
4029 add forwarding tunnel directly. If not send a map-request */
4030 di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst,
4034 mapping_t *m = vec_elt_at_index (lcm->mapping_pool, di);
4035 /* send a map-request also in case of negative mapping entry
4036 with corresponding action */
4037 if (m->action == LISP_SEND_MAP_REQUEST)
4039 /* send map-request */
4040 queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
4041 0 /* is_resend */ );
4046 si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
4050 dp_add_fwd_entry_from_mt (si, di);
4056 /* send map-request */
4057 queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
4058 0 /* is_resend */ );
4062 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
4064 lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
4067 memset (tr, 0, sizeof (*tr));
4068 gid_address_copy (&tr->dst_eid, &dst);
4069 ip_address_copy (&tr->map_resolver_ip,
4070 &lcm->active_map_resolver);
4072 gid_address_free (&dst);
4073 gid_address_free (&src);
4076 vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
4077 n_left_to_next_drop);
4079 vlib_node_increment_counter (vm, node->node_index,
4080 LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
4082 return from_frame->n_vectors;
4086 lisp_cp_lookup_ip4 (vlib_main_t * vm,
4087 vlib_node_runtime_t * node, vlib_frame_t * from_frame)
4089 return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP));
4093 lisp_cp_lookup_ip6 (vlib_main_t * vm,
4094 vlib_node_runtime_t * node, vlib_frame_t * from_frame)
4096 return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP6));
4100 lisp_cp_lookup_l2 (vlib_main_t * vm,
4101 vlib_node_runtime_t * node, vlib_frame_t * from_frame)
4103 return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_MAC));
4107 VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = {
4108 .function = lisp_cp_lookup_ip4,
4109 .name = "lisp-cp-lookup-ip4",
4110 .vector_size = sizeof (u32),
4111 .format_trace = format_lisp_cp_lookup_trace,
4112 .type = VLIB_NODE_TYPE_INTERNAL,
4114 .n_errors = LISP_CP_LOOKUP_N_ERROR,
4115 .error_strings = lisp_cp_lookup_error_strings,
4117 .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4120 [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4126 VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node) = {
4127 .function = lisp_cp_lookup_ip6,
4128 .name = "lisp-cp-lookup-ip6",
4129 .vector_size = sizeof (u32),
4130 .format_trace = format_lisp_cp_lookup_trace,
4131 .type = VLIB_NODE_TYPE_INTERNAL,
4133 .n_errors = LISP_CP_LOOKUP_N_ERROR,
4134 .error_strings = lisp_cp_lookup_error_strings,
4136 .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4139 [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4145 VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node) = {
4146 .function = lisp_cp_lookup_l2,
4147 .name = "lisp-cp-lookup-l2",
4148 .vector_size = sizeof (u32),
4149 .format_trace = format_lisp_cp_lookup_trace,
4150 .type = VLIB_NODE_TYPE_INTERNAL,
4152 .n_errors = LISP_CP_LOOKUP_N_ERROR,
4153 .error_strings = lisp_cp_lookup_error_strings,
4155 .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4158 [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4163 /* lisp_cp_input statistics */
4164 #define foreach_lisp_cp_input_error \
4166 _(RLOC_PROBE_REQ_RECEIVED, "rloc-probe requests received") \
4167 _(RLOC_PROBE_REP_RECEIVED, "rloc-probe replies received") \
4168 _(MAP_NOTIFIES_RECEIVED, "map-notifies received") \
4169 _(MAP_REPLIES_RECEIVED, "map-replies received")
4171 static char *lisp_cp_input_error_strings[] = {
4172 #define _(sym,string) string,
4173 foreach_lisp_cp_input_error
4179 #define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
4180 foreach_lisp_cp_input_error
4182 LISP_CP_INPUT_N_ERROR,
4183 } lisp_cp_input_error_t;
4187 gid_address_t dst_eid;
4188 ip4_address_t map_resolver_ip;
4189 } lisp_cp_input_trace_t;
4192 format_lisp_cp_input_trace (u8 * s, va_list * args)
4194 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
4195 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
4196 CLIB_UNUSED (lisp_cp_input_trace_t * t) =
4197 va_arg (*args, lisp_cp_input_trace_t *);
4199 s = format (s, "LISP-CP-INPUT: TODO");
4204 remove_expired_mapping (lisp_cp_main_t * lcm, u32 mi)
4208 m = pool_elt_at_index (lcm->mapping_pool, mi);
4209 lisp_add_del_adjacency (lcm, 0, &m->eid, 0 /* is_add */ );
4210 vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ ,
4211 0 /* is_static */ , 0);
4212 mapping_delete_timer (lcm, mi);
4216 mapping_start_expiration_timer (lisp_cp_main_t * lcm, u32 mi,
4217 f64 expiration_time)
4220 u64 now = clib_cpu_time_now ();
4221 u64 cpu_cps = lcm->vlib_main->clib_time.clocks_per_second;
4222 u64 exp_clock_time = now + expiration_time * cpu_cps;
4224 m = pool_elt_at_index (lcm->mapping_pool, mi);
4227 timing_wheel_insert (&lcm->wheel, exp_clock_time, mi);
4231 map_records_arg_free (map_records_arg_t * a)
4234 vec_foreach (m, a->mappings)
4236 vec_free (m->locators);
4237 gid_address_free (&m->eid);
4244 process_map_reply (map_records_arg_t * a)
4247 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4248 u32 dst_map_index = 0;
4249 pending_map_request_t *pmr;
4253 if (a->is_rloc_probe)
4256 /* Check pending requests table and nonce */
4257 pmr_index = hash_get (lcm->pending_map_requests_by_nonce, a->nonce);
4260 clib_warning ("No pending map-request entry with nonce %lu!", a->nonce);
4263 pmr = pool_elt_at_index (lcm->pending_map_requests_pool, pmr_index[0]);
4265 vec_foreach (m, a->mappings)
4267 /* insert/update mappings cache */
4268 vnet_lisp_add_del_mapping (&m->eid, m->locators, m->action,
4269 m->authoritative, m->ttl,
4270 1, 0 /* is_static */ , &dst_map_index);
4272 /* try to program forwarding only if mapping saved or updated */
4273 if ((u32) ~ 0 != dst_map_index)
4275 lisp_add_del_adjacency (lcm, &pmr->src, &m->eid, 1);
4276 if ((u32) ~ 0 != m->ttl)
4277 mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60);
4281 /* remove pending map request entry */
4284 clib_fifo_foreach (noncep, pmr->nonces, ({
4285 hash_unset(lcm->pending_map_requests_by_nonce, noncep[0]);
4289 clib_fifo_free (pmr->nonces);
4290 pool_put (lcm->pending_map_requests_pool, pmr);
4293 map_records_arg_free (a);
4298 is_auth_data_valid (map_notify_hdr_t * h, u32 msg_len,
4299 lisp_key_type_t key_id, u8 * key)
4305 auth_data_len = auth_data_len_by_key_id (key_id);
4306 if ((u16) ~ 0 == auth_data_len)
4308 clib_warning ("invalid length for key_id %d!", key_id);
4312 /* save auth data */
4313 vec_validate (auth_data, auth_data_len - 1);
4314 clib_memcpy (auth_data, MNOTIFY_DATA (h), auth_data_len);
4316 /* clear auth data */
4317 memset (MNOTIFY_DATA (h), 0, auth_data_len);
4319 /* get hash of the message */
4320 unsigned char *code = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
4321 (unsigned char *) h, msg_len, NULL, NULL);
4323 result = memcmp (code, auth_data, auth_data_len);
4325 vec_free (auth_data);
4331 process_map_notify (map_records_arg_t * a)
4333 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4336 pmr_index = hash_get (lcm->map_register_messages_by_nonce, a->nonce);
4339 clib_warning ("No pending map-register entry with nonce %lu!",
4344 map_records_arg_free (a);
4345 hash_unset (lcm->map_register_messages_by_nonce, a->nonce);
4349 get_mapping (lisp_cp_main_t * lcm, gid_address_t * e)
4353 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, e);
4356 clib_warning ("eid %U not found in map-cache!", unformat_gid_address,
4360 return pool_elt_at_index (lcm->mapping_pool, mi);
4364 * When map-notify is received it is necessary that all EIDs in the record
4365 * list share common key. The key is then used to verify authentication
4366 * data in map-notify message.
4369 map_record_integrity_check (lisp_cp_main_t * lcm, mapping_t * maps,
4370 u32 key_id, u8 ** key_out)
4372 u32 i, len = vec_len (maps);
4375 /* get key of the first mapping */
4376 m = get_mapping (lcm, &maps[0].eid);
4380 key_out[0] = m->key;
4382 for (i = 1; i < len; i++)
4384 m = get_mapping (lcm, &maps[i].eid);
4388 if (key_id != m->key_id || vec_cmp (m->key, key_out[0]))
4390 clib_warning ("keys does not match! %v, %v", key_out[0], m->key);
4398 parse_map_records (vlib_buffer_t * b, map_records_arg_t * a, u8 count)
4400 locator_t *locators = 0;
4406 /* parse record eid */
4407 for (i = 0; i < count; i++)
4409 len = lisp_msg_parse_mapping_record (b, &deid, &locators, NULL);
4412 clib_warning ("Failed to parse mapping record!");
4413 vec_foreach (loc, locators) locator_free (loc);
4414 vec_free (locators);
4418 m.locators = locators;
4419 gid_address_copy (&m.eid, &deid);
4420 vec_add1 (a->mappings, m);
4426 static map_records_arg_t *
4427 parse_map_notify (vlib_buffer_t * b)
4430 map_notify_hdr_t *mnotif_hdr;
4431 lisp_key_type_t key_id;
4432 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4435 u16 auth_data_len = 0;
4437 map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
4439 memset (a, 0, sizeof (*a));
4440 mnotif_hdr = vlib_buffer_get_current (b);
4441 vlib_buffer_pull (b, sizeof (*mnotif_hdr));
4442 memset (&deid, 0, sizeof (deid));
4444 a->nonce = MNOTIFY_NONCE (mnotif_hdr);
4445 key_id = clib_net_to_host_u16 (MNOTIFY_KEY_ID (mnotif_hdr));
4446 auth_data_len = auth_data_len_by_key_id (key_id);
4448 /* advance buffer by authentication data */
4449 vlib_buffer_pull (b, auth_data_len);
4451 record_count = MNOTIFY_REC_COUNT (mnotif_hdr);
4452 rc = parse_map_records (b, a, record_count);
4455 map_records_arg_free (a);
4459 rc = map_record_integrity_check (lcm, a->mappings, key_id, &key);
4462 map_records_arg_free (a);
4466 /* verify authentication data */
4467 if (!is_auth_data_valid (mnotif_hdr, vlib_buffer_get_tail (b)
4468 - (u8 *) mnotif_hdr, key_id, key))
4470 clib_warning ("Map-notify auth data verification failed for nonce %lu!",
4472 map_records_arg_free (a);
4478 static vlib_buffer_t *
4479 build_map_reply (lisp_cp_main_t * lcm, ip_address_t * sloc,
4480 ip_address_t * dst, u64 nonce, u8 probe_bit,
4481 mapping_t * records, u16 dst_port, u32 * bi_res)
4485 vlib_main_t *vm = lcm->vlib_main;
4487 if (vlib_buffer_alloc (vm, &bi, 1) != 1)
4489 clib_warning ("Can't allocate buffer for Map-Register!");
4493 b = vlib_get_buffer (vm, bi);
4495 /* leave some space for the encap headers */
4496 vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
4498 lisp_msg_put_map_reply (b, records, nonce, probe_bit);
4500 /* push outer ip header */
4501 pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst);
4508 send_map_reply (lisp_cp_main_t * lcm, u32 mi, ip_address_t * dst,
4509 u8 probe_bit, u64 nonce, u16 dst_port,
4510 ip_address_t * probed_loc)
4516 u32 next_index, *to_next;
4517 mapping_t *records = 0, *m;
4519 m = pool_elt_at_index (lcm->mapping_pool, mi);
4523 vec_add1 (records, m[0]);
4524 add_locators (lcm, &records[0], m->locator_set_index, probed_loc);
4525 memset (&src, 0, sizeof (src));
4527 if (!ip_fib_get_first_egress_ip_for_dst (lcm, dst, &src))
4529 clib_warning ("can't find inteface address for %U", format_ip_address,
4534 b = build_map_reply (lcm, &src, dst, nonce, probe_bit, records, dst_port,
4538 free_map_register_records (records);
4540 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
4541 next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
4542 ip4_lookup_node.index : ip6_lookup_node.index;
4544 f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
4546 /* Enqueue the packet */
4547 to_next = vlib_frame_vector_args (f);
4550 vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
4555 find_ip_header (vlib_buffer_t * b, u8 ** ip_hdr)
4557 const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
4558 if (start < 0 && start < -sizeof (b->pre_data))
4564 *ip_hdr = b->data + start;
4565 if ((u8 *) * ip_hdr > (u8 *) vlib_buffer_get_current (b))
4570 process_map_request (vlib_main_t * vm, vlib_node_runtime_t * node,
4571 lisp_cp_main_t * lcm, vlib_buffer_t * b)
4574 ip_address_t *dst_loc = 0, probed_loc, src_loc;
4576 map_request_hdr_t *mreq_hdr;
4577 gid_address_t src, dst;
4579 u32 i, len = 0, rloc_probe_recv = 0;
4580 gid_address_t *itr_rlocs = 0;
4582 mreq_hdr = vlib_buffer_get_current (b);
4583 if (!MREQ_SMR (mreq_hdr) && !MREQ_RLOC_PROBE (mreq_hdr))
4586 ("Only SMR Map-Requests and RLOC probe supported for now!");
4590 vlib_buffer_pull (b, sizeof (*mreq_hdr));
4591 nonce = MREQ_NONCE (mreq_hdr);
4594 len = lisp_msg_parse_addr (b, &src);
4598 len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs,
4599 MREQ_ITR_RLOC_COUNT (mreq_hdr) + 1);
4603 /* parse eid records and send SMR-invoked map-requests */
4604 for (i = 0; i < MREQ_REC_COUNT (mreq_hdr); i++)
4606 memset (&dst, 0, sizeof (dst));
4607 len = lisp_msg_parse_eid_rec (b, &dst);
4610 clib_warning ("Can't parse map-request EID-record");
4614 if (MREQ_SMR (mreq_hdr))
4616 /* send SMR-invoked map-requests */
4617 queue_map_request (&dst, &src, 1 /* invoked */ , 0 /* resend */ );
4619 else if (MREQ_RLOC_PROBE (mreq_hdr))
4621 find_ip_header (b, &ip_hdr);
4624 clib_warning ("Cannot find the IP header!");
4628 memset (&m, 0, sizeof (m));
4629 u32 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
4631 // TODO: select best locator; for now use the first one
4632 dst_loc = &gid_address_ip (&itr_rlocs[0]);
4634 /* get src/dst IP addresses */
4635 get_src_and_dst_ip (ip_hdr, &src_loc, &probed_loc);
4637 // TODO get source port from buffer
4638 u16 src_port = LISP_CONTROL_PORT;
4640 send_map_reply (lcm, mi, dst_loc, 1 /* probe-bit */ , nonce,
4641 src_port, &probed_loc);
4646 vlib_node_increment_counter (vm, node->node_index,
4647 LISP_CP_INPUT_ERROR_RLOC_PROBE_REQ_RECEIVED,
4649 vec_free (itr_rlocs);
4652 static map_records_arg_t *
4653 parse_map_reply (vlib_buffer_t * b)
4660 map_reply_hdr_t *mrep_hdr;
4661 map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
4662 memset (a, 0, sizeof (*a));
4663 locator_t *locators;
4665 mrep_hdr = vlib_buffer_get_current (b);
4666 a->nonce = MREP_NONCE (mrep_hdr);
4667 a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr);
4668 vlib_buffer_pull (b, sizeof (*mrep_hdr));
4670 for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
4672 memset (&m, 0, sizeof (m));
4674 h = vlib_buffer_get_current (b);
4676 m.ttl = clib_net_to_host_u32 (MAP_REC_TTL (h));
4677 m.action = MAP_REC_ACTION (h);
4678 m.authoritative = MAP_REC_AUTH (h);
4680 len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
4683 clib_warning ("Failed to parse mapping record!");
4684 map_records_arg_free (a);
4688 m.locators = locators;
4689 gid_address_copy (&m.eid, &deid);
4690 vec_add1 (a->mappings, m);
4696 queue_map_reply_for_processing (map_records_arg_t * a)
4698 vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (*a));
4702 queue_map_notify_for_processing (map_records_arg_t * a)
4704 vl_api_rpc_call_main_thread (process_map_notify, (u8 *) a, sizeof (a[0]));
4708 lisp_cp_input (vlib_main_t * vm, vlib_node_runtime_t * node,
4709 vlib_frame_t * from_frame)
4711 u32 n_left_from, *from, *to_next_drop, rloc_probe_rep_recv = 0,
4712 map_notifies_recv = 0;
4713 lisp_msg_type_e type;
4714 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4715 map_records_arg_t *a;
4717 from = vlib_frame_vector_args (from_frame);
4718 n_left_from = from_frame->n_vectors;
4721 while (n_left_from > 0)
4723 u32 n_left_to_next_drop;
4725 vlib_get_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP,
4726 to_next_drop, n_left_to_next_drop);
4727 while (n_left_from > 0 && n_left_to_next_drop > 0)
4735 to_next_drop[0] = bi0;
4737 n_left_to_next_drop -= 1;
4739 b0 = vlib_get_buffer (vm, bi0);
4741 type = lisp_msg_type (vlib_buffer_get_current (b0));
4744 case LISP_MAP_REPLY:
4745 a = parse_map_reply (b0);
4748 if (a->is_rloc_probe)
4749 rloc_probe_rep_recv++;
4750 queue_map_reply_for_processing (a);
4753 case LISP_MAP_REQUEST:
4754 process_map_request (vm, node, lcm, b0);
4756 case LISP_MAP_NOTIFY:
4757 a = parse_map_notify (b0);
4760 map_notifies_recv++;
4761 queue_map_notify_for_processing (a);
4765 clib_warning ("Unsupported LISP message type %d", type);
4769 b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
4771 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
4777 vlib_put_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP,
4778 n_left_to_next_drop);
4780 vlib_node_increment_counter (vm, node->node_index,
4781 LISP_CP_INPUT_ERROR_RLOC_PROBE_REP_RECEIVED,
4782 rloc_probe_rep_recv);
4783 vlib_node_increment_counter (vm, node->node_index,
4784 LISP_CP_INPUT_ERROR_MAP_NOTIFIES_RECEIVED,
4786 return from_frame->n_vectors;
4790 VLIB_REGISTER_NODE (lisp_cp_input_node) = {
4791 .function = lisp_cp_input,
4792 .name = "lisp-cp-input",
4793 .vector_size = sizeof (u32),
4794 .format_trace = format_lisp_cp_input_trace,
4795 .type = VLIB_NODE_TYPE_INTERNAL,
4797 .n_errors = LISP_CP_INPUT_N_ERROR,
4798 .error_strings = lisp_cp_input_error_strings,
4800 .n_next_nodes = LISP_CP_INPUT_N_NEXT,
4803 [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
4809 lisp_cp_init (vlib_main_t * vm)
4811 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4812 clib_error_t *error = 0;
4814 if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
4817 lcm->im4 = &ip4_main;
4818 lcm->im6 = &ip6_main;
4819 lcm->vlib_main = vm;
4820 lcm->vnet_main = vnet_get_main ();
4821 lcm->mreq_itr_rlocs = ~0;
4823 memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver));
4825 gid_dictionary_init (&lcm->mapping_index_by_gid);
4826 lcm->do_map_resolver_election = 1;
4827 lcm->map_request_mode = MR_MODE_DST_ONLY;
4829 /* default vrf mapped to vni 0 */
4830 hash_set (lcm->table_id_by_vni, 0, 0);
4831 hash_set (lcm->vni_by_table_id, 0, 0);
4833 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
4834 lisp_cp_input_node.index, 1 /* is_ip4 */ );
4835 udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
4836 lisp_cp_input_node.index, 0 /* is_ip4 */ );
4838 u64 now = clib_cpu_time_now ();
4839 timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second);
4844 send_map_request_thread_fn (void *arg)
4846 map_request_args_t *a = arg;
4847 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4850 resend_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
4852 send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
4858 queue_map_request (gid_address_t * seid, gid_address_t * deid,
4859 u8 smr_invoked, u8 is_resend)
4861 map_request_args_t a;
4863 a.is_resend = is_resend;
4864 gid_address_copy (&a.seid, seid);
4865 gid_address_copy (&a.deid, deid);
4866 a.smr_invoked = smr_invoked;
4868 vl_api_rpc_call_main_thread (send_map_request_thread_fn,
4869 (u8 *) & a, sizeof (a));
4874 * Take an action with a pending map request depending on expiration time
4875 * and re-try counters.
4878 update_pending_request (pending_map_request_t * r, f64 dt)
4880 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4883 if (r->time_to_expire - dt < 0)
4884 /* it's time to decide what to do with this pending request */
4886 if (r->retries_num >= NUMBER_OF_RETRIES)
4887 /* too many retries -> assume current map resolver is not available */
4889 mr = get_map_resolver (&lcm->active_map_resolver);
4892 clib_warning ("Map resolver %U not found - probably deleted "
4893 "by the user recently.", format_ip_address,
4894 &lcm->active_map_resolver);
4898 clib_warning ("map resolver %U is unreachable, ignoring",
4899 format_ip_address, &lcm->active_map_resolver);
4901 /* mark current map resolver unavailable so it won't be
4902 * selected next time */
4904 mr->last_update = vlib_time_now (lcm->vlib_main);
4907 reset_pending_mr_counters (r);
4908 elect_map_resolver (lcm);
4910 /* try to find a next eligible map resolver and re-send */
4911 queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4917 queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4920 r->time_to_expire = PENDING_MREQ_EXPIRATION_TIME;
4924 r->time_to_expire -= dt;
4928 remove_dead_pending_map_requests (lisp_cp_main_t * lcm)
4931 pending_map_request_t *pmr;
4932 u32 *to_be_removed = 0, *pmr_index;
4935 pool_foreach (pmr, lcm->pending_map_requests_pool,
4937 if (pmr->to_be_removed)
4939 clib_fifo_foreach (nonce, pmr->nonces, ({
4940 hash_unset (lcm->pending_map_requests_by_nonce, nonce[0]);
4943 vec_add1 (to_be_removed, pmr - lcm->pending_map_requests_pool);
4948 vec_foreach (pmr_index, to_be_removed)
4949 pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]);
4951 vec_free (to_be_removed);
4955 update_rloc_probing (lisp_cp_main_t * lcm, f64 dt)
4957 static f64 time_left = RLOC_PROBING_INTERVAL;
4959 if (!lcm->is_enabled || !lcm->rloc_probing)
4965 time_left = RLOC_PROBING_INTERVAL;
4966 send_rloc_probes (lcm);
4971 update_map_register (lisp_cp_main_t * lcm, f64 dt)
4973 static f64 time_left = QUICK_MAP_REGISTER_INTERVAL;
4974 static u64 mreg_sent_counter = 0;
4976 if (!lcm->is_enabled || !lcm->map_registering)
4982 if (mreg_sent_counter >= QUICK_MAP_REGISTER_MSG_COUNT)
4983 time_left = MAP_REGISTER_INTERVAL;
4986 mreg_sent_counter++;
4987 time_left = QUICK_MAP_REGISTER_INTERVAL;
4989 send_map_register (lcm, 1 /* want map notify */ );
4994 send_map_resolver_service (vlib_main_t * vm,
4995 vlib_node_runtime_t * rt, vlib_frame_t * f)
4999 pending_map_request_t *pmr;
5000 lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5004 vlib_process_wait_for_event_or_clock (vm, period);
5006 /* currently no signals are expected - just wait for clock */
5007 (void) vlib_process_get_events (vm, 0);
5010 pool_foreach (pmr, lcm->pending_map_requests_pool,
5012 if (!pmr->to_be_removed)
5013 update_pending_request (pmr, period);
5017 remove_dead_pending_map_requests (lcm);
5019 update_map_register (lcm, period);
5020 update_rloc_probing (lcm, period);
5022 u64 now = clib_cpu_time_now ();
5024 expired = timing_wheel_advance (&lcm->wheel, now, expired, 0);
5025 if (vec_len (expired) > 0)
5028 vec_foreach (mi, expired)
5030 remove_expired_mapping (lcm, mi[0]);
5032 _vec_len (expired) = 0;
5041 VLIB_REGISTER_NODE (lisp_retry_service_node,static) = {
5042 .function = send_map_resolver_service,
5043 .type = VLIB_NODE_TYPE_PROCESS,
5044 .name = "lisp-retry-service",
5045 .process_log2_n_stack_bytes = 16,
5049 VLIB_INIT_FUNCTION (lisp_cp_init);
5052 * fd.io coding-style-patch-verification: ON
5055 * eval: (c-set-style "gnu")