FD.io VPP  v16.09
Vector Packet Processing
control.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 
16 #include <vlibmemory/api.h>
17 #include <vnet/lisp-cp/control.h>
18 #include <vnet/lisp-cp/packets.h>
20 #include <vnet/lisp-gpe/lisp_gpe.h>
21 
22 typedef struct
23 {
29 
30 static int
32  u8 smr_invoked, u8 is_resend);
33 
36  u32 sw_if_index, u8 loop)
37 {
38  vnet_main_t *vnm = vnet_get_main ();
39  vnet_sw_interface_t *swif = vnet_get_sw_interface (vnm, sw_if_index);
40  if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
41  sw_if_index = swif->unnumbered_sw_if_index;
42  u32 ia =
43  (vec_len ((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
44  vec_elt ((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
45  (u32) ~ 0;
46  return pool_elt_at_index ((lm)->if_address_pool, ia);
47 }
48 
49 void *
51  u8 version)
52 {
54 
55  ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
56  if (!ia)
57  return 0;
58  return ip_interface_address_get_address (lm, ia);
59 }
60 
61 int
63  u8 version, ip_address_t * result)
64 {
65  ip_lookup_main_t *lm;
66  void *addr;
67 
68  lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
69  addr = ip_interface_get_first_address (lm, sw_if_index, version);
70  if (!addr)
71  return 0;
72 
73  ip_address_set (result, addr, version);
74  return 1;
75 }
76 
77 static u32
79  ip_address_t * dst)
80 {
81  if (ip_addr_version (dst) == IP4)
82  return ip4_fib_lookup_with_table (lcm->im4, fib_index, &ip_addr_v4 (dst),
83  0);
84  else
85  return ip6_fib_lookup_with_table (lcm->im6, fib_index, &ip_addr_v6 (dst));
86 }
87 
88 u32
90  ip_address_t * dst,
91  ip_lookup_main_t * lm)
92 {
93  u32 adj_index;
94  ip_adjacency_t *adj;
95 
96  adj_index = ip_fib_lookup_with_table (lcm, 0, dst);
97  adj = ip_get_adjacency (lm, adj_index);
98 
99  if (adj == 0)
100  return ~0;
101 
102  /* we only want outgoing routes */
105  return ~0;
106 
107  return adj->rewrite_header.sw_if_index;
108 }
109 
110 /**
111  * Find the sw_if_index of the interface that would be used to egress towards
112  * dst.
113  */
114 u32
116 {
117  ip_lookup_main_t *lm;
118 
119  lm = ip_addr_version (dst) == IP4 ?
120  &lcm->im4->lookup_main : &lcm->im6->lookup_main;
121 
122  return ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
123 }
124 
125 /**
126  * Find first IP of the interface that would be used to egress towards dst.
127  * Returns 1 if the address is found 0 otherwise.
128  */
129 int
131  ip_address_t * result)
132 {
133  u32 si;
134  ip_lookup_main_t *lm;
135  void *addr = 0;
136  u8 ipver;
137 
138  ASSERT (result != 0);
139 
140  ipver = ip_addr_version (dst);
141 
142  lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
143  si = ip_fib_get_egress_iface_for_dst_with_lm (lcm, dst, lm);
144 
145  if ((u32) ~ 0 == si)
146  return 0;
147 
148  /* find the first ip address */
149  addr = ip_interface_get_first_address (lm, si, ipver);
150  if (0 == addr)
151  return 0;
152 
153  ip_address_set (result, addr, ipver);
154  return 1;
155 }
156 
157 static int
158 dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
159 {
160  uword *dp_table, *intf;
161  vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai;
162 
163  if (!is_l2)
164  {
165  dp_table = hash_get (lcm->table_id_by_vni, vni);
166 
167  if (!dp_table)
168  {
169  clib_warning ("vni %d not associated to a vrf!", vni);
170  return VNET_API_ERROR_INVALID_VALUE;
171  }
172  }
173  else
174  {
175  dp_table = hash_get (lcm->bd_id_by_vni, vni);
176  if (!dp_table)
177  {
178  clib_warning ("vni %d not associated to a bridge domain!", vni);
179  return VNET_API_ERROR_INVALID_VALUE;
180  }
181  }
182 
183  intf = hash_get (is_l2 ? lcm->l2_dp_intf_by_vni : lcm->dp_intf_by_vni, vni);
184 
185  /* enable/disable data-plane interface */
186  if (is_add)
187  {
188  /* create interface */
189  if (!intf)
190  {
191  ai->is_add = 1;
192  ai->vni = vni;
193  ai->is_l2 = is_l2;
194  ai->dp_table = dp_table[0];
195 
197 
198  /* keep track of vnis for which interfaces have been created */
199  hash_set (lcm->dp_intf_by_vni, vni, 1);
200  }
201  }
202  else
203  {
204  if (intf == 0)
205  {
206  clib_warning ("interface for vni %d doesn't exist!", vni);
207  return VNET_API_ERROR_INVALID_VALUE;
208  }
209 
210  ai->is_add = 0;
211  ai->vni = vni;
212  ai->dp_table = dp_table[0];
214  hash_unset (lcm->dp_intf_by_vni, vni);
215  }
216 
217  return 0;
218 }
219 
220 static void
221 dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
222 {
224  fwd_entry_t *fe = 0;
225  uword *feip = 0;
226  memset (a, 0, sizeof (*a));
227 
228  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
229  if (!feip)
230  return;
231 
232  fe = pool_elt_at_index (lcm->fwd_entry_pool, feip[0]);
233 
234  /* delete dp fwd entry */
235  u32 sw_if_index;
236  a->is_add = 0;
237  a->locator_pairs = fe->locator_pairs;
238  a->vni = gid_address_vni (&fe->deid);
239  gid_address_copy (&a->rmt_eid, &fe->deid);
240 
241  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
242 
243  /* delete entry in fwd table */
244  hash_unset (lcm->fwd_entry_by_mapping_index, dst_map_index);
245  vec_free (fe->locator_pairs);
246  pool_put (lcm->fwd_entry_pool, fe);
247 }
248 
249 /**
250  * Finds first remote locator with best (lowest) priority that has a local
251  * peer locator with an underlying route to it.
252  *
253  */
254 static u32
256  mapping_t * rmt_map, locator_pair_t ** locator_pairs)
257 {
258  u32 i, limitp = 0, li, found = 0, esi;
259  locator_set_t *rmt_ls, *lcl_ls;
260  ip_address_t _lcl_addr, *lcl_addr = &_lcl_addr;
261  locator_t *lp, *rmt = 0;
262  uword *checked = 0;
263  locator_pair_t pair;
264 
265  rmt_ls =
267  lcl_ls =
269 
270  if (!rmt_ls || vec_len (rmt_ls->locator_indices) == 0)
271  return 0;
272 
273  while (1)
274  {
275  rmt = 0;
276 
277  /* find unvisited remote locator with best priority */
278  for (i = 0; i < vec_len (rmt_ls->locator_indices); i++)
279  {
280  if (0 != hash_get (checked, i))
281  continue;
282 
283  li = vec_elt (rmt_ls->locator_indices, i);
284  lp = pool_elt_at_index (lcm->locator_pool, li);
285 
286  /* we don't support non-IP locators for now */
288  continue;
289 
290  if ((found && lp->priority == limitp)
291  || (!found && lp->priority >= limitp))
292  {
293  rmt = lp;
294 
295  /* don't search for locators with lower priority and don't
296  * check this locator again*/
297  limitp = lp->priority;
298  hash_set (checked, i, 1);
299  break;
300  }
301  }
302  /* check if a local locator with a route to remote locator exists */
303  if (rmt != 0)
304  {
305  /* find egress sw_if_index for rmt locator */
306  esi =
308  &gid_address_ip (&rmt->address));
309  if ((u32) ~ 0 == esi)
310  continue;
311 
312  for (i = 0; i < vec_len (lcl_ls->locator_indices); i++)
313  {
314  li = vec_elt (lcl_ls->locator_indices, i);
315  locator_t *sl = pool_elt_at_index (lcm->locator_pool, li);
316 
317  /* found local locator with the needed sw_if_index */
318  if (sl->sw_if_index == esi)
319  {
320  /* and it has an address */
321  if (0 == ip_interface_get_first_ip_address (lcm,
322  sl->sw_if_index,
324  (&rmt->address),
325  lcl_addr))
326  continue;
327 
328  memset (&pair, 0, sizeof (pair));
329  ip_address_copy (&pair.rmt_loc,
330  &gid_address_ip (&rmt->address));
331  ip_address_copy (&pair.lcl_loc, lcl_addr);
332  pair.weight = rmt->weight;
333  vec_add1 (locator_pairs[0], pair);
334  found = 1;
335  }
336  }
337  }
338  else
339  break;
340  }
341 
342  hash_free (checked);
343  return found;
344 }
345 
346 static void
347 dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
348 {
350  mapping_t *src_map, *dst_map;
351  u32 sw_if_index;
352  uword *feip = 0, *dpid;
353  fwd_entry_t *fe;
354  u8 type;
355 
356  memset (a, 0, sizeof (*a));
357 
358  /* remove entry if it already exists */
359  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
360  if (feip)
361  dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
362 
363  src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
364  dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
365 
366  /* insert data plane forwarding entry */
367  a->is_add = 1;
368 
369  gid_address_copy (&a->rmt_eid, &dst_map->eid);
370  a->vni = gid_address_vni (&a->rmt_eid);
371 
372  /* get vrf or bd_index associated to vni */
373  type = gid_address_type (&dst_map->eid);
374  if (GID_ADDR_IP_PREFIX == type)
375  {
376  dpid = hash_get (lcm->table_id_by_vni, a->vni);
377  if (!dpid)
378  {
379  clib_warning ("vni %d not associated to a vrf!", a->vni);
380  return;
381  }
382  a->table_id = dpid[0];
383  }
384  else if (GID_ADDR_MAC == type)
385  {
386  dpid = hash_get (lcm->bd_id_by_vni, a->vni);
387  if (!dpid)
388  {
389  clib_warning ("vni %d not associated to a bridge domain !", a->vni);
390  return;
391  }
392  a->bd_id = dpid[0];
393  }
394 
395  /* find best locator pair that 1) verifies LISP policy 2) are connected */
396  if (0 == get_locator_pairs (lcm, src_map, dst_map, &a->locator_pairs))
397  {
398  /* negative entry */
399  a->is_negative = 1;
400  a->action = dst_map->action;
401  }
402 
403  /* TODO remove */
405  a->decap_next_index = (ipver == IP4) ?
406  LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
407 
408  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
409 
410  /* add tunnel to fwd entry table XXX check return value from DP insertion */
411  pool_get (lcm->fwd_entry_pool, fe);
412  fe->locator_pairs = a->locator_pairs;
413  gid_address_copy (&fe->deid, &a->rmt_eid);
414  hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
415  fe - lcm->fwd_entry_pool);
416 }
417 
418 /**
419  * Add/remove mapping to/from map-cache. Overwriting not allowed.
420  */
421 int
423  u32 * map_index_result)
424 {
426  u32 mi, *map_indexp, map_index, i;
427  mapping_t *m, *old_map;
428  u32 **eid_indexes;
429 
431  old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
432  if (a->is_add)
433  {
434  /* TODO check if overwriting and take appropriate actions */
435  if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid, &a->eid))
436  {
437  clib_warning ("eid %U found in the eid-table", format_gid_address,
438  &a->eid);
439  return VNET_API_ERROR_VALUE_EXIST;
440  }
441 
442  pool_get (lcm->mapping_pool, m);
443  gid_address_copy (&m->eid, &a->eid);
445  m->ttl = a->ttl;
446  m->action = a->action;
447  m->local = a->local;
448  m->is_static = a->is_static;
449 
450  map_index = m - lcm->mapping_pool;
451  gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
452  1);
453 
455  {
456  clib_warning ("Locator set with index %d doesn't exist",
457  a->locator_set_index);
458  return VNET_API_ERROR_INVALID_VALUE;
459  }
460 
461  /* add eid to list of eids supported by locator-set */
463  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
464  a->locator_set_index);
465  vec_add1 (eid_indexes[0], map_index);
466 
467  if (a->local)
468  {
469  /* mark as local */
470  vec_add1 (lcm->local_mappings_indexes, map_index);
471  }
472  map_index_result[0] = map_index;
473  }
474  else
475  {
476  if (mi == GID_LOOKUP_MISS)
477  {
478  clib_warning ("eid %U not found in the eid-table",
479  format_gid_address, &a->eid);
480  return VNET_API_ERROR_INVALID_VALUE;
481  }
482 
483  /* clear locator-set to eids binding */
484  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
485  a->locator_set_index);
486  for (i = 0; i < vec_len (eid_indexes[0]); i++)
487  {
488  map_indexp = vec_elt_at_index (eid_indexes[0], i);
489  if (map_indexp[0] == mi)
490  break;
491  }
492  vec_del1 (eid_indexes[0], i);
493 
494  /* remove local mark if needed */
495  m = pool_elt_at_index (lcm->mapping_pool, mi);
496  if (m->local)
497  {
498  u32 k, *lm_indexp;
499  for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
500  {
501  lm_indexp = vec_elt_at_index (lcm->local_mappings_indexes, k);
502  if (lm_indexp[0] == mi)
503  break;
504  }
506  }
507 
508  /* remove mapping from dictionary */
510  gid_address_free (&m->eid);
511  pool_put_index (lcm->mapping_pool, mi);
512  }
513 
514  return 0;
515 }
516 
517 /**
518  * Add/update/delete mapping to/in/from map-cache.
519  */
520 int
522  u32 * map_index_result)
523 {
524  uword *dp_table = 0;
525  u32 vni;
526  u8 type;
527 
529 
531  {
532  clib_warning ("LISP is disabled!");
533  return VNET_API_ERROR_LISP_DISABLED;
534  }
535 
536  vni = gid_address_vni (&a->eid);
537  type = gid_address_type (&a->eid);
538  if (GID_ADDR_IP_PREFIX == type)
539  dp_table = hash_get (lcm->table_id_by_vni, vni);
540  else if (GID_ADDR_MAC == type)
541  dp_table = hash_get (lcm->bd_id_by_vni, vni);
542 
543  if (!dp_table)
544  {
545  clib_warning ("vni %d not associated to a %s!", vni,
546  GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
547  return VNET_API_ERROR_INVALID_VALUE;
548  }
549 
550  /* store/remove mapping from map-cache */
551  return vnet_lisp_map_cache_add_del (a, map_index_result);
552 }
553 
554 static clib_error_t *
556  vlib_cli_command_t * cmd)
557 {
559  unformat_input_t _line_input, *line_input = &_line_input;
560  u8 is_add = 1;
561  gid_address_t eid;
562  gid_address_t *eids = 0;
563  clib_error_t *error = 0;
564  u8 *locator_set_name = 0;
565  u32 locator_set_index = 0, map_index = 0;
566  uword *p;
568  int rv = 0;
569  u32 vni = 0;
570 
571  memset (&eid, 0, sizeof (eid));
572  memset (a, 0, sizeof (*a));
573 
574  /* Get a line of input. */
575  if (!unformat_user (input, unformat_line_input, line_input))
576  return 0;
577 
578  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
579  {
580  if (unformat (line_input, "add"))
581  is_add = 1;
582  else if (unformat (line_input, "del"))
583  is_add = 0;
584  else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
585  ;
586  else if (unformat (line_input, "vni %d", &vni))
587  gid_address_vni (&eid) = vni;
588  else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
589  {
590  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
591  if (!p)
592  {
593  error = clib_error_return (0, "locator-set %s doesn't exist",
594  locator_set_name);
595  goto done;
596  }
597  locator_set_index = p[0];
598  }
599  else
600  {
601  error = unformat_parse_error (line_input);
602  goto done;
603  }
604  }
605  /* XXX treat batch configuration */
606 
607  if (GID_ADDR_SRC_DST == gid_address_type (&eid))
608  {
609  error =
610  clib_error_return (0, "src/dst is not supported for local EIDs!");
611  goto done;
612  }
613 
614  gid_address_copy (&a->eid, &eid);
615  a->is_add = is_add;
616  a->locator_set_index = locator_set_index;
617  a->local = 1;
618 
619  rv = vnet_lisp_add_del_local_mapping (a, &map_index);
620  if (0 != rv)
621  {
622  error = clib_error_return (0, "failed to %s local mapping!",
623  is_add ? "add" : "delete");
624  }
625 done:
626  vec_free (eids);
627  if (locator_set_name)
628  vec_free (locator_set_name);
629  gid_address_free (&a->eid);
630  return error;
631 }
632 
633 /* *INDENT-OFF* */
634 VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
635  .path = "lisp eid-table",
636  .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
637  "locator-set <locator-set>",
639 };
640 /* *INDENT-ON* */
641 
642 int
643 vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
644 {
646  uword *dp_idp, *vnip, **dp_table_by_vni, **vni_by_dp_table;
647 
649  {
650  clib_warning ("LISP is disabled!");
651  return -1;
652  }
653 
654  dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
655  vni_by_dp_table = is_l2 ? &lcm->vni_by_bd_id : &lcm->vni_by_table_id;
656 
657  if (!is_l2 && (vni == 0 || dp_id == 0))
658  {
659  clib_warning ("can't add/del default vni-vrf mapping!");
660  return -1;
661  }
662 
663  dp_idp = hash_get (dp_table_by_vni[0], vni);
664  vnip = hash_get (vni_by_dp_table[0], dp_id);
665 
666  if (is_add)
667  {
668  if (dp_idp || vnip)
669  {
670  clib_warning ("vni %d or vrf %d already used in vrf/vni "
671  "mapping!", vni, dp_id);
672  return -1;
673  }
674  hash_set (dp_table_by_vni[0], vni, dp_id);
675  hash_set (vni_by_dp_table[0], dp_id, vni);
676 
677  /* create dp iface */
678  dp_add_del_iface (lcm, vni, is_l2, 1);
679  }
680  else
681  {
682  if (!dp_idp || !vnip)
683  {
684  clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
685  "mapping!", vni, dp_id);
686  return -1;
687  }
688  hash_unset (dp_table_by_vni[0], vni);
689  hash_unset (vni_by_dp_table[0], dp_id);
690 
691  /* remove dp iface */
692  dp_add_del_iface (lcm, vni, is_l2, 0);
693  }
694  return 0;
695 
696 }
697 
698 static clib_error_t *
700  unformat_input_t * input,
701  vlib_cli_command_t * cmd)
702 {
703  u8 is_add = 1, is_l2 = 0;
704  u32 vni = 0, dp_id = 0;
705  unformat_input_t _line_input, *line_input = &_line_input;
706 
707  /* Get a line of input. */
708  if (!unformat_user (input, unformat_line_input, line_input))
709  return 0;
710 
711  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
712  {
713  if (unformat (line_input, "del"))
714  is_add = 0;
715  else if (unformat (line_input, "vni %d", &vni))
716  ;
717  else if (unformat (line_input, "vrf %d", &dp_id))
718  ;
719  else if (unformat (line_input, "bd %d", &dp_id))
720  is_l2 = 1;
721  else
722  {
723  return unformat_parse_error (line_input);
724  }
725  }
726  vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
727  return 0;
728 }
729 
730 /* *INDENT-OFF* */
731 VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
732  .path = "lisp eid-table map",
733  .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
734  .function = lisp_eid_table_map_command_fn,
735 };
736 /* *INDENT-ON* */
737 
738 /* return 0 if the two locator sets are identical 1 otherwise */
739 static u8
740 compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes,
741  locator_t * new_locators)
742 {
743  u32 i, old_li;
744  locator_t *old_loc, *new_loc;
745 
746  if (vec_len (old_ls_indexes) != vec_len (new_locators))
747  return 1;
748 
749  for (i = 0; i < vec_len (new_locators); i++)
750  {
751  old_li = vec_elt (old_ls_indexes, i);
752  old_loc = pool_elt_at_index (lcm->locator_pool, old_li);
753 
754  new_loc = vec_elt_at_index (new_locators, i);
755 
756  if (locator_cmp (old_loc, new_loc))
757  return 1;
758  }
759  return 0;
760 }
761 
762 /**
763  * Adds/removes/updates mapping. Does not program forwarding.
764  *
765  * @param eid end-host identifier
766  * @param rlocs vector of remote locators
767  * @param action action for negative map-reply
768  * @param is_add add mapping if non-zero, delete otherwise
769  * @param res_map_index the map-index that was created/updated/removed. It is
770  * set to ~0 if no action is taken.
771  * @param is_static used for distinguishing between statically learned
772  remote mappings and mappings obtained from MR
773  * @return return code
774  */
775 int
777  u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
778  u32 * res_map_index)
779 {
780  vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
781  vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
783  u32 mi, ls_index = 0, dst_map_index;
784  mapping_t *old_map;
785 
787  {
788  clib_warning ("LISP is disabled!");
789  return VNET_API_ERROR_LISP_DISABLED;
790  }
791 
792  if (res_map_index)
793  res_map_index[0] = ~0;
794 
795  memset (m_args, 0, sizeof (m_args[0]));
796  memset (ls_args, 0, sizeof (ls_args[0]));
797 
798  ls_args->locators = rlocs;
799 
801  old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
802 
803  if (is_add)
804  {
805  /* overwrite: if mapping already exists, decide if locators should be
806  * updated and be done */
807  if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
808  {
809  if (!is_static && (old_map->is_static || old_map->local))
810  {
811  /* do not overwrite local or static remote mappings */
812  clib_warning ("mapping %U rejected due to collision with local "
813  "or static remote mapping!", format_gid_address,
814  &eid);
815  return 0;
816  }
817 
818  locator_set_t *old_ls;
819 
820  /* update mapping attributes */
821  old_map->action = action;
822  old_map->authoritative = authoritative;
823  old_map->ttl = ttl;
824 
825  old_ls = pool_elt_at_index (lcm->locator_set_pool,
826  old_map->locator_set_index);
827  if (compare_locators (lcm, old_ls->locator_indices,
828  ls_args->locators))
829  {
830  /* set locator-set index to overwrite */
831  ls_args->is_add = 1;
832  ls_args->index = old_map->locator_set_index;
833  vnet_lisp_add_del_locator_set (ls_args, 0);
834  if (res_map_index)
835  res_map_index[0] = mi;
836  }
837  }
838  /* new mapping */
839  else
840  {
841  ls_args->is_add = 1;
842  ls_args->index = ~0;
843 
844  vnet_lisp_add_del_locator_set (ls_args, &ls_index);
845 
846  /* add mapping */
847  gid_address_copy (&m_args->eid, eid);
848  m_args->is_add = 1;
849  m_args->action = action;
850  m_args->locator_set_index = ls_index;
851  m_args->is_static = is_static;
852  vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
853 
854  if (res_map_index)
855  res_map_index[0] = dst_map_index;
856  }
857  }
858  else
859  {
860  if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
861  {
862  clib_warning ("cannot delete mapping for eid %U",
863  format_gid_address, eid);
864  return -1;
865  }
866 
867  m_args->is_add = 0;
868  gid_address_copy (&m_args->eid, eid);
869  m_args->locator_set_index = old_map->locator_set_index;
870 
871  /* delete mapping associated from map-cache */
872  vnet_lisp_map_cache_add_del (m_args, 0);
873 
874  ls_args->is_add = 0;
875  ls_args->index = old_map->locator_set_index;
876  /* delete locator set */
877  vnet_lisp_add_del_locator_set (ls_args, 0);
878 
879  /* return old mapping index */
880  if (res_map_index)
881  res_map_index[0] = mi;
882  }
883 
884  /* success */
885  return 0;
886 }
887 
888 int
890 {
891  int rv = 0;
892  u32 mi, *map_indices = 0, *map_indexp;
894  vnet_lisp_add_del_mapping_args_t _dm_args, *dm_args = &_dm_args;
895  vnet_lisp_add_del_locator_set_args_t _ls, *ls = &_ls;
896 
897  /* *INDENT-OFF* */
899  ({
900  vec_add1 (map_indices, mi);
901  }));
902  /* *INDENT-ON* */
903 
904  vec_foreach (map_indexp, map_indices)
905  {
906  mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
907  if (!map->local)
908  {
909  dp_del_fwd_entry (lcm, 0, map_indexp[0]);
910 
911  dm_args->is_add = 0;
912  gid_address_copy (&dm_args->eid, &map->eid);
913  dm_args->locator_set_index = map->locator_set_index;
914 
915  /* delete mapping associated to fwd entry */
916  vnet_lisp_map_cache_add_del (dm_args, 0);
917 
918  ls->is_add = 0;
919  ls->local = 0;
920  ls->index = map->locator_set_index;
921  /* delete locator set */
922  rv = vnet_lisp_add_del_locator_set (ls, 0);
923  if (rv != 0)
924  goto cleanup;
925  }
926  }
927 
928 cleanup:
929  if (map_indices)
930  vec_free (map_indices);
931  return rv;
932 }
933 
934 /**
935  * Adds adjacency or removes forwarding entry associated to remote mapping.
936  * Note that adjacencies are not stored, they only result in forwarding entries
937  * being created.
938  */
939 int
941  gid_address_t * remote_eid, u8 is_add)
942 {
943  u32 local_mi, remote_mi = ~0;
944 
946  {
947  clib_warning ("LISP is disabled!");
948  return VNET_API_ERROR_LISP_DISABLED;
949  }
950 
951  remote_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, remote_eid);
952  if (GID_LOOKUP_MISS == remote_mi)
953  {
954  clib_warning ("Remote eid %U not found. Cannot add adjacency!",
955  format_gid_address, remote_eid);
956 
957  return -1;
958  }
959 
960  if (is_add)
961  {
962  /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
963  * delete*/
964 
965  /* check if source eid has an associated mapping. If pitr mode is on,
966  * just use the pitr's mapping */
967  local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
968  gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
969 
970 
971  if (GID_LOOKUP_MISS == local_mi)
972  {
973  clib_warning ("Local eid %U not found. Cannot add adjacency!",
974  format_gid_address, local_eid);
975 
976  return -1;
977  }
978 
979  /* update forwarding */
980  dp_add_fwd_entry (lcm, local_mi, remote_mi);
981  }
982  else
983  dp_del_fwd_entry (lcm, 0, remote_mi);
984 
985  return 0;
986 }
987 
988 int
990 {
992  return lisp_add_del_adjacency (lcm, &a->seid, &a->deid, a->is_add);
993 }
994 
995 /**
996  * Handler for add/del remote mapping CLI.
997  *
998  * @param vm vlib context
999  * @param input input from user
1000  * @param cmd cmd
1001  * @return pointer to clib error structure
1002  */
1003 static clib_error_t *
1005  unformat_input_t * input,
1006  vlib_cli_command_t * cmd)
1007 {
1008  clib_error_t *error = 0;
1009  unformat_input_t _line_input, *line_input = &_line_input;
1010  u8 is_add = 1, del_all = 0;
1011  locator_t rloc, *rlocs = 0, *curr_rloc = 0;
1012  gid_address_t eid;
1013  u8 eid_set = 0;
1014  u32 vni, action = ~0, p, w;
1015  int rv;
1016 
1017  /* Get a line of input. */
1018  if (!unformat_user (input, unformat_line_input, line_input))
1019  return 0;
1020 
1021  memset (&eid, 0, sizeof (eid));
1022  memset (&rloc, 0, sizeof (rloc));
1023 
1024  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1025  {
1026  if (unformat (line_input, "del-all"))
1027  del_all = 1;
1028  else if (unformat (line_input, "del"))
1029  is_add = 0;
1030  else if (unformat (line_input, "add"))
1031  ;
1032  else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1033  eid_set = 1;
1034  else if (unformat (line_input, "vni %u", &vni))
1035  {
1036  gid_address_vni (&eid) = vni;
1037  }
1038  else if (unformat (line_input, "p %d w %d", &p, &w))
1039  {
1040  if (!curr_rloc)
1041  {
1042  clib_warning
1043  ("No RLOC configured for setting priority/weight!");
1044  goto done;
1045  }
1046  curr_rloc->priority = p;
1047  curr_rloc->weight = w;
1048  }
1049  else if (unformat (line_input, "rloc %U", unformat_ip_address,
1050  &gid_address_ip (&rloc.address)))
1051  {
1052  vec_add1 (rlocs, rloc);
1053  curr_rloc = &rlocs[vec_len (rlocs) - 1];
1054  }
1055  else if (unformat (line_input, "action %U",
1057  ;
1058  else
1059  {
1060  clib_warning ("parse error");
1061  goto done;
1062  }
1063  }
1064 
1065  if (!eid_set)
1066  {
1067  clib_warning ("missing eid!");
1068  goto done;
1069  }
1070 
1071  if (!del_all)
1072  {
1073  if (is_add && (~0 == action) && 0 == vec_len (rlocs))
1074  {
1075  clib_warning ("no action set for negative map-reply!");
1076  goto done;
1077  }
1078  }
1079  else
1080  {
1082  goto done;
1083  }
1084 
1085  /* TODO build src/dst with seid */
1086 
1087  /* if it's a delete, clean forwarding */
1088  if (!is_add)
1089  {
1091  rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0);
1092  if (rv)
1093  {
1094  goto done;
1095  }
1096  }
1097 
1098  /* add as static remote mapping, i.e., not authoritative and infinite
1099  * ttl */
1100  rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
1101  1 /* is_static */ , 0);
1102 
1103  if (rv)
1104  clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
1105 
1106 done:
1107  vec_free (rlocs);
1108  unformat_free (line_input);
1109  return error;
1110 }
1111 
1112 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) =
1113 {
1114 .path = "lisp remote-mapping",.short_help =
1115  "lisp remote-mapping add|del [del-all] vni <vni> "
1116  "eid <est-eid> [action <no-action|natively-forward|"
1117  "send-map-request|drop>] rloc <dst-locator> p <prio> w <weight> "
1118  "[rloc <dst-locator> ... ]",.function =
1120 
1121 /**
1122  * Handler for add/del adjacency CLI.
1123  */
1124 static clib_error_t *
1126  vlib_cli_command_t * cmd)
1127 {
1128  clib_error_t *error = 0;
1129  unformat_input_t _line_input, *line_input = &_line_input;
1131  u8 is_add = 1;
1132  locator_t rloc, *rlocs = 0;
1133  ip_prefix_t *deid_ippref, *seid_ippref;
1134  gid_address_t seid, deid;
1135  u8 *dmac = gid_address_mac (&deid);
1136  u8 *smac = gid_address_mac (&seid);
1137  u8 deid_set = 0, seid_set = 0;
1138  u8 *s = 0;
1139  u32 vni, action = ~0;
1140  int rv;
1141 
1142  /* Get a line of input. */
1143  if (!unformat_user (input, unformat_line_input, line_input))
1144  return 0;
1145 
1146  memset (&deid, 0, sizeof (deid));
1147  memset (&seid, 0, sizeof (seid));
1148  memset (&rloc, 0, sizeof (rloc));
1149 
1150  seid_ippref = &gid_address_ippref (&seid);
1151  deid_ippref = &gid_address_ippref (&deid);
1152 
1153  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1154  {
1155  if (unformat (line_input, "del"))
1156  is_add = 0;
1157  else if (unformat (line_input, "add"))
1158  ;
1159  else if (unformat (line_input, "deid %U",
1160  unformat_ip_prefix, deid_ippref))
1161  {
1163  deid_set = 1;
1164  }
1165  else if (unformat (line_input, "deid %U", unformat_mac_address, dmac))
1166  {
1167  gid_address_type (&deid) = GID_ADDR_MAC;
1168  deid_set = 1;
1169  }
1170  else if (unformat (line_input, "vni %u", &vni))
1171  {
1172  gid_address_vni (&seid) = vni;
1173  gid_address_vni (&deid) = vni;
1174  }
1175  else if (unformat (line_input, "seid %U",
1176  unformat_ip_prefix, seid_ippref))
1177  {
1179  seid_set = 1;
1180  }
1181  else if (unformat (line_input, "seid %U", unformat_mac_address, smac))
1182  {
1183  gid_address_type (&seid) = GID_ADDR_MAC;
1184  seid_set = 1;
1185  }
1186  else
1187  {
1188  clib_warning ("parse error");
1189  goto done;
1190  }
1191  }
1192 
1193  if (!deid_set)
1194  {
1195  clib_warning ("missing deid!");
1196  goto done;
1197  }
1198 
1199  if (GID_ADDR_IP_PREFIX == gid_address_type (&deid))
1200  {
1201  /* if seid not set, make sure the ip version is the same as that
1202  * of the deid. This ensures the seid to be configured will be
1203  * either 0/0 or ::/0 */
1204  if (!seid_set)
1205  ip_prefix_version (seid_ippref) = ip_prefix_version (deid_ippref);
1206 
1207  if (is_add &&
1208  (ip_prefix_version (deid_ippref)
1209  != ip_prefix_version (seid_ippref)))
1210  {
1211  clib_warning ("source and destination EIDs are not"
1212  " in the same IP family!");
1213  goto done;
1214  }
1215  }
1216 
1217  if (is_add && (~0 == action) && 0 == vec_len (rlocs))
1218  {
1219  clib_warning ("no action set for negative map-reply!");
1220  goto done;
1221  }
1222 
1223  memset (a, 0, sizeof (a[0]));
1224  gid_address_copy (&a->seid, &deid);
1225  gid_address_copy (&a->deid, &seid);
1226 
1227  a->is_add = is_add;
1228  rv = vnet_lisp_add_del_adjacency (a);
1229 
1230  if (rv)
1231  clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete");
1232 
1233 done:
1234  unformat_free (line_input);
1235  if (s)
1236  vec_free (s);
1237  return error;
1238 }
1239 
1240 /* *INDENT-OFF* */
1241 VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
1242  .path = "lisp adjacency",
1243  .short_help = "lisp adjacency add|del vni <vni>"
1244  "deid <dest-eid> seid <src-eid> [action <no-action|natively-forward|"
1245  "send-map-request|drop>] rloc <dst-locator> [rloc <dst-locator> ... ]",
1247 };
1248 /* *INDENT-ON* */
1249 
1250 static clib_error_t *
1252  unformat_input_t * input,
1253  vlib_cli_command_t * cmd)
1254 {
1255  map_resolver_t *mr;
1257 
1258  vec_foreach (mr, lcm->map_resolvers)
1259  {
1260  vlib_cli_output (vm, "%U", format_ip_address, &mr->address);
1261  }
1262  return 0;
1263 }
1264 
1265 /* *INDENT-OFF* */
1266 VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
1267  .path = "show lisp map-resolvers",
1268  .short_help = "show lisp map-resolvers",
1270 };
1271 /* *INDENT-ON* */
1272 
1273 int
1274 vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
1275 {
1277  u32 locator_set_index = ~0;
1278  mapping_t *m;
1279  uword *p;
1280 
1281  if (vnet_lisp_enable_disable_status () == 0)
1282  {
1283  clib_warning ("LISP is disabled!");
1284  return VNET_API_ERROR_LISP_DISABLED;
1285  }
1286 
1287  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1288  if (!p)
1289  {
1290  clib_warning ("locator-set %v doesn't exist", locator_set_name);
1291  return -1;
1292  }
1293  locator_set_index = p[0];
1294 
1295  if (is_add)
1296  {
1297  pool_get (lcm->mapping_pool, m);
1298  m->locator_set_index = locator_set_index;
1299  m->local = 1;
1300  lcm->pitr_map_index = m - lcm->mapping_pool;
1301 
1302  /* enable pitr mode */
1303  lcm->lisp_pitr = 1;
1304  }
1305  else
1306  {
1307  /* remove pitr mapping */
1309 
1310  /* disable pitr mode */
1311  lcm->lisp_pitr = 0;
1312  }
1313  return 0;
1314 }
1315 
1316 static clib_error_t *
1318  unformat_input_t * input,
1319  vlib_cli_command_t * cmd)
1320 {
1321  u8 locator_name_set = 0;
1322  u8 *locator_set_name = 0;
1323  u8 is_add = 1;
1324  unformat_input_t _line_input, *line_input = &_line_input;
1325  clib_error_t *error = 0;
1326  int rv = 0;
1327 
1328  /* Get a line of input. */
1329  if (!unformat_user (input, unformat_line_input, line_input))
1330  return 0;
1331 
1332  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1333  {
1334  if (unformat (line_input, "ls %_%v%_", &locator_set_name))
1335  locator_name_set = 1;
1336  else if (unformat (line_input, "disable"))
1337  is_add = 0;
1338  else
1339  return clib_error_return (0, "parse error");
1340  }
1341 
1342  if (!locator_name_set)
1343  {
1344  clib_warning ("No locator set specified!");
1345  goto done;
1346  }
1347  rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
1348  if (0 != rv)
1349  {
1350  error = clib_error_return (0, "failed to %s pitr!",
1351  is_add ? "add" : "delete");
1352  }
1353 
1354 done:
1355  if (locator_set_name)
1356  vec_free (locator_set_name);
1357  return error;
1358 }
1359 
1360 /* *INDENT-OFF* */
1361 VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
1362  .path = "lisp pitr",
1363  .short_help = "lisp pitr [disable] ls <locator-set-name>",
1365 };
1366 /* *INDENT-ON* */
1367 
1368 static clib_error_t *
1370  unformat_input_t * input, vlib_cli_command_t * cmd)
1371 {
1373  mapping_t *m;
1374  locator_set_t *ls;
1375  u8 *tmp_str = 0;
1376 
1377  vlib_cli_output (vm, "%=20s%=16s",
1378  "pitr", lcm->lisp_pitr ? "locator-set" : "");
1379 
1380  if (!lcm->lisp_pitr)
1381  {
1382  vlib_cli_output (vm, "%=20s", "disable");
1383  return 0;
1384  }
1385 
1386  if (~0 == lcm->pitr_map_index)
1387  {
1388  tmp_str = format (0, "N/A");
1389  }
1390  else
1391  {
1393  if (~0 != m->locator_set_index)
1394  {
1395  ls =
1397  tmp_str = format (0, "%s", ls->name);
1398  }
1399  else
1400  {
1401  tmp_str = format (0, "N/A");
1402  }
1403  }
1404  vec_add1 (tmp_str, 0);
1405 
1406  vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
1407 
1408  vec_free (tmp_str);
1409 
1410  return 0;
1411 }
1412 
1413 /* *INDENT-OFF* */
1414 VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
1415  .path = "show lisp pitr",
1416  .short_help = "Show pitr",
1417  .function = lisp_show_pitr_command_fn,
1418 };
1419 /* *INDENT-ON* */
1420 
1421 static u8 *
1422 format_eid_entry (u8 * s, va_list * args)
1423 {
1424  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
1425  lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *);
1426  mapping_t *mapit = va_arg (*args, mapping_t *);
1427  locator_set_t *ls = va_arg (*args, locator_set_t *);
1428  gid_address_t *gid = &mapit->eid;
1429  u32 ttl = mapit->ttl;
1430  u8 aut = mapit->authoritative;
1431  u32 *loc_index;
1432  u8 first_line = 1;
1433  u8 *loc;
1434 
1435  u8 *type = ls->local ? format (0, "local(%s)", ls->name)
1436  : format (0, "remote");
1437 
1438  if (vec_len (ls->locator_indices) == 0)
1439  {
1440  s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
1441  type, ttl, aut);
1442  }
1443  else
1444  {
1445  vec_foreach (loc_index, ls->locator_indices)
1446  {
1447  locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
1448  if (l->local)
1449  loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
1450  l->sw_if_index);
1451  else
1452  loc = format (0, "%U", format_ip_address,
1453  &gid_address_ip (&l->address));
1454 
1455  if (first_line)
1456  {
1457  s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
1458  gid, type, loc, ttl, aut);
1459  first_line = 0;
1460  }
1461  else
1462  s = format (s, "%55s%v\n", "", loc);
1463  }
1464  }
1465  return s;
1466 }
1467 
1468 static clib_error_t *
1470  unformat_input_t * input,
1471  vlib_cli_command_t * cmd)
1472 {
1474  mapping_t *mapit;
1475  unformat_input_t _line_input, *line_input = &_line_input;
1476  u32 mi;
1477  gid_address_t eid;
1478  u8 print_all = 1;
1479  u8 filter = 0;
1480 
1481  memset (&eid, 0, sizeof (eid));
1482 
1483  /* Get a line of input. */
1484  if (!unformat_user (input, unformat_line_input, line_input))
1485  return 0;
1486 
1487  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1488  {
1489  if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1490  print_all = 0;
1491  else if (unformat (line_input, "local"))
1492  filter = 1;
1493  else if (unformat (line_input, "remote"))
1494  filter = 2;
1495  else
1496  return clib_error_return (0, "parse error: '%U'",
1497  format_unformat_error, line_input);
1498  }
1499 
1500  vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
1501  "EID", "type", "locators", "ttl", "autoritative");
1502 
1503  if (print_all)
1504  {
1505  /* *INDENT-OFF* */
1506  pool_foreach (mapit, lcm->mapping_pool,
1507  ({
1508  locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
1509  mapit->locator_set_index);
1510  if (filter && !((1 == filter && ls->local) ||
1511  (2 == filter && !ls->local)))
1512  {
1513  continue;
1514  }
1515  vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
1516  lcm, mapit, ls);
1517  }));
1518  /* *INDENT-ON* */
1519  }
1520  else
1521  {
1522  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
1523  if ((u32) ~ 0 == mi)
1524  return 0;
1525 
1526  mapit = pool_elt_at_index (lcm->mapping_pool, mi);
1527  locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
1528  mapit->locator_set_index);
1529 
1530  if (filter && !((1 == filter && ls->local) ||
1531  (2 == filter && !ls->local)))
1532  {
1533  return 0;
1534  }
1535 
1536  vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
1537  lcm, mapit, ls);
1538  }
1539 
1540  return 0;
1541 }
1542 
1543 /* *INDENT-OFF* */
1544 VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = {
1545  .path = "show lisp eid-table",
1546  .short_help = "Shows EID table",
1547  .function = lisp_show_eid_table_command_fn,
1548 };
1549 /* *INDENT-ON* */
1550 
1551 /* cleans locator to locator-set data and removes locators not part of
1552  * any locator-set */
1553 static void
1555 {
1556  u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0;
1558  for (i = 0; i < vec_len (ls->locator_indices); i++)
1559  {
1560  loc_indexp = vec_elt_at_index (ls->locator_indices, i);
1561  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
1562  loc_indexp[0]);
1563  for (j = 0; j < vec_len (ls_indexes[0]); j++)
1564  {
1565  ls_indexp = vec_elt_at_index (ls_indexes[0], j);
1566  if (ls_indexp[0] == lsi)
1567  break;
1568  }
1569 
1570  /* delete index for removed locator-set */
1571  vec_del1 (ls_indexes[0], j);
1572 
1573  /* delete locator if it's part of no locator-set */
1574  if (vec_len (ls_indexes[0]) == 0)
1575  {
1576  pool_put_index (lcm->locator_pool, loc_indexp[0]);
1577  vec_add1 (to_be_deleted, i);
1578  }
1579  }
1580 
1581  if (to_be_deleted)
1582  {
1583  for (i = 0; i < vec_len (to_be_deleted); i++)
1584  {
1585  loc_indexp = vec_elt_at_index (to_be_deleted, i);
1586  vec_del1 (ls->locator_indices, loc_indexp[0]);
1587  }
1588  vec_free (to_be_deleted);
1589  }
1590 }
1591 
1592 static inline uword *
1594 {
1596 
1597  ASSERT (a != NULL);
1598  ASSERT (p != NULL);
1599 
1600  /* find locator-set */
1601  if (a->local)
1602  {
1604  }
1605  else
1606  {
1607  *p = a->index;
1608  }
1609 
1610  return p;
1611 }
1612 
1613 static inline int
1615  locator_t * loc)
1616 {
1617  locator_t *itloc;
1618  u32 *locit;
1619 
1620  ASSERT (ls != NULL);
1621  ASSERT (loc != NULL);
1622 
1623  vec_foreach (locit, ls->locator_indices)
1624  {
1625  itloc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1626  if ((ls->local && itloc->sw_if_index == loc->sw_if_index) ||
1627  (!ls->local && !gid_address_cmp (&itloc->address, &loc->address)))
1628  {
1629  clib_warning ("Duplicate locator");
1630  return VNET_API_ERROR_VALUE_EXIST;
1631  }
1632  }
1633 
1634  return 0;
1635 }
1636 
1637 static inline void
1639  u32 ls_index, u32 loc_id)
1640 {
1642  u32 **ls_indexes = NULL;
1643 
1644  ASSERT (ls != NULL);
1645  ASSERT (locit != NULL);
1646 
1647  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, locit[0]);
1648  pool_put_index (lcm->locator_pool, locit[0]);
1649  vec_del1 (ls->locator_indices, loc_id);
1650  vec_del1 (ls_indexes[0], ls_index);
1651 }
1652 
1653 int
1655  locator_set_t * ls, u32 * ls_result)
1656 {
1658  locator_t *loc = NULL, *itloc = NULL;
1659  uword _p = (u32) ~ 0, *p = &_p;
1660  u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL;
1661  u32 loc_id = ~0;
1662  int ret = 0;
1663 
1664  ASSERT (a != NULL);
1665 
1666  if (vnet_lisp_enable_disable_status () == 0)
1667  {
1668  clib_warning ("LISP is disabled!");
1669  return VNET_API_ERROR_LISP_DISABLED;
1670  }
1671 
1672  p = get_locator_set_index (a, p);
1673  if (!p)
1674  {
1675  clib_warning ("locator-set %v doesn't exist", a->name);
1676  return VNET_API_ERROR_INVALID_ARGUMENT;
1677  }
1678 
1679  if (ls == 0)
1680  {
1681  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1682  if (!ls)
1683  {
1684  clib_warning ("locator-set %d to be overwritten doesn't exist!",
1685  p[0]);
1686  return VNET_API_ERROR_INVALID_ARGUMENT;
1687  }
1688  }
1689 
1690  if (a->is_add)
1691  {
1692  if (ls_result)
1693  ls_result[0] = p[0];
1694 
1695  /* allocate locators */
1696  vec_foreach (itloc, a->locators)
1697  {
1698  ret = is_locator_in_locator_set (lcm, ls, itloc);
1699  if (0 != ret)
1700  {
1701  return ret;
1702  }
1703 
1704  pool_get (lcm->locator_pool, loc);
1705  loc[0] = itloc[0];
1706  loc_index = loc - lcm->locator_pool;
1707 
1708  vec_add1 (ls->locator_indices, loc_index);
1709 
1710  vec_validate (lcm->locator_to_locator_sets, loc_index);
1711  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
1712  loc_index);
1713  vec_add1 (ls_indexes[0], p[0]);
1714  }
1715  }
1716  else
1717  {
1718  ls_index = p[0];
1719 
1720  itloc = a->locators;
1721  loc_id = 0;
1722  vec_foreach (locit, ls->locator_indices)
1723  {
1724  loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1725 
1726  if (loc->local && loc->sw_if_index == itloc->sw_if_index)
1727  {
1728  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
1729  }
1730  if (0 == loc->local &&
1731  !gid_address_cmp (&loc->address, &itloc->address))
1732  {
1733  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
1734  }
1735 
1736  loc_id++;
1737  }
1738  }
1739 
1740  return 0;
1741 }
1742 
1743 int
1745  u32 * ls_result)
1746 {
1748  locator_set_t *ls;
1749  uword _p = (u32) ~ 0, *p = &_p;
1750  u32 ls_index;
1751  u32 **eid_indexes;
1752  int ret = 0;
1753 
1754  if (vnet_lisp_enable_disable_status () == 0)
1755  {
1756  clib_warning ("LISP is disabled!");
1757  return VNET_API_ERROR_LISP_DISABLED;
1758  }
1759 
1760  if (a->is_add)
1761  {
1762  p = get_locator_set_index (a, p);
1763 
1764  /* overwrite */
1765  if (p && p[0] != (u32) ~ 0)
1766  {
1767  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1768  if (!ls)
1769  {
1770  clib_warning ("locator-set %d to be overwritten doesn't exist!",
1771  p[0]);
1772  return -1;
1773  }
1774 
1775  /* clean locator to locator-set vectors and remove locators if
1776  * they're not part of another locator-set */
1777  clean_locator_to_locator_set (lcm, p[0]);
1778 
1779  /* remove locator indices from locator set */
1780  vec_free (ls->locator_indices);
1781 
1782  ls_index = p[0];
1783 
1784  if (ls_result)
1785  ls_result[0] = p[0];
1786  }
1787  /* new locator-set */
1788  else
1789  {
1790  pool_get (lcm->locator_set_pool, ls);
1791  memset (ls, 0, sizeof (*ls));
1792  ls_index = ls - lcm->locator_set_pool;
1793 
1794  if (a->local)
1795  {
1796  ls->name = vec_dup (a->name);
1797 
1798  if (!lcm->locator_set_index_by_name)
1800  /* size */
1801  0,
1802  sizeof
1803  (ls->name
1804  [0]),
1805  sizeof
1806  (uword));
1808  ls_index);
1809 
1810  /* mark as local locator-set */
1811  vec_add1 (lcm->local_locator_set_indexes, ls_index);
1812  }
1813  ls->local = a->local;
1814  if (ls_result)
1815  ls_result[0] = ls_index;
1816  }
1817 
1818  ret = vnet_lisp_add_del_locator (a, ls, NULL);
1819  if (0 != ret)
1820  {
1821  return ret;
1822  }
1823  }
1824  else
1825  {
1826  p = get_locator_set_index (a, p);
1827  if (!p)
1828  {
1829  clib_warning ("locator-set %v doesn't exists", a->name);
1830  return -1;
1831  }
1832 
1833  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1834  if (!ls)
1835  {
1836  clib_warning ("locator-set with index %d doesn't exists", p[0]);
1837  return -1;
1838  }
1839 
1840  if (lcm->mreq_itr_rlocs == p[0])
1841  {
1842  clib_warning ("Can't delete the locator-set used to constrain "
1843  "the itr-rlocs in map-requests!");
1844  return -1;
1845  }
1846 
1847  if (vec_len (lcm->locator_set_to_eids) != 0)
1848  {
1849  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]);
1850  if (vec_len (eid_indexes[0]) != 0)
1851  {
1852  clib_warning
1853  ("Can't delete a locator that supports a mapping!");
1854  return -1;
1855  }
1856  }
1857 
1858  /* clean locator to locator-sets data */
1859  clean_locator_to_locator_set (lcm, p[0]);
1860 
1861  if (ls->local)
1862  {
1863  u32 it, lsi;
1864 
1866  {
1867  lsi = vec_elt (lcm->local_locator_set_indexes, it);
1868  if (lsi == p[0])
1869  {
1871  break;
1872  }
1873  }
1875  }
1876  vec_free (ls->name);
1877  vec_free (ls->locator_indices);
1878  pool_put (lcm->locator_set_pool, ls);
1879  }
1880  return 0;
1881 }
1882 
1883 clib_error_t *
1885 {
1886  u32 vni, dp_table;
1887  clib_error_t *error = 0;
1890 
1891  a->is_en = is_enable;
1892  error = vnet_lisp_gpe_enable_disable (a);
1893  if (error)
1894  {
1895  return clib_error_return (0, "failed to %s data-plane!",
1896  a->is_en ? "enable" : "disable");
1897  }
1898 
1899  if (is_enable)
1900  {
1901  /* enable all l2 and l3 ifaces */
1902 
1903  /* *INDENT-OFF* */
1904  hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({
1905  dp_add_del_iface(lcm, vni, 0, 1);
1906  }));
1907  hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({
1908  dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1);
1909  }));
1910  /* *INDENT-ON* */
1911  }
1912  else
1913  {
1914  /* clear interface table */
1915  hash_free (lcm->dp_intf_by_vni);
1917  pool_free (lcm->fwd_entry_pool);
1918  }
1919 
1920  /* update global flag */
1921  lcm->is_enabled = is_enable;
1922 
1923  return 0;
1924 }
1925 
1926 static clib_error_t *
1928  vlib_cli_command_t * cmd)
1929 {
1930  unformat_input_t _line_input, *line_input = &_line_input;
1931  u8 is_enabled = 0;
1932  u8 is_set = 0;
1933 
1934  /* Get a line of input. */
1935  if (!unformat_user (input, unformat_line_input, line_input))
1936  return 0;
1937 
1938  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1939  {
1940  if (unformat (line_input, "enable"))
1941  {
1942  is_set = 1;
1943  is_enabled = 1;
1944  }
1945  else if (unformat (line_input, "disable"))
1946  is_set = 1;
1947  else
1948  {
1949  return clib_error_return (0, "parse error: '%U'",
1950  format_unformat_error, line_input);
1951  }
1952  }
1953 
1954  if (!is_set)
1955  return clib_error_return (0, "state not set");
1956 
1957  return vnet_lisp_enable_disable (is_enabled);
1958 }
1959 
1960 /* *INDENT-OFF* */
1961 VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
1962  .path = "lisp",
1963  .short_help = "lisp [enable|disable]",
1964  .function = lisp_enable_disable_command_fn,
1965 };
1966 /* *INDENT-ON* */
1967 
1968 u8
1970 {
1972  return lcm->is_enabled;
1973 }
1974 
1975 static u8 *
1976 format_lisp_status (u8 * s, va_list * args)
1977 {
1979  return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
1980 }
1981 
1982 static clib_error_t *
1984  vlib_cli_command_t * cmd)
1985 {
1986  u8 *msg = 0;
1987  msg = format (msg, "feature: %U\ngpe: %U\n",
1989  vlib_cli_output (vm, "%v", msg);
1990  vec_free (msg);
1991  return 0;
1992 }
1993 
1994 /* *INDENT-OFF* */
1995 VLIB_CLI_COMMAND (lisp_show_status_command) = {
1996  .path = "show lisp status",
1997  .short_help = "show lisp status",
1998  .function = lisp_show_status_command_fn,
1999 };
2000 /* *INDENT-ON* */
2001 
2002 static clib_error_t *
2004  unformat_input_t * input,
2005  vlib_cli_command_t * cmd)
2006 {
2007  hash_pair_t *p;
2009 
2010  vlib_cli_output (vm, "%=10s%=10s", "VNI", "VRF");
2011 
2012  /* *INDENT-OFF* */
2014  ({
2015  vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
2016  }));
2017  /* *INDENT-ON* */
2018 
2019  return 0;
2020 }
2021 
2022 /* *INDENT-OFF* */
2023 VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
2024  .path = "show lisp eid-table map",
2025  .short_help = "show lisp eid-table vni to vrf mappings",
2027 };
2028 /* *INDENT-ON* */
2029 
2030 static clib_error_t *
2032  unformat_input_t * input,
2033  vlib_cli_command_t * cmd)
2034 {
2036  vnet_main_t *vnm = lgm->vnet_main;
2037  unformat_input_t _line_input, *line_input = &_line_input;
2038  u8 is_add = 1;
2039  clib_error_t *error = 0;
2040  u8 *locator_set_name = 0;
2041  locator_t locator, *locators = 0;
2043  u32 ls_index = 0;
2044  int rv = 0;
2045 
2046  memset (&locator, 0, sizeof (locator));
2047  memset (a, 0, sizeof (a[0]));
2048 
2049  /* Get a line of input. */
2050  if (!unformat_user (input, unformat_line_input, line_input))
2051  return 0;
2052 
2053  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2054  {
2055  if (unformat (line_input, "add %_%v%_", &locator_set_name))
2056  is_add = 1;
2057  else if (unformat (line_input, "del %_%v%_", &locator_set_name))
2058  is_add = 0;
2059  else if (unformat (line_input, "iface %U p %d w %d",
2061  &locator.sw_if_index, &locator.priority,
2062  &locator.weight))
2063  {
2064  locator.local = 1;
2065  vec_add1 (locators, locator);
2066  }
2067  else
2068  {
2069  error = unformat_parse_error (line_input);
2070  goto done;
2071  }
2072  }
2073 
2074  a->name = locator_set_name;
2075  a->locators = locators;
2076  a->is_add = is_add;
2077  a->local = 1;
2078 
2079  rv = vnet_lisp_add_del_locator_set (a, &ls_index);
2080  if (0 != rv)
2081  {
2082  error = clib_error_return (0, "failed to %s locator-set!",
2083  is_add ? "add" : "delete");
2084  }
2085 
2086 done:
2087  vec_free (locators);
2088  if (locator_set_name)
2089  vec_free (locator_set_name);
2090  return error;
2091 }
2092 
2093 /* *INDENT-OFF* */
2094 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
2095  .path = "lisp locator-set",
2096  .short_help = "lisp locator-set add/del <name> [iface <iface-name> "
2097  "p <priority> w <weight>]",
2099 };
2100 /* *INDENT-ON* */
2101 
2102 static clib_error_t *
2104  unformat_input_t * input,
2105  vlib_cli_command_t * cmd)
2106 {
2108  vnet_main_t *vnm = lgm->vnet_main;
2109  unformat_input_t _line_input, *line_input = &_line_input;
2110  u8 is_add = 1;
2111  clib_error_t *error = 0;
2112  u8 *locator_set_name = 0;
2113  u8 locator_set_name_set = 0;
2114  locator_t locator, *locators = 0;
2116  u32 ls_index = 0;
2117 
2118  memset (&locator, 0, sizeof (locator));
2119  memset (a, 0, sizeof (a[0]));
2120 
2121  /* Get a line of input. */
2122  if (!unformat_user (input, unformat_line_input, line_input))
2123  return 0;
2124 
2125  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2126  {
2127  if (unformat (line_input, "add"))
2128  is_add = 1;
2129  else if (unformat (line_input, "del"))
2130  is_add = 0;
2131  else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
2132  locator_set_name_set = 1;
2133  else if (unformat (line_input, "iface %U p %d w %d",
2135  &locator.sw_if_index, &locator.priority,
2136  &locator.weight))
2137  {
2138  locator.local = 1;
2139  vec_add1 (locators, locator);
2140  }
2141  else
2142  {
2143  error = unformat_parse_error (line_input);
2144  goto done;
2145  }
2146  }
2147 
2148  if (!locator_set_name_set)
2149  {
2150  error = clib_error_return (0, "locator_set name not set!");
2151  goto done;
2152  }
2153 
2154  a->name = locator_set_name;
2155  a->locators = locators;
2156  a->is_add = is_add;
2157  a->local = 1;
2158 
2159  vnet_lisp_add_del_locator (a, 0, &ls_index);
2160 
2161 done:
2162  vec_free (locators);
2163  vec_free (locator_set_name);
2164  return error;
2165 }
2166 
2167 /* *INDENT-OFF* */
2168 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = {
2169  .path = "lisp locator",
2170  .short_help = "lisp locator add/del locator-set <name> iface <iface-name> "
2171  "p <priority> w <weight>",
2173 };
2174 /* *INDENT-ON* */
2175 
2176 static clib_error_t *
2178  unformat_input_t * input,
2179  vlib_cli_command_t * cmd)
2180 {
2181  locator_set_t *lsit;
2182  locator_t *loc;
2183  u32 *locit;
2185 
2186  vlib_cli_output (vm, "%=20s%=16s%=16s%=16s", "Locator-set", "Locator",
2187  "Priority", "Weight");
2188 
2189  /* *INDENT-OFF* */
2190  pool_foreach (lsit, lcm->locator_set_pool,
2191  ({
2192  u8 * msg = 0;
2193  int next_line = 0;
2194  if (lsit->local)
2195  {
2196  msg = format (msg, "%=16v", lsit->name);
2197  }
2198  else
2199  {
2200  msg = format (msg, "%=16s", "remote");
2201  }
2202  vec_foreach (locit, lsit->locator_indices)
2203  {
2204  if (next_line)
2205  {
2206  msg = format (msg, "%16s", " ");
2207  }
2208  loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2209  if (loc->local)
2210  msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
2211  loc->weight);
2212  else
2213  msg = format (msg, "%16U%16d%16d\n", format_ip_address,
2214  &gid_address_ip(&loc->address), loc->priority,
2215  loc->weight);
2216  next_line = 1;
2217  }
2218  vlib_cli_output (vm, "%v", msg);
2219  vec_free (msg);
2220  }));
2221  /* *INDENT-ON* */
2222  return 0;
2223 }
2224 
2225 /* *INDENT-OFF* */
2226 VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
2227  .path = "show lisp locator-set",
2228  .short_help = "Shows locator-sets",
2230 };
2231 /* *INDENT-ON* */
2232 
2233 static map_resolver_t *
2234 get_map_resolver (ip_address_t * a)
2235 {
2237  map_resolver_t *mr;
2238 
2239  vec_foreach (mr, lcm->map_resolvers)
2240  {
2241  if (!ip_address_cmp (&mr->address, a))
2242  {
2243  return mr;
2244  }
2245  }
2246  return 0;
2247 }
2248 
2249 int
2251 {
2253  u32 i;
2254  map_resolver_t _mr, *mr = &_mr;
2255 
2256  if (vnet_lisp_enable_disable_status () == 0)
2257  {
2258  clib_warning ("LISP is disabled!");
2259  return VNET_API_ERROR_LISP_DISABLED;
2260  }
2261 
2262  if (a->is_add)
2263  {
2264 
2265  if (get_map_resolver (&a->address))
2266  {
2267  clib_warning ("map-resolver %U already exists!", format_ip_address,
2268  &a->address);
2269  return -1;
2270  }
2271 
2272  memset (mr, 0, sizeof (*mr));
2273  ip_address_copy (&mr->address, &a->address);
2274  vec_add1 (lcm->map_resolvers, *mr);
2275 
2276  if (vec_len (lcm->map_resolvers) == 1)
2277  lcm->do_map_resolver_election = 1;
2278  }
2279  else
2280  {
2281  for (i = 0; i < vec_len (lcm->map_resolvers); i++)
2282  {
2283  mr = vec_elt_at_index (lcm->map_resolvers, i);
2284  if (!ip_address_cmp (&mr->address, &a->address))
2285  {
2286  if (!ip_address_cmp (&mr->address, &lcm->active_map_resolver))
2287  lcm->do_map_resolver_election = 1;
2288 
2289  vec_del1 (lcm->map_resolvers, i);
2290  break;
2291  }
2292  }
2293  }
2294  return 0;
2295 }
2296 
2297 static clib_error_t *
2299  unformat_input_t * input,
2300  vlib_cli_command_t * cmd)
2301 {
2302  unformat_input_t _line_input, *line_input = &_line_input;
2303  u8 is_add = 1, addr_set = 0;
2304  ip_address_t ip_addr;
2305  clib_error_t *error = 0;
2306  int rv = 0;
2308 
2309  /* Get a line of input. */
2310  if (!unformat_user (input, unformat_line_input, line_input))
2311  return 0;
2312 
2313  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2314  {
2315  if (unformat (line_input, "add"))
2316  is_add = 1;
2317  else if (unformat (line_input, "del"))
2318  is_add = 0;
2319  else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
2320  addr_set = 1;
2321  else
2322  {
2323  error = unformat_parse_error (line_input);
2324  goto done;
2325  }
2326  }
2327 
2328  if (!addr_set)
2329  {
2330  error = clib_error_return (0, "Map-resolver address must be set!");
2331  goto done;
2332  }
2333 
2334  a->is_add = is_add;
2335  a->address = ip_addr;
2337  if (0 != rv)
2338  {
2339  error = clib_error_return (0, "failed to %s map-resolver!",
2340  is_add ? "add" : "delete");
2341  }
2342 
2343 done:
2344  return error;
2345 }
2346 
2347 /* *INDENT-OFF* */
2348 VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
2349  .path = "lisp map-resolver",
2350  .short_help = "lisp map-resolver add/del <ip_address>",
2352 };
2353 /* *INDENT-ON* */
2354 
2355 int
2357 {
2359  uword *p = 0;
2360 
2361  if (vnet_lisp_enable_disable_status () == 0)
2362  {
2363  clib_warning ("LISP is disabled!");
2364  return VNET_API_ERROR_LISP_DISABLED;
2365  }
2366 
2367  if (a->is_add)
2368  {
2370  if (!p)
2371  {
2372  clib_warning ("locator-set %v doesn't exist", a->locator_set_name);
2373  return VNET_API_ERROR_INVALID_ARGUMENT;
2374  }
2375 
2376  lcm->mreq_itr_rlocs = p[0];
2377  }
2378  else
2379  {
2380  lcm->mreq_itr_rlocs = ~0;
2381  }
2382 
2383  return 0;
2384 }
2385 
2386 static clib_error_t *
2388  unformat_input_t * input,
2389  vlib_cli_command_t * cmd)
2390 {
2391  unformat_input_t _line_input, *line_input = &_line_input;
2392  u8 is_add = 1;
2393  u8 *locator_set_name = 0;
2394  clib_error_t *error = 0;
2395  int rv = 0;
2397 
2398  /* Get a line of input. */
2399  if (!unformat_user (input, unformat_line_input, line_input))
2400  return 0;
2401 
2402  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2403  {
2404  if (unformat (line_input, "del"))
2405  is_add = 0;
2406  else if (unformat (line_input, "add %s", &locator_set_name))
2407  is_add = 1;
2408  else
2409  {
2410  error = unformat_parse_error (line_input);
2411  goto done;
2412  }
2413  }
2414 
2415  a->is_add = is_add;
2416  a->locator_set_name = locator_set_name;
2418  if (0 != rv)
2419  {
2420  error = clib_error_return (0, "failed to %s map-request itr-rlocs!",
2421  is_add ? "add" : "delete");
2422  }
2423 
2424  vec_free (locator_set_name);
2425 
2426 done:
2427  return error;
2428 
2429 }
2430 
2431 /* *INDENT-OFF* */
2432 VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = {
2433  .path = "lisp map-request itr-rlocs",
2434  .short_help = "lisp map-request itr-rlocs add/del <locator_set_name>",
2436 };
2437 /* *INDENT-ON* */
2438 
2439 static clib_error_t *
2441  unformat_input_t * input,
2442  vlib_cli_command_t * cmd)
2443 {
2445  locator_set_t *loc_set;
2446 
2447  vlib_cli_output (vm, "%=20s", "itr-rlocs");
2448 
2449  if (~0 == lcm->mreq_itr_rlocs)
2450  {
2451  return 0;
2452  }
2453 
2454  loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
2455 
2456  vlib_cli_output (vm, "%=20s", loc_set->name);
2457 
2458  return 0;
2459 }
2460 
2461 /* *INDENT-OFF* */
2462 VLIB_CLI_COMMAND (lisp_show_map_request_command) = {
2463  .path = "show lisp map-request itr-rlocs",
2464  .short_help = "Shows map-request itr-rlocs",
2466 };
2467 /* *INDENT-ON* */
2468 
2469 /* Statistics (not really errors) */
2470 #define foreach_lisp_cp_lookup_error \
2471 _(DROP, "drop") \
2472 _(MAP_REQUESTS_SENT, "map-request sent")
2473 
2475 #define _(sym,string) string,
2477 #undef _
2478 };
2479 
2480 typedef enum
2481 {
2482 #define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
2484 #undef _
2487 
2488 typedef enum
2489 {
2495 
2496 typedef struct
2497 {
2499  ip_address_t map_resolver_ip;
2501 
2502 u8 *
2503 format_lisp_cp_lookup_trace (u8 * s, va_list * args)
2504 {
2505  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
2506  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
2507  lisp_cp_lookup_trace_t *t = va_arg (*args, lisp_cp_lookup_trace_t *);
2508 
2509  s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
2511  &t->dst_eid);
2512  return s;
2513 }
2514 
2515 int
2516 get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
2517  ip_address_t * sloc)
2518 {
2519  map_resolver_t *mrit;
2520  ip_address_t *a;
2521 
2522  if (vec_len (lcm->map_resolvers) == 0)
2523  {
2524  clib_warning ("No map-resolver configured");
2525  return 0;
2526  }
2527 
2528  /* find the first mr ip we have a route to and the ip of the
2529  * iface that has a route to it */
2530  vec_foreach (mrit, lcm->map_resolvers)
2531  {
2532  a = &mrit->address;
2533  if (0 != ip_fib_get_first_egress_ip_for_dst (lcm, a, sloc))
2534  {
2535  ip_address_copy (mr_ip, a);
2536 
2537  /* also update globals */
2538  return 1;
2539  }
2540  }
2541 
2542  clib_warning ("Can't find map-resolver and local interface ip!");
2543  return 0;
2544 }
2545 
2546 static gid_address_t *
2548 {
2549  void *addr;
2550  u32 i;
2551  locator_t *loc;
2552  u32 *loc_indexp;
2553  ip_interface_address_t *ia = 0;
2554  gid_address_t gid_data, *gid = &gid_data;
2555  gid_address_t *rlocs = 0;
2556  ip_prefix_t *ippref = &gid_address_ippref (gid);
2557  ip_address_t *rloc = &ip_prefix_addr (ippref);
2558 
2559  memset (gid, 0, sizeof (gid[0]));
2561  for (i = 0; i < vec_len (loc_set->locator_indices); i++)
2562  {
2563  loc_indexp = vec_elt_at_index (loc_set->locator_indices, i);
2564  loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
2565 
2566  /* Add ipv4 locators first TODO sort them */
2567 
2568  /* *INDENT-OFF* */
2570  loc->sw_if_index, 1 /* unnumbered */,
2571  ({
2572  addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
2573  ip_address_set (rloc, addr, IP4);
2574  ip_prefix_len (ippref) = 32;
2575  ip_prefix_normalize (ippref);
2576  vec_add1 (rlocs, gid[0]);
2577  }));
2578 
2579  /* Add ipv6 locators */
2581  loc->sw_if_index, 1 /* unnumbered */,
2582  ({
2583  addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
2584  ip_address_set (rloc, addr, IP6);
2585  ip_prefix_len (ippref) = 128;
2586  ip_prefix_normalize (ippref);
2587  vec_add1 (rlocs, gid[0]);
2588  }));
2589  /* *INDENT-ON* */
2590 
2591  }
2592  return rlocs;
2593 }
2594 
2595 static vlib_buffer_t *
2597  gid_address_t * seid, gid_address_t * deid,
2598  locator_set_t * loc_set, ip_address_t * mr_ip,
2599  ip_address_t * sloc, u8 is_smr_invoked,
2600  u64 * nonce_res, u32 * bi_res)
2601 {
2602  vlib_buffer_t *b;
2603  u32 bi;
2604  gid_address_t *rlocs = 0;
2605  vlib_main_t *vm = lcm->vlib_main;
2606 
2607  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2608  {
2609  clib_warning ("Can't allocate buffer for Map-Request!");
2610  return 0;
2611  }
2612 
2613  b = vlib_get_buffer (vm, bi);
2614 
2615  /* leave some space for the encap headers */
2617 
2618  /* get rlocs */
2619  rlocs = build_itr_rloc_list (lcm, loc_set);
2620 
2621  /* put lisp msg */
2622  lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked, nonce_res);
2623 
2624  /* push ecm: udp-ip-lisp */
2626 
2627  /* push outer ip header */
2629  mr_ip);
2630 
2631  bi_res[0] = bi;
2632 
2633  vec_free (rlocs);
2634  return b;
2635 }
2636 
2637 static void
2639 {
2641  r->retries_num = 0;
2642 }
2643 
2644 static int
2646 {
2647  map_resolver_t *mr;
2648 
2649  vec_foreach (mr, lcm->map_resolvers)
2650  {
2651  if (!mr->is_down)
2652  {
2654  lcm->do_map_resolver_election = 0;
2655  return 1;
2656  }
2657  }
2658  return 0;
2659 }
2660 
2661 #define send_encapsulated_map_request(lcm, seid, deid, smr) \
2662  _send_encapsulated_map_request(lcm, seid, deid, smr, 0)
2663 
2664 #define resend_encapsulated_map_request(lcm, seid, deid, smr) \
2665  _send_encapsulated_map_request(lcm, seid, deid, smr, 1)
2666 
2667 static int
2668 _send_encapsulated_map_request (lisp_cp_main_t * lcm,
2669  gid_address_t * seid, gid_address_t * deid,
2670  u8 is_smr_invoked, u8 is_resend)
2671 {
2672  map_resolver_t *mr;
2673  u32 next_index, bi = 0, *to_next, map_index;
2674  vlib_buffer_t *b;
2675  vlib_frame_t *f;
2676  u64 nonce = 0;
2677  locator_set_t *loc_set;
2678  mapping_t *map;
2679  pending_map_request_t *pmr, *duplicate_pmr = 0;
2680  ip_address_t sloc;
2681  u32 ls_index;
2682 
2684 
2685  /* if there is already a pending request remember it */
2686 
2687  /* *INDENT-OFF* */
2689  ({
2690  if (!gid_address_cmp (&pmr->src, seid)
2691  && !gid_address_cmp (&pmr->dst, deid))
2692  {
2693  duplicate_pmr = pmr;
2694  break;
2695  }
2696  }));
2697  /* *INDENT-ON* */
2698 
2699  if (!is_resend && duplicate_pmr)
2700  {
2701  /* don't send the request if there is a pending map request already */
2702  return 0;
2703  }
2704 
2705  /* get locator-set for seid */
2706  if (!lcm->lisp_pitr)
2707  {
2708  map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
2709  if (map_index == ~0)
2710  {
2711  clib_warning ("No local mapping found in eid-table for %U!",
2712  format_gid_address, seid);
2713  return -1;
2714  }
2715 
2716  map = pool_elt_at_index (lcm->mapping_pool, map_index);
2717 
2718  if (!map->local)
2719  {
2720  clib_warning
2721  ("Mapping found for src eid %U is not marked as local!",
2722  format_gid_address, seid);
2723  return -1;
2724  }
2725  ls_index = map->locator_set_index;
2726  }
2727  else
2728  {
2729  map_index = lcm->pitr_map_index;
2730  map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
2731  ls_index = map->locator_set_index;
2732  }
2733 
2734  /* overwrite locator set if map-request itr-rlocs configured */
2735  if (~0 != lcm->mreq_itr_rlocs)
2736  {
2737  ls_index = lcm->mreq_itr_rlocs;
2738  }
2739 
2740  loc_set = pool_elt_at_index (lcm->locator_set_pool, ls_index);
2741 
2742  while (lcm->do_map_resolver_election
2744  &lcm->active_map_resolver,
2745  &sloc)))
2746  {
2747  if (0 == elect_map_resolver (lcm))
2748  /* all Mrs are down */
2749  {
2750  if (duplicate_pmr)
2751  duplicate_pmr->to_be_removed = 1;
2752 
2753  /* restart MR checking by marking all of them up */
2754  vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0;
2755 
2756  return -1;
2757  }
2758  }
2759 
2760  /* build the encapsulated map request */
2761  b = build_encapsulated_map_request (lcm, seid, deid, loc_set,
2762  &lcm->active_map_resolver,
2763  &sloc, is_smr_invoked, &nonce, &bi);
2764 
2765  if (!b)
2766  return -1;
2767 
2768  /* set fib index to default and lookup node */
2769  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
2770  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
2771  ip4_lookup_node.index : ip6_lookup_node.index;
2772 
2773  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
2774 
2775  /* Enqueue the packet */
2776  to_next = vlib_frame_vector_args (f);
2777  to_next[0] = bi;
2778  f->n_vectors = 1;
2779  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
2780 
2781  if (duplicate_pmr)
2782  /* if there is a pending request already update it */
2783  {
2784  if (clib_fifo_elts (duplicate_pmr->nonces) >= PENDING_MREQ_QUEUE_LEN)
2785  {
2786  /* remove the oldest nonce */
2787  u64 CLIB_UNUSED (tmp), *nonce_del;
2788  nonce_del = clib_fifo_head (duplicate_pmr->nonces);
2789  hash_unset (lcm->pending_map_requests_by_nonce, nonce_del[0]);
2790  clib_fifo_sub1 (duplicate_pmr->nonces, tmp);
2791  }
2792 
2793  clib_fifo_add1 (duplicate_pmr->nonces, nonce);
2794  hash_set (lcm->pending_map_requests_by_nonce, nonce,
2795  duplicate_pmr - lcm->pending_map_requests_pool);
2796  }
2797  else
2798  {
2799  /* add map-request to pending requests table */
2800  pool_get (lcm->pending_map_requests_pool, pmr);
2801  memset (pmr, 0, sizeof (*pmr));
2802  gid_address_copy (&pmr->src, seid);
2803  gid_address_copy (&pmr->dst, deid);
2804  clib_fifo_add1 (pmr->nonces, nonce);
2805  pmr->is_smr_invoked = is_smr_invoked;
2807  hash_set (lcm->pending_map_requests_by_nonce, nonce,
2808  pmr - lcm->pending_map_requests_pool);
2809  }
2810 
2811  return 0;
2812 }
2813 
2814 static void
2815 get_src_and_dst_ip (void *hdr, ip_address_t * src, ip_address_t * dst)
2816 {
2817  ip4_header_t *ip4 = hdr;
2818  ip6_header_t *ip6;
2819 
2820  if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
2821  {
2822  ip_address_set (src, &ip4->src_address, IP4);
2823  ip_address_set (dst, &ip4->dst_address, IP4);
2824  }
2825  else
2826  {
2827  ip6 = hdr;
2828  ip_address_set (src, &ip6->src_address, IP6);
2829  ip_address_set (dst, &ip6->dst_address, IP6);
2830  }
2831 }
2832 
2833 static u32
2835  u8 version)
2836 {
2837  uword *vnip;
2838  u32 vni = ~0, table_id = ~0, fib_index;
2839 
2840  if (version == IP4)
2841  {
2842  ip4_fib_t *fib;
2843  ip4_main_t *im4 = &ip4_main;
2844  fib_index = vec_elt (im4->fib_index_by_sw_if_index,
2845  vnet_buffer (b)->sw_if_index[VLIB_RX]);
2846  fib = find_ip4_fib_by_table_index_or_id (im4, fib_index,
2848  table_id = fib->table_id;
2849  }
2850  else
2851  {
2852  ip6_fib_t *fib;
2853  ip6_main_t *im6 = &ip6_main;
2854  fib_index = vec_elt (im6->fib_index_by_sw_if_index,
2855  vnet_buffer (b)->sw_if_index[VLIB_RX]);
2856  fib = find_ip6_fib_by_table_index_or_id (im6, fib_index,
2858  table_id = fib->table_id;
2859  }
2860 
2861  vnip = hash_get (lcm->vni_by_table_id, table_id);
2862  if (vnip)
2863  vni = vnip[0];
2864  else
2865  clib_warning ("vrf %d is not mapped to any vni!", table_id);
2866 
2867  return vni;
2868 }
2869 
2872 {
2873  uword *vnip;
2874  u32 vni = ~0;
2875  u32 sw_if_index0;
2876 
2877  l2input_main_t *l2im = &l2input_main;
2878  l2_input_config_t *config;
2879  l2_bridge_domain_t *bd_config;
2880 
2881  sw_if_index0 = vnet_buffer (b)->sw_if_index[VLIB_RX];
2882  config = vec_elt_at_index (l2im->configs, sw_if_index0);
2883  bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
2884 
2885  vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id);
2886  if (vnip)
2887  vni = vnip[0];
2888  else
2889  clib_warning ("bridge domain %d is not mapped to any vni!",
2890  config->bd_index);
2891 
2892  return vni;
2893 }
2894 
2895 always_inline void
2897  gid_address_t * src, gid_address_t * dst)
2898 {
2899  u32 vni = 0;
2900  u16 type;
2901 
2902  memset (src, 0, sizeof (*src));
2903  memset (dst, 0, sizeof (*dst));
2904  type = vnet_buffer (b)->lisp.overlay_afi;
2905 
2906  if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
2907  {
2908  ip4_header_t *ip;
2909  u8 version, preflen;
2910 
2913 
2914  ip = vlib_buffer_get_current (b);
2915  get_src_and_dst_ip (ip, &gid_address_ip (src), &gid_address_ip (dst));
2916 
2917  version = gid_address_ip_version (src);
2918  preflen = ip_address_max_len (version);
2919  gid_address_ippref_len (src) = preflen;
2920  gid_address_ippref_len (dst) = preflen;
2921 
2922  vni = lisp_get_vni_from_buffer_ip (lcm, b, version);
2923  gid_address_vni (dst) = vni;
2924  gid_address_vni (src) = vni;
2925  }
2926  else if (LISP_AFI_MAC == type)
2927  {
2928  ethernet_header_t *eh;
2929 
2930  eh = vlib_buffer_get_current (b);
2931 
2934  mac_copy (&gid_address_mac (src), eh->src_address);
2935  mac_copy (&gid_address_mac (dst), eh->dst_address);
2936 
2937  /* get vni */
2938  vni = lisp_get_vni_from_buffer_eth (lcm, b);
2939 
2940  gid_address_vni (dst) = vni;
2941  gid_address_vni (src) = vni;
2942  }
2943 }
2944 
2945 static uword
2947  vlib_frame_t * from_frame)
2948 {
2949  u32 *from, *to_next_drop, di, si;
2951  u32 pkts_mapped = 0;
2952  uword n_left_from, n_left_to_next_drop;
2953 
2954  from = vlib_frame_vector_args (from_frame);
2955  n_left_from = from_frame->n_vectors;
2956 
2957  while (n_left_from > 0)
2958  {
2960  to_next_drop, n_left_to_next_drop);
2961 
2962  while (n_left_from > 0 && n_left_to_next_drop > 0)
2963  {
2964  u32 pi0;
2965  vlib_buffer_t *b0;
2966  gid_address_t src, dst;
2967 
2968  pi0 = from[0];
2969  from += 1;
2970  n_left_from -= 1;
2971  to_next_drop[0] = pi0;
2972  to_next_drop += 1;
2973  n_left_to_next_drop -= 1;
2974 
2975  b0 = vlib_get_buffer (vm, pi0);
2976  b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
2977 
2978  /* src/dst eid pair */
2979  get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
2980 
2981  /* if we have remote mapping for destination already in map-chache
2982  add forwarding tunnel directly. If not send a map-request */
2983  di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
2984  if (~0 != di)
2985  {
2986  mapping_t *m = vec_elt_at_index (lcm->mapping_pool, di);
2987  /* send a map-request also in case of negative mapping entry
2988  with corresponding action */
2989  if (m->action == LISP_SEND_MAP_REQUEST)
2990  {
2991  /* send map-request */
2992  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
2993  0 /* is_resend */ );
2994  pkts_mapped++;
2995  }
2996  else
2997  {
2999  &src);
3000  if (~0 != si)
3001  {
3002  dp_add_fwd_entry (lcm, si, di);
3003  }
3004  }
3005  }
3006  else
3007  {
3008  /* send map-request */
3009  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
3010  0 /* is_resend */ );
3011  pkts_mapped++;
3012  }
3013 
3015  {
3016  lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
3017  sizeof (*tr));
3018 
3019  memset (tr, 0, sizeof (*tr));
3020  gid_address_copy (&tr->dst_eid, &dst);
3022  &lcm->active_map_resolver);
3023  }
3024  gid_address_free (&dst);
3025  gid_address_free (&src);
3026  }
3027 
3029  n_left_to_next_drop);
3030  }
3032  LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
3033  pkts_mapped);
3034  return from_frame->n_vectors;
3035 }
3036 
3037 /* *INDENT-OFF* */
3039  .function = lisp_cp_lookup,
3040  .name = "lisp-cp-lookup",
3041  .vector_size = sizeof (u32),
3042  .format_trace = format_lisp_cp_lookup_trace,
3044 
3045  .n_errors = LISP_CP_LOOKUP_N_ERROR,
3046  .error_strings = lisp_cp_lookup_error_strings,
3047 
3048  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
3049 
3050  .next_nodes = {
3051  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
3052  [LISP_CP_LOOKUP_NEXT_IP4_LOOKUP] = "ip4-lookup",
3053  [LISP_CP_LOOKUP_NEXT_IP6_LOOKUP] = "ip6-lookup",
3054  },
3055 };
3056 /* *INDENT-ON* */
3057 
3058 /* lisp_cp_input statistics */
3059 #define foreach_lisp_cp_input_error \
3060 _(DROP, "drop") \
3061 _(MAP_REPLIES_RECEIVED, "map-replies received")
3062 
3064 #define _(sym,string) string,
3066 #undef _
3067 };
3068 
3069 typedef enum
3070 {
3071 #define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
3073 #undef _
3076 
3077 typedef enum
3078 {
3082 
3083 typedef struct
3084 {
3088 
3089 u8 *
3090 format_lisp_cp_input_trace (u8 * s, va_list * args)
3091 {
3092  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
3093  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
3095  va_arg (*args, lisp_cp_input_trace_t *);
3096 
3097  s = format (s, "LISP-CP-INPUT: TODO");
3098  return s;
3099 }
3100 
3101 void *
3103 {
3105  vlib_buffer_t *b = arg;
3106  u32 len = 0, i, ttl, dst_map_index = 0;
3107  void *h;
3108  pending_map_request_t *pmr;
3109  locator_t probed;
3110  map_reply_hdr_t *mrep_hdr;
3111  u64 nonce, *noncep;
3112  gid_address_t deid;
3113  uword *pmr_index;
3114  u8 authoritative, action;
3115  locator_t *locators = 0, *loc;
3116 
3117  mrep_hdr = vlib_buffer_get_current (b);
3118 
3120 
3121  /* Check pending requests table and nonce */
3122  nonce = MREP_NONCE (mrep_hdr);
3123  pmr_index = hash_get (lcm->pending_map_requests_by_nonce, nonce);
3124  if (!pmr_index)
3125  {
3126  clib_warning ("No pending map-request entry with nonce %lu!", nonce);
3127  goto done;
3128  }
3129  pmr = pool_elt_at_index (lcm->pending_map_requests_pool, pmr_index[0]);
3130 
3131  vlib_buffer_pull (b, sizeof (*mrep_hdr));
3132 
3133  for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
3134  {
3135  h = vlib_buffer_get_current (b);
3136  ttl = clib_net_to_host_u32 (MAP_REC_TTL (h));
3137  action = MAP_REC_ACTION (h);
3138  authoritative = MAP_REC_AUTH (h);
3139 
3140  len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
3141  if (len == ~0)
3142  {
3143  clib_warning ("Failed to parse mapping record!");
3144  vec_foreach (loc, locators)
3145  {
3146  locator_free (loc);
3147  }
3148  vec_free (locators);
3149  goto done;
3150  }
3151 
3152  /* insert/update mappings cache */
3153  vnet_lisp_add_del_mapping (&deid, locators, action, authoritative, ttl,
3154  1, 0 /* is_static */ , &dst_map_index);
3155 
3156  /* try to program forwarding only if mapping saved or updated */
3157  if ((u32) ~ 0 != dst_map_index)
3158  lisp_add_del_adjacency (lcm, &pmr->src, &deid, 1);
3159 
3160  vec_free (locators);
3161  }
3162 
3163  /* remove pending map request entry */
3164 
3165  /* *INDENT-OFF* */
3166  clib_fifo_foreach (noncep, pmr->nonces, ({
3167  hash_unset(lcm->pending_map_requests_by_nonce, noncep[0]);
3168  }));
3169  /* *INDENT-ON* */
3170 
3171  clib_fifo_free (pmr->nonces);
3172  pool_put (lcm->pending_map_requests_pool, pmr);
3173 
3174 done:
3176  return 0;
3177 }
3178 
3179 void
3181  vlib_buffer_t * b)
3182 {
3183  map_request_hdr_t *mreq_hdr;
3184  gid_address_t src, dst;
3185 // u64 nonce;
3186  u32 i, len = 0;
3187  gid_address_t *itr_rlocs = 0, *rloc;
3188 
3189  mreq_hdr = vlib_buffer_get_current (b);
3190  vlib_buffer_pull (b, sizeof (*mreq_hdr));
3191 
3192 // nonce = MREQ_NONCE(mreq_hdr);
3193 
3194  if (!MREQ_SMR (mreq_hdr))
3195  {
3196  clib_warning ("Only SMR Map-Requests supported for now!");
3197  return;
3198  }
3199 
3200  /* parse src eid */
3201  len = lisp_msg_parse_addr (b, &src);
3202  if (len == ~0)
3203  return;
3204 
3205  /* for now we don't do anything with the itr's rlocs */
3206  len =
3207  lisp_msg_parse_itr_rlocs (b, &itr_rlocs,
3208  MREQ_ITR_RLOC_COUNT (mreq_hdr) + 1);
3209  if (len == ~0)
3210  return;
3211 
3212  /* TODO: RLOCs are currently unused, so free them for now */
3213  vec_foreach (rloc, itr_rlocs)
3214  {
3215  gid_address_free (rloc);
3216  }
3217 
3218  /* parse eid records and send SMR-invoked map-requests */
3219  for (i = 0; i < MREQ_REC_COUNT (mreq_hdr); i++)
3220  {
3221  memset (&dst, 0, sizeof (dst));
3222  len = lisp_msg_parse_eid_rec (b, &dst);
3223  if (len == ~0)
3224  {
3225  clib_warning ("Can't parse map-request EID-record");
3226  return;
3227  }
3228  /* send SMR-invoked map-requests */
3229  queue_map_request (&dst, &src, 1 /* invoked */ , 0 /* resend */ );
3230  }
3231 }
3232 
3233 static void
3235 {
3236  vlib_buffer_t *a = clib_mem_alloc (sizeof (a[0]) + b->current_length);
3237 
3238  clib_memcpy (a->data, b->data + b->current_data, b->current_length);
3240  a->current_data = 0;
3241 
3242  vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (a[0])
3243  + a->current_length);
3244  clib_mem_free (a);
3245 }
3246 
3247 static uword
3249  vlib_frame_t * from_frame)
3250 {
3251  u32 n_left_from, *from, *to_next_drop;
3254 
3255  from = vlib_frame_vector_args (from_frame);
3256  n_left_from = from_frame->n_vectors;
3257 
3258 
3259  while (n_left_from > 0)
3260  {
3261  u32 n_left_to_next_drop;
3262 
3264  to_next_drop, n_left_to_next_drop);
3265  while (n_left_from > 0 && n_left_to_next_drop > 0)
3266  {
3267  u32 bi0;
3268  vlib_buffer_t *b0;
3269 
3270  bi0 = from[0];
3271  from += 1;
3272  n_left_from -= 1;
3273  to_next_drop[0] = bi0;
3274  to_next_drop += 1;
3275  n_left_to_next_drop -= 1;
3276 
3277  b0 = vlib_get_buffer (vm, bi0);
3278 
3279  type = lisp_msg_type (vlib_buffer_get_current (b0));
3280  switch (type)
3281  {
3282  case LISP_MAP_REPLY:
3283  queue_map_reply (b0);
3284  break;
3285  case LISP_MAP_REQUEST:
3286  process_map_request (vm, lcm, b0);
3287  break;
3288  default:
3289  clib_warning ("Unsupported LISP message type %d", type);
3290  break;
3291  }
3292 
3293  b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
3294 
3296  {
3297 
3298  }
3299  }
3300 
3302  n_left_to_next_drop);
3303  }
3304  return from_frame->n_vectors;
3305 }
3306 
3307 /* *INDENT-OFF* */
3309  .function = lisp_cp_input,
3310  .name = "lisp-cp-input",
3311  .vector_size = sizeof (u32),
3312  .format_trace = format_lisp_cp_input_trace,
3314 
3315  .n_errors = LISP_CP_INPUT_N_ERROR,
3316  .error_strings = lisp_cp_input_error_strings,
3317 
3318  .n_next_nodes = LISP_CP_INPUT_N_NEXT,
3319 
3320  .next_nodes = {
3321  [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
3322  },
3323 };
3324 /* *INDENT-ON* */
3325 
3326 clib_error_t *
3328 {
3330  clib_error_t *error = 0;
3331 
3332  if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
3333  return error;
3334 
3335  lcm->im4 = &ip4_main;
3336  lcm->im6 = &ip6_main;
3337  lcm->vlib_main = vm;
3338  lcm->vnet_main = vnet_get_main ();
3339  lcm->mreq_itr_rlocs = ~0;
3340  lcm->lisp_pitr = 0;
3341  memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver));
3342 
3345 
3346  lcm->pending_map_request_lock[0] = 0;
3348  lcm->do_map_resolver_election = 1;
3349 
3350  /* default vrf mapped to vni 0 */
3351  hash_set (lcm->table_id_by_vni, 0, 0);
3352  hash_set (lcm->vni_by_table_id, 0, 0);
3353 
3354  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
3355  lisp_cp_input_node.index, 1 /* is_ip4 */ );
3356  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
3357  lisp_cp_input_node.index, 0 /* is_ip4 */ );
3358 
3359  return 0;
3360 }
3361 
3362 static void *
3364 {
3365  map_request_args_t *a = arg;
3367 
3369 
3370  if (a->is_resend)
3372  else
3373  send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
3374 
3376 
3377  return 0;
3378 }
3379 
3380 static int
3382  u8 smr_invoked, u8 is_resend)
3383 {
3385 
3386  a.is_resend = is_resend;
3387  gid_address_copy (&a.seid, seid);
3388  gid_address_copy (&a.deid, deid);
3389  a.smr_invoked = smr_invoked;
3390 
3392  (u8 *) & a, sizeof (a));
3393  return 0;
3394 }
3395 
3396 /**
3397  * Take an action with a pending map request depending on expiration time
3398  * and re-try counters.
3399  */
3400 static void
3402 {
3404  map_resolver_t *mr;
3405 
3406  if (r->time_to_expire - dt < 0)
3407  /* it's time to decide what to do with this pending request */
3408  {
3409  if (r->retries_num >= NUMBER_OF_RETRIES)
3410  /* too many retries -> assume current map resolver is not available */
3411  {
3413  if (!mr)
3414  {
3415  clib_warning ("Map resolver %U not found - probably deleted "
3416  "by the user recently.", format_ip_address,
3417  &lcm->active_map_resolver);
3418  }
3419  else
3420  {
3421  clib_warning ("map resolver %U is unreachable, ignoring",
3423 
3424  /* mark current map resolver unavailable so it won't be
3425  * selected next time */
3426  mr->is_down = 1;
3427  mr->last_update = vlib_time_now (lcm->vlib_main);
3428  }
3429 
3431  elect_map_resolver (lcm);
3432 
3433  /* try to find a next eligible map resolver and re-send */
3434  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
3435  1 /* resend */ );
3436  }
3437  else
3438  {
3439  /* try again */
3440  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
3441  1 /* resend */ );
3442  r->retries_num++;
3444  }
3445  }
3446  else
3447  r->time_to_expire -= dt;
3448 }
3449 
3450 static void
3452 {
3453  u64 *nonce;
3454  pending_map_request_t *pmr;
3455  u32 *to_be_removed = 0, *pmr_index;
3456 
3458 
3459  /* *INDENT-OFF* */
3461  ({
3462  if (pmr->to_be_removed)
3463  {
3464  clib_fifo_foreach (nonce, pmr->nonces, ({
3465  hash_unset (lcm->pending_map_requests_by_nonce, nonce[0]);
3466  }));
3467 
3468  vec_add1 (to_be_removed, pmr - lcm->pending_map_requests_pool);
3469  }
3470  }));
3471  /* *INDENT-ON* */
3472 
3473  vec_foreach (pmr_index, to_be_removed)
3474  pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]);
3475 
3476  vec_free (to_be_removed);
3477 }
3478 
3479 static uword
3482 {
3483  f64 period = 2.0;
3484  pending_map_request_t *pmr;
3486 
3487  while (1)
3488  {
3490 
3491  /* currently no signals are expected - just wait for clock */
3492  (void) vlib_process_get_events (vm, 0);
3493 
3495 
3496  /* *INDENT-OFF* */
3498  ({
3499  if (!pmr->to_be_removed)
3500  update_pending_request (pmr, period);
3501  }));
3502  /* *INDENT-ON* */
3503 
3505 
3507  }
3508 
3509  /* unreachable */
3510  return 0;
3511 }
3512 
3513 /* *INDENT-OFF* */
3515  .function = send_map_resolver_service,
3516  .type = VLIB_NODE_TYPE_PROCESS,
3517  .name = "lisp-retry-service",
3518  .process_log2_n_stack_bytes = 16,
3519 };
3520 /* *INDENT-ON* */
3521 
3523 
3524 /*
3525  * fd.io coding-style-patch-verification: ON
3526  *
3527  * Local Variables:
3528  * eval: (c-set-style "gnu")
3529  * End:
3530  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
#define MREQ_SMR(h_)
static clib_error_t * lisp_show_map_resolvers_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1251
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:622
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:422
ip4_fib_t * find_ip4_fib_by_table_index_or_id(ip4_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv4 fib.
Definition: ip4_forward.c:120
#define MREQ_ITR_RLOC_COUNT(h_)
static uword lisp_cp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3248
#define gid_address_ip_version(_a)
Definition: lisp_types.h:209
#define vec_foreach_index(var, v)
Iterate over vector indices.
u32 pitr_map_index
Definition: control.h:136
#define MREP_REC_COUNT(h_)
#define hash_set(h, key, value)
Definition: hash.h:254
l2_input_config_t * configs
Definition: l2_input.h:66
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_fifo_head(v)
Definition: fifo.h:254
#define gid_address_type(_a)
Definition: lisp_types.h:205
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static clib_error_t * lisp_pitr_set_locator_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1317
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:682
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
gid_address_t deid
Definition: control.c:26
lisp_cp_lookup_next_t
Definition: control.c:2488
ip4_address_t src_address
Definition: ip4_packet.h:138
static uword clib_fifo_elts(void *v)
Definition: fifo.h:66
ip_address_t active_map_resolver
Definition: control.h:116
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define MAP_REC_TTL(h)
gid_address_t dst_eid
Definition: control.c:3085
void * pkt_push_udp_and_ip(vlib_main_t *vm, vlib_buffer_t *b, u16 sp, u16 dp, ip_address_t *sip, ip_address_t *dip)
Definition: packets.c:226
#define MREQ_REC_COUNT(h_)
static vlib_buffer_t * build_encapsulated_map_request(lisp_cp_main_t *lcm, gid_address_t *seid, gid_address_t *deid, locator_set_t *loc_set, ip_address_t *mr_ip, ip_address_t *sloc, u8 is_smr_invoked, u64 *nonce_res, u32 *bi_res)
Definition: control.c:2596
ip_lookup_next_t lookup_next_index
Definition: lookup.h:180
u32 table_id
Definition: ip4.h:59
int vnet_lisp_gpe_add_del_fwd_entry(vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u32 *hw_if_indexp)
Definition: lisp_gpe.c:539
locator_pair_t * locator_pairs
Definition: control.h:42
IP unicast adjacency.
Definition: lookup.h:164
uword * table_id_by_vni
Definition: control.h:124
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
clib_error_t * vnet_lisp_gpe_enable_disable(vnet_lisp_gpe_enable_disable_args_t *a)
Definition: lisp_gpe.c:797
#define NULL
Definition: clib.h:55
#define foreach_lisp_cp_input_error
Definition: control.c:3059
static clib_error_t * lisp_show_status_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1983
u32 * local_mappings_indexes
Definition: control.h:93
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
locator_t * locator_pool
Definition: control.h:78
#define PENDING_MREQ_QUEUE_LEN
Definition: control.h:25
u8 src_address[6]
Definition: packet.h:54
static int elect_map_resolver(lisp_cp_main_t *lcm)
Definition: control.c:2645
uword unformat_ip_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:147
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
Definition: control.h:38
lisp_cp_input_next_t
Definition: control.c:3077
u32 ip_fib_get_egress_iface_for_dst(lisp_cp_main_t *lcm, ip_address_t *dst)
Find the sw_if_index of the interface that would be used to egress towards dst.
Definition: control.c:115
#define hash_set_mem(h, key, value)
Definition: hash.h:274
static char * lisp_cp_input_error_strings[]
Definition: control.c:3063
ip_lookup_main_t lookup_main
Definition: ip4.h:115
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:123
unformat_function_t unformat_vnet_sw_interface
static void remove_dead_pending_map_requests(lisp_cp_main_t *lcm)
Definition: control.c:3451
vlib_error_t * errors
Definition: node.h:418
uword * vni_by_table_id
Definition: control.h:125
uword * dp_intf_by_vni
Definition: control.h:132
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
static uword lisp_cp_lookup(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:2946
static clib_error_t * lisp_add_del_locator_in_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2103
ip6_address_t src_address
Definition: ip6_packet.h:298
#define ip_prefix_version(_a)
Definition: lisp_types.h:59
format_function_t format_vnet_sw_if_index_name
void gid_dictionary_init(gid_dictionary_t *db)
static clib_error_t * lisp_eid_table_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:699
static void clean_locator_to_locator_set(lisp_cp_main_t *lcm, u32 lsi)
Definition: control.c:1554
int vnet_lisp_add_del_adjacency(vnet_lisp_add_del_adjacency_args_t *a)
Definition: control.c:989
#define NUMBER_OF_RETRIES
Definition: control.h:23
static clib_error_t * lisp_cp_show_locator_sets_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2177
map_resolver_t * map_resolvers
Definition: control.h:110
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:1541
uword unformat_negative_mapping_action(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:306
static void reset_pending_mr_counters(pending_map_request_t *r)
Definition: control.c:2638
u32 ** locator_to_locator_sets
Definition: control.h:84
vlib_main_t * vlib_main
Definition: control.h:144
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
vlib_node_registration_t lisp_cp_lookup_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_node)
Definition: control.c:3038
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
static clib_error_t * lisp_add_del_local_eid_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:555
static void queue_map_reply(vlib_buffer_t *b)
Definition: control.c:3234
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:525
#define always_inline
Definition: clib.h:84
int ip_fib_get_first_egress_ip_for_dst(lisp_cp_main_t *lcm, ip_address_t *dst, ip_address_t *result)
Find first IP of the interface that would be used to egress towards dst.
Definition: control.c:130
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
u16 bd_id
Definition: lisp_gpe.h:293
ip4_address_t dst_address
Definition: ip4_packet.h:138
u8 dst_address[6]
Definition: packet.h:53
u8 is_add
Definition: lisp_gpe.h:267
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:407
void di(unformat_input_t *i)
Definition: unformat.c:163
volatile u32 * pending_map_request_lock
Definition: control.h:107
ip6_fib_t * find_ip6_fib_by_table_index_or_id(ip6_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv6 fib.
Definition: ip6_forward.c:185
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u32 * fwd_entry_by_mapping_index
Definition: control.h:97
u32 ip4_fib_lookup_with_table(ip4_main_t *im, u32 fib_index, ip4_address_t *dst, u32 disable_default_route)
Definition: ip4_forward.c:58
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1321
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
int vlib_main(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:1572
int vnet_lisp_eid_table_map(u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
Definition: control.c:643
static u32 get_locator_pairs(lisp_cp_main_t *lcm, mapping_t *lcl_map, mapping_t *rmt_map, locator_pair_t **locator_pairs)
Finds first remote locator with best (lowest) priority that has a local peer locator with an underlyi...
Definition: control.c:255
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
uword * bd_id_by_vni
Definition: control.h:128
#define ip_addr_v4(_a)
Definition: lisp_types.h:41
void * lisp_msg_put_mreq(lisp_cp_main_t *lcm, vlib_buffer_t *b, gid_address_t *seid, gid_address_t *deid, gid_address_t *rlocs, u8 is_smr_invoked, u64 *nonce)
static lisp_cp_main_t * vnet_lisp_cp_get_main()
Definition: control.h:157
#define vlib_call_init_function(vm, x)
Definition: init.h:161
static void * send_map_request_thread_fn(void *arg)
Definition: control.c:3363
uword * vni_by_bd_id
Definition: control.h:129
Definition: lisp_gpe.h:265
gid_address_t src
Definition: control.h:29
#define ip_addr_version(_a)
Definition: lisp_types.h:43
ip6_main_t * im6
Definition: control.h:143
static void update_pending_request(pending_map_request_t *r, f64 dt)
Take an action with a pending map request depending on expiration time and re-try counters...
Definition: control.c:3401
clib_error_t * vnet_lisp_enable_disable(u8 is_enable)
Definition: control.c:1884
static clib_error_t * lisp_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1927
u32 gid_dictionary_lookup(gid_dictionary_t *db, gid_address_t *key)
#define hash_get(h, key)
Definition: hash.h:248
int vnet_lisp_pitr_set_locator_set(u8 *locator_set_name, u8 is_add)
Definition: control.c:1274
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
#define hash_unset_mem(h, key)
Definition: hash.h:280
lisp_cp_lookup_error_t
Definition: control.c:2480
u8 do_map_resolver_election
Definition: control.h:118
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
u32 table_id
Definition: lisp_gpe.h:292
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
u32 gid_dictionary_add_del(gid_dictionary_t *db, gid_address_t *key, u32 value, u8 is_add)
#define gid_address_mac(_a)
Definition: lisp_types.h:211
int get_mr_and_local_iface_ip(lisp_cp_main_t *lcm, ip_address_t *mr_ip, ip_address_t *sloc)
Definition: control.c:2516
int vnet_lisp_map_cache_add_del(vnet_lisp_add_del_mapping_args_t *a, u32 *map_index_result)
Add/remove mapping to/from map-cache.
Definition: control.c:422
#define MAP_REC_AUTH(h)
int vnet_lisp_add_del_local_mapping(vnet_lisp_add_del_mapping_args_t *a, u32 *map_index_result)
Add/update/delete mapping to/in/from map-cache.
Definition: control.c:521
u32 lisp_msg_parse_addr(vlib_buffer_t *b, gid_address_t *eid)
static vlib_node_registration_t lisp_retry_service_node
(constructor) VLIB_REGISTER_NODE (lisp_retry_service_node)
Definition: control.c:3514
vlib_node_registration_t lisp_cp_input_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_input_node)
Definition: control.c:3308
#define hash_free(h)
Definition: hash.h:286
void gid_address_free(gid_address_t *a)
Definition: lisp_types.c:645
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
u8 authoritative
Definition: lisp_types.h:287
#define unformat_parse_error(input)
Definition: format.h:267
u32 * local_locator_set_indexes
Definition: control.h:94
#define PREDICT_FALSE(x)
Definition: clib.h:97
uword unformat_gid_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:271
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:765
u8 * format_gid_address(u8 *s, va_list *args)
Definition: lisp_types.c:224
ip_address_t lcl_loc
Definition: lisp_types.h:300
static u8 compare_locators(lisp_cp_main_t *lcm, u32 *old_ls_indexes, locator_t *new_locators)
Definition: control.c:740
#define foreach_lisp_cp_lookup_error
Definition: control.c:2470
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
#define MAX_LISP_MSG_ENCAP_LEN
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:348
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
ip_address_t map_resolver_ip
Definition: control.c:2499
int vnet_lisp_add_del_mapping(gid_address_t *eid, locator_t *rlocs, u8 action, u8 authoritative, u32 ttl, u8 is_add, u8 is_static, u32 *res_map_index)
Adds/removes/updates mapping.
Definition: control.c:776
#define clib_fifo_foreach(v, f, body)
Definition: fifo.h:279
u32 decap_next_index
Definition: lisp_gpe.h:284
static clib_error_t * lisp_add_del_map_resolver_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2298
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:118
static int queue_map_request(gid_address_t *seid, gid_address_t *deid, u8 smr_invoked, u8 is_resend)
Definition: control.c:3381
#define ip_addr_v6(_a)
Definition: lisp_types.h:42
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1111
static void remove_locator_from_locator_set(locator_set_t *ls, u32 *locit, u32 ls_index, u32 loc_id)
Definition: control.c:1638
static clib_error_t * lisp_show_eid_table_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2003
#define gid_address_ippref(_a)
Definition: lisp_types.h:206
static void * vlib_buffer_pull(vlib_buffer_t *b, u8 size)
Definition: packets.h:64
u8 is_negative
Definition: lisp_gpe.h:270
static int is_locator_in_locator_set(lisp_cp_main_t *lcm, locator_set_t *ls, locator_t *loc)
Definition: control.c:1614
#define pool_free(p)
Free a pool.
Definition: pool.h:263
u32 lisp_msg_parse_itr_rlocs(vlib_buffer_t *b, gid_address_t **rlocs, u8 rloc_count)
u32 sw_if_index
Definition: lisp_types.h:254
clib_error_t * lisp_cp_init(vlib_main_t *vm)
Definition: control.c:3327
static clib_error_t * lisp_add_del_mreq_itr_rlocs_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2387
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Definition: packets.h:56
u32 vni
Definition: lisp_gpe.h:287
uword * pending_map_requests_by_nonce
Definition: control.h:103
static void dp_add_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:347
int vnet_lisp_add_del_mreq_itr_rlocs(vnet_lisp_add_del_mreq_itr_rloc_args_t *a)
Definition: control.c:2356
u16 n_vectors
Definition: node.h:344
int lisp_add_del_adjacency(lisp_cp_main_t *lcm, gid_address_t *local_eid, gid_address_t *remote_eid, u8 is_add)
Adds adjacency or removes forwarding entry associated to remote mapping.
Definition: control.c:940
u8 * format_lisp_cp_input_trace(u8 *s, va_list *args)
Definition: control.c:3090
#define MAP_REC_ACTION(h)
int gid_address_cmp(gid_address_t *a1, gid_address_t *a2)
Definition: lisp_types.c:1319
static void lisp_pending_map_request_lock(lisp_cp_main_t *lcm)
Definition: control.h:244
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
#define gid_address_ippref_len(_a)
Definition: lisp_types.h:207
Definition: ip6.h:64
vnet_main_t * vnet_main
Definition: lisp_gpe.h:212
Definition: ip4.h:48
u32 lisp_msg_parse_mapping_record(vlib_buffer_t *b, gid_address_t *eid, locator_t **locs, locator_t *probed_)
gid_address_t deid
Definition: control.h:41
static void lisp_pending_map_request_unlock(lisp_cp_main_t *lcm)
Definition: control.h:252
u32 locator_set_index
Definition: lisp_types.h:283
void * lisp_msg_push_ecm(vlib_main_t *vm, vlib_buffer_t *b, int lp, int rp, gid_address_t *la, gid_address_t *ra)
#define clib_memcpy(a, b, c)
Definition: string.h:63
u32 locator_cmp(locator_t *l1, locator_t *l2)
Definition: lisp_types.c:1400
static map_resolver_t * get_map_resolver(ip_address_t *a)
Definition: control.c:2234
u32 ip6_fib_lookup_with_table(ip6_main_t *im, u32 fib_index, ip6_address_t *dst)
Definition: ip6_forward.c:61
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
int vnet_lisp_gpe_add_del_iface(vnet_lisp_gpe_add_del_iface_args_t *a, u32 *hw_if_indexp)
Definition: interface.c:1060
ip4_address_t map_resolver_ip
Definition: control.c:3086
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:73
lisp_gpe_main_t lisp_gpe_main
Definition: lisp_gpe.c:19
void * ip_interface_get_first_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 version)
Definition: control.c:50
u8 vnet_lisp_enable_disable_status(void)
Definition: control.c:1969
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:1381
static uword send_map_resolver_service(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: control.c:3480
struct _gid_address_t gid_address_t
uword unformat_mac_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:188
u8 * format_vnet_lisp_gpe_status(u8 *s, va_list *args)
Definition: lisp_gpe.c:979
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:228
int ip_interface_get_first_ip_address(lisp_cp_main_t *lcm, u32 sw_if_index, u8 version, ip_address_t *result)
Definition: control.c:62
#define ASSERT(truth)
static lisp_msg_type_e lisp_msg_type(void *b)
unsigned int u32
Definition: types.h:88
u8 * format_ip_address(u8 *s, va_list *args)
Definition: lisp_types.c:127
#define GID_LOOKUP_MISS
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:335
int vnet_lisp_clear_all_remote_adjacencies(void)
Definition: control.c:889
ip6_main_t ip6_main
Definition: ip6_forward.c:2955
ip_lookup_main_t lookup_main
Definition: ip6.h:110
gid_address_t seid
Definition: control.c:25
static void get_src_and_dst_ip(void *hdr, ip_address_t *src, ip_address_t *dst)
Definition: control.c:2815
clib_error_t * lisp_gpe_init(vlib_main_t *vm)
Definition: lisp_gpe.c:986
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
ip_address_t address
Definition: control.h:55
gid_dictionary_t mapping_index_by_gid
Definition: control.h:72
ip_interface_address_t * ip_interface_get_first_interface_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 loop)
Definition: control.c:35
IPv4 main type.
Definition: ip4.h:114
uword * l2_dp_intf_by_vni
Definition: control.h:133
static u32 lisp_get_vni_from_buffer_ip(lisp_cp_main_t *lcm, vlib_buffer_t *b, u8 version)
Definition: control.c:2834
locator_set_t * locator_set_pool
Definition: control.h:81
static void clib_mem_free(void *p)
Definition: mem.h:154
static clib_error_t * lisp_show_mreq_itr_rlocs_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2440
u8 is_static
Definition: lisp_types.h:291
u32 ** locator_set_to_eids
Definition: control.h:90
#define LISP_CONTROL_PORT
static u8 * format_eid_entry(u8 *s, va_list *args)
Definition: control.c:1422
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
gid_address_t rmt_eid
Definition: lisp_gpe.h:275
uword unformat_ip_prefix(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:168
static clib_error_t * lisp_add_del_adjacency_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Handler for add/del adjacency CLI.
Definition: control.c:1125
#define clib_fifo_free(f)
Definition: fifo.h:257
static void * clib_mem_alloc(uword size)
Definition: mem.h:107
u32 ip_fib_get_egress_iface_for_dst_with_lm(lisp_cp_main_t *lcm, ip_address_t *dst, ip_lookup_main_t *lm)
Definition: control.c:89
fwd_entry_t * fwd_entry_pool
Definition: control.h:100
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define IP6_ROUTE_FLAG_FIB_INDEX
Definition: ip6.h:354
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
#define vec_elt(v, i)
Get vector value at index i.
pending_map_request_t * pending_map_requests_pool
Definition: control.h:106
int vnet_lisp_add_del_locator_set(vnet_lisp_add_del_locator_set_args_t *a, u32 *ls_result)
Definition: control.c:1744
#define gid_address_ip(_a)
Definition: lisp_types.h:208
Definition: defs.h:47
#define clib_fifo_add1(f, e)
Definition: fifo.h:192
unsigned short u16
Definition: types.h:57
l2input_main_t l2input_main
Definition: l2_input.c:76
#define gid_address_vni(_a)
Definition: lisp_types.h:212
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:633
static u32 lisp_get_vni_from_buffer_eth(lisp_cp_main_t *lcm, vlib_buffer_t *b)
Definition: control.c:2871
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
static uword * get_locator_set_index(vnet_lisp_add_del_locator_set_args_t *a, uword *p)
Definition: control.c:1593
void locator_free(locator_t *l)
Definition: lisp_types.c:1418
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
static char * lisp_cp_lookup_error_strings[]
Definition: control.c:2474
unsigned char u8
Definition: types.h:56
static int dp_add_del_iface(lisp_cp_main_t *lcm, u32 vni, u8 is_l2, u8 is_add)
Definition: control.c:158
#define hash_foreach_pair(p, v, body)
Definition: hash.h:338
static void dp_del_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:221
#define IP4_ROUTE_FLAG_FIB_INDEX
Definition: ip4.h:311
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
int ip_address_cmp(ip_address_t *ip1, ip_address_t *ip2)
Definition: lisp_types.c:656
int vnet_lisp_add_del_locator(vnet_lisp_add_del_locator_set_args_t *a, locator_set_t *ls, u32 *ls_result)
Definition: control.c:1654
f64 last_update
Definition: control.h:54
locator_pair_t * locator_pairs
Definition: lisp_gpe.h:278
mapping_t * mapping_pool
Definition: control.h:75
static clib_error_t * lisp_show_eid_table_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1469
u8 ip_address_max_len(u8 version)
Definition: lisp_types.c:422
uword * locator_set_index_by_name
Definition: control.h:87
static gid_address_t * build_itr_rloc_list(lisp_cp_main_t *lcm, locator_set_t *loc_set)
Definition: control.c:2547
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:69
void gid_address_copy(gid_address_t *dst, gid_address_t *src)
Definition: lisp_types.c:1188
Definition: lisp_types.h:24
gid_address_t eid
Definition: lisp_types.h:280
gid_address_t address
Definition: lisp_types.h:255
#define hash_get_mem(h, key)
Definition: hash.h:268
void mac_copy(void *dst, void *src)
Definition: lisp_types.c:808
static void get_src_and_dst_eids_from_buffer(lisp_cp_main_t *lcm, vlib_buffer_t *b, gid_address_t *src, gid_address_t *dst)
Definition: control.c:2896
u32 lisp_msg_parse_eid_rec(vlib_buffer_t *b, gid_address_t *eid)
static clib_error_t * lisp_show_pitr_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1369
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:114
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
gid_address_t dst
Definition: control.h:30
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
int vnet_lisp_add_del_map_resolver(vnet_lisp_add_del_map_resolver_args_t *a)
Definition: control.c:2250
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1578
void process_map_request(vlib_main_t *vm, lisp_cp_main_t *lcm, vlib_buffer_t *b)
Definition: control.c:3180
ip_address_t rmt_loc
Definition: lisp_types.h:301
u8 data[0]
Packet data.
Definition: buffer.h:151
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:78
#define vec_foreach(var, vec)
Vector iterator.
u8 action
Definition: lisp_gpe.h:271
void * process_map_reply(void *arg)
Definition: control.c:3102
u32 table_id
Definition: ip6.h:66
vhost_vring_addr_t addr
Definition: vhost-user.h:82
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:461
gid_address_t dst_eid
Definition: control.c:2498
#define clib_error_return(e, args...)
Definition: error.h:111
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
struct _unformat_input_t unformat_input_t
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:601
#define MREP_NONCE(h_)
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:390
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
Definition: lisp_types.h:25
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
unformat_function_t unformat_line_input
Definition: format.h:281
static u8 * format_lisp_status(u8 *s, va_list *args)
Definition: control.c:1976
u32 * fib_index_by_sw_if_index
Definition: ip6.h:123
u32 mreq_itr_rlocs
Definition: control.h:121
static u32 ip_fib_lookup_with_table(lisp_cp_main_t *lcm, u32 fib_index, ip_address_t *dst)
Definition: control.c:78
void ip_address_set(ip_address_t *dst, void *src, u8 version)
Definition: lisp_types.c:685
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
u32 * locator_indices
Definition: lisp_types.h:274
#define send_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:2661
vnet_main_t * vnet_main
Definition: control.h:145
static clib_error_t * lisp_add_del_locator_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2031
u8 * format_lisp_cp_lookup_trace(u8 *s, va_list *args)
Definition: control.c:2503
ip4_main_t * im4
Definition: control.h:142
void ip_address_copy(ip_address_t *dst, ip_address_t *src)
Definition: lisp_types.c:673
Definition: defs.h:46
lisp_msg_type_e
static clib_error_t * lisp_add_del_remote_mapping_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Handler for add/del remote mapping CLI.
Definition: control.c:1004
#define ip_prefix_addr(_a)
Definition: lisp_types.h:58
ip6_address_t dst_address
Definition: ip6_packet.h:298
#define resend_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:2664
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:480
#define PENDING_MREQ_EXPIRATION_TIME
Definition: control.h:24
lisp_cp_input_error_t
Definition: control.c:3069