FD.io VPP  v17.01.1-3-gc6833f8
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>
23 #include <vnet/fib/fib_entry.h>
24 #include <vnet/fib/fib_table.h>
25 
26 #include <openssl/evp.h>
27 #include <openssl/hmac.h>
28 
29 typedef struct
30 {
36 
37 typedef struct
38 {
43 
44 static int
46  gid_address_t * remote_eid, u8 is_add);
47 
48 u8
50 {
52  return lcm->map_request_mode;
53 }
54 
55 static u16
57 {
58  switch (key_id)
59  {
60  case HMAC_SHA_1_96:
61  return SHA1_AUTH_DATA_LEN;
62  case HMAC_SHA_256_128:
63  return SHA256_AUTH_DATA_LEN;
64  default:
65  clib_warning ("unsupported key type: %d!", key_id);
66  return (u16) ~ 0;
67  }
68  return (u16) ~ 0;
69 }
70 
71 static const EVP_MD *
73 {
74  switch (key_id)
75  {
76  case HMAC_SHA_1_96:
77  return EVP_sha1 ();
78  case HMAC_SHA_256_128:
79  return EVP_sha256 ();
80  default:
81  clib_warning ("unsupported encryption key type: %d!", key_id);
82  break;
83  }
84  return 0;
85 }
86 
87 static int
89  u8 smr_invoked, u8 is_resend);
90 
93  u32 sw_if_index, u8 loop)
94 {
95  vnet_main_t *vnm = vnet_get_main ();
96  vnet_sw_interface_t *swif = vnet_get_sw_interface (vnm, sw_if_index);
97  if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
98  sw_if_index = swif->unnumbered_sw_if_index;
99  u32 ia =
100  (vec_len ((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
101  vec_elt ((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
102  (u32) ~ 0;
103  return pool_elt_at_index ((lm)->if_address_pool, ia);
104 }
105 
106 void *
108  u8 version)
109 {
111 
112  ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
113  if (!ia)
114  return 0;
115  return ip_interface_address_get_address (lm, ia);
116 }
117 
118 int
120  u8 version, ip_address_t * result)
121 {
122  ip_lookup_main_t *lm;
123  void *addr;
124 
125  lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
126  addr = ip_interface_get_first_address (lm, sw_if_index, version);
127  if (!addr)
128  return 0;
129 
130  ip_address_set (result, addr, version);
131  return 1;
132 }
133 
134 /**
135  * convert from a LISP address to a FIB prefix
136  */
137 void
138 ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
139 {
140  if (addr->version == IP4)
141  {
142  prefix->fp_len = 32;
143  prefix->fp_proto = FIB_PROTOCOL_IP4;
144  memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
145  memcpy (&prefix->fp_addr.ip4, &addr->ip, sizeof (prefix->fp_addr.ip4));
146  }
147  else
148  {
149  prefix->fp_len = 128;
150  prefix->fp_proto = FIB_PROTOCOL_IP6;
151  memcpy (&prefix->fp_addr.ip6, &addr->ip, sizeof (prefix->fp_addr.ip6));
152  }
153 }
154 
155 /**
156  * convert from a LISP to a FIB prefix
157  */
158 void
159 ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
160  fib_prefix_t * fib_prefix)
161 {
162  ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
163  fib_prefix->fp_len = ip_prefix->len;
164 }
165 
166 /**
167  * Find the sw_if_index of the interface that would be used to egress towards
168  * dst.
169  */
170 u32
172 {
173  fib_node_index_t fei;
174  fib_prefix_t prefix;
175 
176  ip_address_to_fib_prefix (dst, &prefix);
177 
178  fei = fib_table_lookup (0, &prefix);
179 
180  return (fib_entry_get_resolving_interface (fei));
181 }
182 
183 /**
184  * Find first IP of the interface that would be used to egress towards dst.
185  * Returns 1 if the address is found 0 otherwise.
186  */
187 int
189  ip_address_t * result)
190 {
191  u32 si;
192  ip_lookup_main_t *lm;
193  void *addr = 0;
194  u8 ipver;
195 
196  ASSERT (result != 0);
197 
198  ipver = ip_addr_version (dst);
199 
200  lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
201  si = ip_fib_get_egress_iface_for_dst (lcm, dst);
202 
203  if ((u32) ~ 0 == si)
204  return 0;
205 
206  /* find the first ip address */
207  addr = ip_interface_get_first_address (lm, si, ipver);
208  if (0 == addr)
209  return 0;
210 
211  ip_address_set (result, addr, ipver);
212  return 1;
213 }
214 
215 static int
216 dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
217 {
218  uword *dp_table;
219 
220  if (!is_l2)
221  {
222  dp_table = hash_get (lcm->table_id_by_vni, vni);
223 
224  if (!dp_table)
225  {
226  clib_warning ("vni %d not associated to a vrf!", vni);
227  return VNET_API_ERROR_INVALID_VALUE;
228  }
229  }
230  else
231  {
232  dp_table = hash_get (lcm->bd_id_by_vni, vni);
233  if (!dp_table)
234  {
235  clib_warning ("vni %d not associated to a bridge domain!", vni);
236  return VNET_API_ERROR_INVALID_VALUE;
237  }
238  }
239 
240  /* enable/disable data-plane interface */
241  if (is_add)
242  {
243  if (is_l2)
244  lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table[0]);
245  else
246  lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0]);
247  }
248  else
249  {
250  if (is_l2)
252  else
254  }
255 
256  return 0;
257 }
258 
259 static void
260 dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
261 {
263  fwd_entry_t *fe = 0;
264  uword *feip = 0;
265  memset (a, 0, sizeof (*a));
266 
267  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
268  if (!feip)
269  return;
270 
271  fe = pool_elt_at_index (lcm->fwd_entry_pool, feip[0]);
272 
273  /* delete dp fwd entry */
274  u32 sw_if_index;
275  a->is_add = 0;
276  a->locator_pairs = fe->locator_pairs;
277  a->vni = gid_address_vni (&fe->reid);
278  gid_address_copy (&a->rmt_eid, &fe->reid);
279  if (fe->is_src_dst)
280  gid_address_copy (&a->lcl_eid, &fe->leid);
281 
282  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
283 
284  /* delete entry in fwd table */
285  hash_unset (lcm->fwd_entry_by_mapping_index, dst_map_index);
286  vec_free (fe->locator_pairs);
287  pool_put (lcm->fwd_entry_pool, fe);
288 }
289 
290 /**
291  * Finds first remote locator with best (lowest) priority that has a local
292  * peer locator with an underlying route to it.
293  *
294  */
295 static u32
297  mapping_t * rmt_map, locator_pair_t ** locator_pairs)
298 {
299  u32 i, limitp = 0, li, found = 0, esi;
300  locator_set_t *rmt_ls, *lcl_ls;
301  ip_address_t _lcl_addr, *lcl_addr = &_lcl_addr;
302  locator_t *lp, *rmt = 0;
303  uword *checked = 0;
304  locator_pair_t pair;
305 
306  rmt_ls =
308  lcl_ls =
310 
311  if (!rmt_ls || vec_len (rmt_ls->locator_indices) == 0)
312  return 0;
313 
314  while (1)
315  {
316  rmt = 0;
317 
318  /* find unvisited remote locator with best priority */
319  for (i = 0; i < vec_len (rmt_ls->locator_indices); i++)
320  {
321  if (0 != hash_get (checked, i))
322  continue;
323 
324  li = vec_elt (rmt_ls->locator_indices, i);
325  lp = pool_elt_at_index (lcm->locator_pool, li);
326 
327  /* we don't support non-IP locators for now */
329  continue;
330 
331  if ((found && lp->priority == limitp)
332  || (!found && lp->priority >= limitp))
333  {
334  rmt = lp;
335 
336  /* don't search for locators with lower priority and don't
337  * check this locator again*/
338  limitp = lp->priority;
339  hash_set (checked, i, 1);
340  break;
341  }
342  }
343  /* check if a local locator with a route to remote locator exists */
344  if (rmt != 0)
345  {
346  /* find egress sw_if_index for rmt locator */
347  esi =
349  &gid_address_ip (&rmt->address));
350  if ((u32) ~ 0 == esi)
351  continue;
352 
353  for (i = 0; i < vec_len (lcl_ls->locator_indices); i++)
354  {
355  li = vec_elt (lcl_ls->locator_indices, i);
356  locator_t *sl = pool_elt_at_index (lcm->locator_pool, li);
357 
358  /* found local locator with the needed sw_if_index */
359  if (sl->sw_if_index == esi)
360  {
361  /* and it has an address */
362  if (0 == ip_interface_get_first_ip_address (lcm,
363  sl->sw_if_index,
365  (&rmt->address),
366  lcl_addr))
367  continue;
368 
369  memset (&pair, 0, sizeof (pair));
370  ip_address_copy (&pair.rmt_loc,
371  &gid_address_ip (&rmt->address));
372  ip_address_copy (&pair.lcl_loc, lcl_addr);
373  pair.weight = rmt->weight;
374  pair.priority = rmt->priority;
375  vec_add1 (locator_pairs[0], pair);
376  found = 1;
377  }
378  }
379  }
380  else
381  break;
382  }
383 
384  hash_free (checked);
385  return found;
386 }
387 
388 static void
390  fid_address_t * fid)
391 {
393 
394  dst[0] = src[0];
395 
396  switch (fid_addr_type (fid))
397  {
398  case FID_ADDR_IP_PREF:
400  gid_address_ippref (dst) = fid_addr_ippref (fid);
401  break;
402  case FID_ADDR_MAC:
404  mac_copy (gid_address_mac (dst), fid_addr_mac (fid));
405  break;
406  default:
407  clib_warning ("Unsupported fid type %d!", fid_addr_type (fid));
408  break;
409  }
410 }
411 
412 u8
414 {
416  return lcm->map_registering;
417 }
418 
419 u8
421 {
423  return lcm->rloc_probing;
424 }
425 
426 static void
427 dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
428 {
430  mapping_t *src_map, *dst_map;
431  u32 sw_if_index;
432  uword *feip = 0, *dpid;
433  fwd_entry_t *fe;
434  u8 type, is_src_dst = 0;
435 
436  memset (a, 0, sizeof (*a));
437 
438  /* remove entry if it already exists */
439  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
440  if (feip)
441  dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
442 
443  if (lcm->lisp_pitr)
444  src_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
445  else
446  src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
447  dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
448 
449  /* insert data plane forwarding entry */
450  a->is_add = 1;
451 
452  if (MR_MODE_SRC_DST == lcm->map_request_mode)
453  {
454  if (GID_ADDR_SRC_DST == gid_address_type (&dst_map->eid))
455  {
456  gid_address_sd_to_flat (&a->rmt_eid, &dst_map->eid,
457  &gid_address_sd_dst (&dst_map->eid));
458  gid_address_sd_to_flat (&a->lcl_eid, &dst_map->eid,
459  &gid_address_sd_src (&dst_map->eid));
460  }
461  else
462  {
463  gid_address_copy (&a->rmt_eid, &dst_map->eid);
464  gid_address_copy (&a->lcl_eid, &src_map->eid);
465  }
466  is_src_dst = 1;
467  }
468  else
469  gid_address_copy (&a->rmt_eid, &dst_map->eid);
470 
471  a->vni = gid_address_vni (&a->rmt_eid);
472 
473  /* get vrf or bd_index associated to vni */
474  type = gid_address_type (&a->rmt_eid);
475  if (GID_ADDR_IP_PREFIX == type)
476  {
477  dpid = hash_get (lcm->table_id_by_vni, a->vni);
478  if (!dpid)
479  {
480  clib_warning ("vni %d not associated to a vrf!", a->vni);
481  return;
482  }
483  a->table_id = dpid[0];
484  }
485  else if (GID_ADDR_MAC == type)
486  {
487  dpid = hash_get (lcm->bd_id_by_vni, a->vni);
488  if (!dpid)
489  {
490  clib_warning ("vni %d not associated to a bridge domain !", a->vni);
491  return;
492  }
493  a->bd_id = dpid[0];
494  }
495 
496  /* find best locator pair that 1) verifies LISP policy 2) are connected */
497  if (0 == get_locator_pairs (lcm, src_map, dst_map, &a->locator_pairs))
498  {
499  /* negative entry */
500  a->is_negative = 1;
501  a->action = dst_map->action;
502  }
503 
504  /* TODO remove */
506  a->decap_next_index = (ipver == IP4) ?
507  LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT;
508 
509  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
510 
511  /* add tunnel to fwd entry table XXX check return value from DP insertion */
512  pool_get (lcm->fwd_entry_pool, fe);
513  fe->locator_pairs = a->locator_pairs;
514  gid_address_copy (&fe->reid, &a->rmt_eid);
515 
516  if (is_src_dst)
517  gid_address_copy (&fe->leid, &a->lcl_eid);
518  else
519  gid_address_copy (&fe->leid, &src_map->eid);
520 
521  fe->is_src_dst = is_src_dst;
522  hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
523  fe - lcm->fwd_entry_pool);
524 }
525 
526 /**
527  * Returns vector of adjacencies.
528  *
529  * The caller must free the vector returned by this function.
530  *
531  * @param vni virtual network identifier
532  * @return vector of adjacencies
533  */
536 {
538  fwd_entry_t *fwd;
539  lisp_adjacency_t *adjs = 0, adj;
540 
541  /* *INDENT-OFF* */
542  pool_foreach(fwd, lcm->fwd_entry_pool,
543  ({
544  if (gid_address_vni (&fwd->reid) != vni)
545  continue;
546 
547  gid_address_copy (&adj.reid, &fwd->reid);
548  gid_address_copy (&adj.leid, &fwd->leid);
549  vec_add1 (adjs, adj);
550  }));
551  /* *INDENT-ON* */
552 
553  return adjs;
554 }
555 
556 static clib_error_t *
558  unformat_input_t * input,
559  vlib_cli_command_t * cmd)
560 {
561  lisp_adjacency_t *adjs, *adj;
562  vlib_cli_output (vm, "%s %40s\n", "leid", "reid");
563  unformat_input_t _line_input, *line_input = &_line_input;
564  u32 vni = ~0;
565 
566  /* Get a line of input. */
567  if (!unformat_user (input, unformat_line_input, line_input))
568  return 0;
569 
570  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
571  {
572  if (unformat (line_input, "vni %d", &vni))
573  ;
574  else
575  {
576  vlib_cli_output (vm, "parse error: '%U'",
577  format_unformat_error, line_input);
578  return 0;
579  }
580  }
581 
582  if (~0 == vni)
583  {
584  vlib_cli_output (vm, "error: no vni specified!");
585  return 0;
586  }
587 
589 
590  vec_foreach (adj, adjs)
591  {
592  vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid,
593  format_gid_address, &adj->reid);
594  }
595  vec_free (adjs);
596 
597  return 0;
598 }
599 
600 /* *INDENT-OFF* */
601 VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = {
602  .path = "show lisp adjacencies",
603  .short_help = "show lisp adjacencies",
605 };
606 /* *INDENT-ON* */
607 
608 static lisp_msmr_t *
609 get_map_server (ip_address_t * a)
610 {
612  lisp_msmr_t *m;
613 
614  vec_foreach (m, lcm->map_servers)
615  {
616  if (!ip_address_cmp (&m->address, a))
617  {
618  return m;
619  }
620  }
621  return 0;
622 }
623 
624 static lisp_msmr_t *
625 get_map_resolver (ip_address_t * a)
626 {
628  lisp_msmr_t *m;
629 
630  vec_foreach (m, lcm->map_resolvers)
631  {
632  if (!ip_address_cmp (&m->address, a))
633  {
634  return m;
635  }
636  }
637  return 0;
638 }
639 
640 int
641 vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add)
642 {
643  u32 i;
645  lisp_msmr_t _ms, *ms = &_ms;
646 
648  {
649  clib_warning ("LISP is disabled!");
650  return VNET_API_ERROR_LISP_DISABLED;
651  }
652 
653  if (is_add)
654  {
655  if (get_map_server (addr))
656  {
657  clib_warning ("map-server %U already exists!", format_ip_address,
658  addr);
659  return -1;
660  }
661 
662  memset (ms, 0, sizeof (*ms));
663  ip_address_copy (&ms->address, addr);
664  vec_add1 (lcm->map_servers, ms[0]);
665  }
666  else
667  {
668  for (i = 0; i < vec_len (lcm->map_servers); i++)
669  {
670  ms = vec_elt_at_index (lcm->map_servers, i);
671  if (!ip_address_cmp (&ms->address, addr))
672  {
673  vec_del1 (lcm->map_servers, i);
674  break;
675  }
676  }
677  }
678 
679  return 0;
680 }
681 
682 static clib_error_t *
684  unformat_input_t * input,
685  vlib_cli_command_t * cmd)
686 {
687  int rv = 0;
688  u8 is_add = 1, ip_set = 0;
689  ip_address_t ip;
690  unformat_input_t _line_input, *line_input = &_line_input;
691 
692  /* Get a line of input. */
693  if (!unformat_user (input, unformat_line_input, line_input))
694  return 0;
695 
696  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
697  {
698  if (unformat (line_input, "add"))
699  is_add = 1;
700  else if (unformat (line_input, "del"))
701  is_add = 0;
702  else if (unformat (line_input, "%U", unformat_ip_address, &ip))
703  ip_set = 1;
704  else
705  {
706  vlib_cli_output (vm, "parse error: '%U'",
707  format_unformat_error, line_input);
708  return 0;
709  }
710  }
711 
712  if (!ip_set)
713  {
714  vlib_cli_output (vm, "map-server ip address not set!");
715  return 0;
716  }
717 
718  rv = vnet_lisp_add_del_map_server (&ip, is_add);
719  if (!rv)
720  vlib_cli_output (vm, "failed to %s map-server!",
721  is_add ? "add" : "delete");
722 
723  return 0;
724 }
725 
726 /* *INDENT-OFF* */
727 VLIB_CLI_COMMAND (lisp_add_del_map_server_command) = {
728  .path = "lisp map-server",
729  .short_help = "lisp map-server add|del <ip>",
731 };
732 /* *INDENT-ON* */
733 
734 /**
735  * Add/remove mapping to/from map-cache. Overwriting not allowed.
736  */
737 int
739  u32 * map_index_result)
740 {
742  u32 mi, *map_indexp, map_index, i;
743  mapping_t *m, *old_map;
744  u32 **eid_indexes;
745 
747  old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
748  if (a->is_add)
749  {
750  /* TODO check if overwriting and take appropriate actions */
751  if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid, &a->eid))
752  {
753  clib_warning ("eid %U found in the eid-table", format_gid_address,
754  &a->eid);
755  return VNET_API_ERROR_VALUE_EXIST;
756  }
757 
758  pool_get (lcm->mapping_pool, m);
759  gid_address_copy (&m->eid, &a->eid);
761  m->ttl = a->ttl;
762  m->action = a->action;
763  m->local = a->local;
764  m->is_static = a->is_static;
765  m->key = vec_dup (a->key);
766  m->key_id = a->key_id;
767 
768  map_index = m - lcm->mapping_pool;
769  gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
770  1);
771 
773  {
774  clib_warning ("Locator set with index %d doesn't exist",
775  a->locator_set_index);
776  return VNET_API_ERROR_INVALID_VALUE;
777  }
778 
779  /* add eid to list of eids supported by locator-set */
781  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
782  a->locator_set_index);
783  vec_add1 (eid_indexes[0], map_index);
784 
785  if (a->local)
786  {
787  /* mark as local */
788  vec_add1 (lcm->local_mappings_indexes, map_index);
789  }
790  map_index_result[0] = map_index;
791  }
792  else
793  {
794  if (mi == GID_LOOKUP_MISS)
795  {
796  clib_warning ("eid %U not found in the eid-table",
797  format_gid_address, &a->eid);
798  return VNET_API_ERROR_INVALID_VALUE;
799  }
800 
801  /* clear locator-set to eids binding */
802  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
803  a->locator_set_index);
804  for (i = 0; i < vec_len (eid_indexes[0]); i++)
805  {
806  map_indexp = vec_elt_at_index (eid_indexes[0], i);
807  if (map_indexp[0] == mi)
808  break;
809  }
810  vec_del1 (eid_indexes[0], i);
811 
812  /* remove local mark if needed */
813  m = pool_elt_at_index (lcm->mapping_pool, mi);
814  if (m->local)
815  {
816  u32 k, *lm_indexp;
817  for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
818  {
819  lm_indexp = vec_elt_at_index (lcm->local_mappings_indexes, k);
820  if (lm_indexp[0] == mi)
821  break;
822  }
824  }
825 
826  /* remove mapping from dictionary */
828  gid_address_free (&m->eid);
829  pool_put_index (lcm->mapping_pool, mi);
830  }
831 
832  return 0;
833 }
834 
835 /**
836  * Add/update/delete mapping to/in/from map-cache.
837  */
838 int
840  u32 * map_index_result)
841 {
842  uword *dp_table = 0;
843  u32 vni;
844  u8 type;
845 
847 
849  {
850  clib_warning ("LISP is disabled!");
851  return VNET_API_ERROR_LISP_DISABLED;
852  }
853 
854  vni = gid_address_vni (&a->eid);
855  type = gid_address_type (&a->eid);
856  if (GID_ADDR_IP_PREFIX == type)
857  dp_table = hash_get (lcm->table_id_by_vni, vni);
858  else if (GID_ADDR_MAC == type)
859  dp_table = hash_get (lcm->bd_id_by_vni, vni);
860 
861  if (!dp_table)
862  {
863  clib_warning ("vni %d not associated to a %s!", vni,
864  GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
865  return VNET_API_ERROR_INVALID_VALUE;
866  }
867 
868  /* store/remove mapping from map-cache */
869  return vnet_lisp_map_cache_add_del (a, map_index_result);
870 }
871 
872 static clib_error_t *
874  vlib_cli_command_t * cmd)
875 {
877  unformat_input_t _line_input, *line_input = &_line_input;
878  u8 is_add = 1;
879  gid_address_t eid;
880  gid_address_t *eids = 0;
881  clib_error_t *error = 0;
882  u8 *locator_set_name = 0;
883  u32 locator_set_index = 0, map_index = 0;
884  uword *p;
886  int rv = 0;
887  u32 vni = 0;
888  u8 *key = 0;
889  u32 key_id = 0;
890 
891  memset (&eid, 0, sizeof (eid));
892  memset (a, 0, sizeof (*a));
893 
894  /* Get a line of input. */
895  if (!unformat_user (input, unformat_line_input, line_input))
896  return 0;
897 
898  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
899  {
900  if (unformat (line_input, "add"))
901  is_add = 1;
902  else if (unformat (line_input, "del"))
903  is_add = 0;
904  else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
905  ;
906  else if (unformat (line_input, "vni %d", &vni))
907  gid_address_vni (&eid) = vni;
908  else if (unformat (line_input, "secret-key %_%v%_", &key))
909  ;
910  else if (unformat (line_input, "key-id %U", unformat_hmac_key_id,
911  &key_id))
912  ;
913  else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
914  {
915  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
916  if (!p)
917  {
918  error = clib_error_return (0, "locator-set %s doesn't exist",
919  locator_set_name);
920  goto done;
921  }
922  locator_set_index = p[0];
923  }
924  else
925  {
926  error = unformat_parse_error (line_input);
927  goto done;
928  }
929  }
930  /* XXX treat batch configuration */
931 
932  if (GID_ADDR_SRC_DST == gid_address_type (&eid))
933  {
934  error =
935  clib_error_return (0, "src/dst is not supported for local EIDs!");
936  goto done;
937  }
938 
939  if (key && (0 == key_id))
940  {
941  vlib_cli_output (vm, "invalid key_id!");
942  return 0;
943  }
944 
945  gid_address_copy (&a->eid, &eid);
946  a->is_add = is_add;
947  a->locator_set_index = locator_set_index;
948  a->local = 1;
949  a->key = key;
950  a->key_id = key_id;
951 
952  rv = vnet_lisp_add_del_local_mapping (a, &map_index);
953  if (0 != rv)
954  {
955  error = clib_error_return (0, "failed to %s local mapping!",
956  is_add ? "add" : "delete");
957  }
958 done:
959  vec_free (eids);
960  if (locator_set_name)
961  vec_free (locator_set_name);
962  gid_address_free (&a->eid);
963  vec_free (a->key);
964  return error;
965 }
966 
967 /* *INDENT-OFF* */
968 VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
969  .path = "lisp eid-table",
970  .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
971  "locator-set <locator-set> [key <secret-key> key-id sha1|sha256 ]",
973 };
974 /* *INDENT-ON* */
975 
976 int
977 vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
978 {
980  uword *dp_idp, *vnip, **dp_table_by_vni, **vni_by_dp_table;
981 
983  {
984  clib_warning ("LISP is disabled!");
985  return -1;
986  }
987 
988  dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
989  vni_by_dp_table = is_l2 ? &lcm->vni_by_bd_id : &lcm->vni_by_table_id;
990 
991  if (!is_l2 && (vni == 0 || dp_id == 0))
992  {
993  clib_warning ("can't add/del default vni-vrf mapping!");
994  return -1;
995  }
996 
997  dp_idp = hash_get (dp_table_by_vni[0], vni);
998  vnip = hash_get (vni_by_dp_table[0], dp_id);
999 
1000  if (is_add)
1001  {
1002  if (dp_idp || vnip)
1003  {
1004  clib_warning ("vni %d or vrf %d already used in vrf/vni "
1005  "mapping!", vni, dp_id);
1006  return -1;
1007  }
1008  hash_set (dp_table_by_vni[0], vni, dp_id);
1009  hash_set (vni_by_dp_table[0], dp_id, vni);
1010 
1011  /* create dp iface */
1012  dp_add_del_iface (lcm, vni, is_l2, 1);
1013  }
1014  else
1015  {
1016  if (!dp_idp || !vnip)
1017  {
1018  clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
1019  "mapping!", vni, dp_id);
1020  return -1;
1021  }
1022  hash_unset (dp_table_by_vni[0], vni);
1023  hash_unset (vni_by_dp_table[0], dp_id);
1024 
1025  /* remove dp iface */
1026  dp_add_del_iface (lcm, vni, is_l2, 0);
1027  }
1028  return 0;
1029 
1030 }
1031 
1032 static clib_error_t *
1034  unformat_input_t * input,
1035  vlib_cli_command_t * cmd)
1036 {
1037  u8 is_add = 1, is_l2 = 0;
1038  u32 vni = 0, dp_id = 0;
1039  unformat_input_t _line_input, *line_input = &_line_input;
1040 
1041  /* Get a line of input. */
1042  if (!unformat_user (input, unformat_line_input, line_input))
1043  return 0;
1044 
1045  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1046  {
1047  if (unformat (line_input, "del"))
1048  is_add = 0;
1049  else if (unformat (line_input, "vni %d", &vni))
1050  ;
1051  else if (unformat (line_input, "vrf %d", &dp_id))
1052  ;
1053  else if (unformat (line_input, "bd %d", &dp_id))
1054  is_l2 = 1;
1055  else
1056  {
1057  return unformat_parse_error (line_input);
1058  }
1059  }
1060  vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add);
1061  return 0;
1062 }
1063 
1064 /* *INDENT-OFF* */
1065 VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
1066  .path = "lisp eid-table map",
1067  .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf> | bd <bdi>",
1068  .function = lisp_eid_table_map_command_fn,
1069 };
1070 /* *INDENT-ON* */
1071 
1072 /* return 0 if the two locator sets are identical 1 otherwise */
1073 static u8
1074 compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes,
1075  locator_t * new_locators)
1076 {
1077  u32 i, old_li;
1078  locator_t *old_loc, *new_loc;
1079 
1080  if (vec_len (old_ls_indexes) != vec_len (new_locators))
1081  return 1;
1082 
1083  for (i = 0; i < vec_len (new_locators); i++)
1084  {
1085  old_li = vec_elt (old_ls_indexes, i);
1086  old_loc = pool_elt_at_index (lcm->locator_pool, old_li);
1087 
1088  new_loc = vec_elt_at_index (new_locators, i);
1089 
1090  if (locator_cmp (old_loc, new_loc))
1091  return 1;
1092  }
1093  return 0;
1094 }
1095 
1096 typedef struct
1097 {
1099  void *lcm;
1102 
1103 /**
1104  * Callback invoked when a sub-prefix is found
1105  */
1106 static void
1108 {
1109  u8 delete = 0;
1110  remove_mapping_args_t *a = arg;
1111  lisp_cp_main_t *lcm = a->lcm;
1112  mapping_t *m;
1113  locator_set_t *ls;
1114 
1115  m = pool_elt_at_index (lcm->mapping_pool, mi);
1116  if (!m)
1117  return;
1118 
1120 
1121  if (a->is_negative)
1122  {
1123  if (0 != vec_len (ls->locator_indices))
1124  delete = 1;
1125  }
1126  else
1127  {
1128  if (0 == vec_len (ls->locator_indices))
1129  delete = 1;
1130  }
1131 
1132  if (delete)
1133  vec_add1 (a->eids_to_be_deleted, m->eid);
1134 }
1135 
1136 /**
1137  * This function searches map cache and looks for IP prefixes that are subset
1138  * of the provided one. If such prefix is found depending on 'is_negative'
1139  * it does follows:
1140  *
1141  * 1) if is_negative is true and found prefix points to positive mapping,
1142  * then the mapping is removed
1143  * 2) if is_negative is false and found prefix points to negative mapping,
1144  * then the mapping is removed
1145  */
1146 static void
1148  u8 is_negative)
1149 {
1150  gid_address_t *e;
1152  memset (&a, 0, sizeof (a));
1153 
1154  /* do this only in src/dst mode ... */
1155  if (MR_MODE_SRC_DST != lcm->map_request_mode)
1156  return;
1157 
1158  /* ... and only for IP prefix */
1159  if (GID_ADDR_SRC_DST != gid_address_type (eid)
1161  return;
1162 
1163  a.is_negative = is_negative;
1164  a.lcm = lcm;
1165 
1168 
1170  {
1171  lisp_add_del_adjacency (lcm, 0, e, 0 /* is_add */ );
1172  vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0);
1173  }
1174 
1176 }
1177 
1178 static void
1180 {
1181  timing_wheel_delete (&lcm->wheel, mi);
1182 }
1183 
1184 /**
1185  * Adds/removes/updates mapping. Does not program forwarding.
1186  *
1187  * @param eid end-host identifier
1188  * @param rlocs vector of remote locators
1189  * @param action action for negative map-reply
1190  * @param is_add add mapping if non-zero, delete otherwise
1191  * @param res_map_index the map-index that was created/updated/removed. It is
1192  * set to ~0 if no action is taken.
1193  * @param is_static used for distinguishing between statically learned
1194  remote mappings and mappings obtained from MR
1195  * @return return code
1196  */
1197 int
1199  u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
1200  u32 * res_map_index)
1201 {
1202  vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
1203  vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
1205  u32 mi, ls_index = 0, dst_map_index;
1206  mapping_t *old_map;
1207 
1208  if (vnet_lisp_enable_disable_status () == 0)
1209  {
1210  clib_warning ("LISP is disabled!");
1211  return VNET_API_ERROR_LISP_DISABLED;
1212  }
1213 
1214  if (res_map_index)
1215  res_map_index[0] = ~0;
1216 
1217  memset (m_args, 0, sizeof (m_args[0]));
1218  memset (ls_args, 0, sizeof (ls_args[0]));
1219 
1220  ls_args->locators = rlocs;
1221 
1222  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
1223  old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
1224 
1225  if (is_add)
1226  {
1227  /* overwrite: if mapping already exists, decide if locators should be
1228  * updated and be done */
1229  if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
1230  {
1231  if (!is_static && (old_map->is_static || old_map->local))
1232  {
1233  /* do not overwrite local or static remote mappings */
1234  clib_warning ("mapping %U rejected due to collision with local "
1235  "or static remote mapping!", format_gid_address,
1236  eid);
1237  return 0;
1238  }
1239 
1240  locator_set_t *old_ls;
1241 
1242  /* update mapping attributes */
1243  old_map->action = action;
1244  old_map->authoritative = authoritative;
1245  old_map->ttl = ttl;
1246 
1247  old_ls = pool_elt_at_index (lcm->locator_set_pool,
1248  old_map->locator_set_index);
1249  if (compare_locators (lcm, old_ls->locator_indices,
1250  ls_args->locators))
1251  {
1252  /* set locator-set index to overwrite */
1253  ls_args->is_add = 1;
1254  ls_args->index = old_map->locator_set_index;
1255  vnet_lisp_add_del_locator_set (ls_args, 0);
1256  if (res_map_index)
1257  res_map_index[0] = mi;
1258  }
1259  }
1260  /* new mapping */
1261  else
1262  {
1263  remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators);
1264 
1265  ls_args->is_add = 1;
1266  ls_args->index = ~0;
1267 
1268  vnet_lisp_add_del_locator_set (ls_args, &ls_index);
1269 
1270  /* add mapping */
1271  gid_address_copy (&m_args->eid, eid);
1272  m_args->is_add = 1;
1273  m_args->action = action;
1274  m_args->locator_set_index = ls_index;
1275  m_args->is_static = is_static;
1276  m_args->ttl = ttl;
1277  vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
1278 
1279  if (res_map_index)
1280  res_map_index[0] = dst_map_index;
1281  }
1282  }
1283  else
1284  {
1285  if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
1286  {
1287  clib_warning ("cannot delete mapping for eid %U",
1288  format_gid_address, eid);
1289  return -1;
1290  }
1291 
1292  m_args->is_add = 0;
1293  gid_address_copy (&m_args->eid, eid);
1294  m_args->locator_set_index = old_map->locator_set_index;
1295 
1296  /* delete mapping associated from map-cache */
1297  vnet_lisp_map_cache_add_del (m_args, 0);
1298 
1299  ls_args->is_add = 0;
1300  ls_args->index = old_map->locator_set_index;
1301  /* delete locator set */
1302  vnet_lisp_add_del_locator_set (ls_args, 0);
1303 
1304  /* delete timer associated to the mapping if any */
1305  if (old_map->timer_set)
1306  mapping_delete_timer (lcm, mi);
1307 
1308  /* return old mapping index */
1309  if (res_map_index)
1310  res_map_index[0] = mi;
1311  }
1312 
1313  /* success */
1314  return 0;
1315 }
1316 
1317 int
1319 {
1320  int rv = 0;
1321  u32 mi, *map_indices = 0, *map_indexp;
1323  vnet_lisp_add_del_mapping_args_t _dm_args, *dm_args = &_dm_args;
1324  vnet_lisp_add_del_locator_set_args_t _ls, *ls = &_ls;
1325 
1326  /* *INDENT-OFF* */
1327  pool_foreach_index (mi, lcm->mapping_pool,
1328  ({
1329  vec_add1 (map_indices, mi);
1330  }));
1331  /* *INDENT-ON* */
1332 
1333  vec_foreach (map_indexp, map_indices)
1334  {
1335  mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
1336  if (!map->local)
1337  {
1338  dp_del_fwd_entry (lcm, 0, map_indexp[0]);
1339 
1340  dm_args->is_add = 0;
1341  gid_address_copy (&dm_args->eid, &map->eid);
1342  dm_args->locator_set_index = map->locator_set_index;
1343 
1344  /* delete mapping associated to fwd entry */
1345  vnet_lisp_map_cache_add_del (dm_args, 0);
1346 
1347  ls->is_add = 0;
1348  ls->local = 0;
1349  ls->index = map->locator_set_index;
1350  /* delete locator set */
1351  rv = vnet_lisp_add_del_locator_set (ls, 0);
1352  if (rv != 0)
1353  goto cleanup;
1354  }
1355  }
1356 
1357 cleanup:
1358  if (map_indices)
1359  vec_free (map_indices);
1360  return rv;
1361 }
1362 
1363 /**
1364  * Adds adjacency or removes forwarding entry associated to remote mapping.
1365  * Note that adjacencies are not stored, they only result in forwarding entries
1366  * being created.
1367  */
1368 static int
1370  gid_address_t * remote_eid, u8 is_add)
1371 {
1372  u32 local_mi, remote_mi = ~0;
1373 
1374  if (vnet_lisp_enable_disable_status () == 0)
1375  {
1376  clib_warning ("LISP is disabled!");
1377  return VNET_API_ERROR_LISP_DISABLED;
1378  }
1379 
1381  remote_eid, local_eid);
1382  if (GID_LOOKUP_MISS == remote_mi)
1383  {
1384  clib_warning ("Remote eid %U not found. Cannot add adjacency!",
1385  format_gid_address, remote_eid);
1386 
1387  return -1;
1388  }
1389 
1390  if (is_add)
1391  {
1392  /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
1393  * delete*/
1394 
1395  /* check if source eid has an associated mapping. If pitr mode is on,
1396  * just use the pitr's mapping */
1397  local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
1398  gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid);
1399 
1400 
1401  if (GID_LOOKUP_MISS == local_mi)
1402  {
1403  clib_warning ("Local eid %U not found. Cannot add adjacency!",
1404  format_gid_address, local_eid);
1405 
1406  return -1;
1407  }
1408 
1409  /* update forwarding */
1410  dp_add_fwd_entry (lcm, local_mi, remote_mi);
1411  }
1412  else
1413  dp_del_fwd_entry (lcm, 0, remote_mi);
1414 
1415  return 0;
1416 }
1417 
1418 int
1420 {
1422  return lisp_add_del_adjacency (lcm, &a->leid, &a->reid, a->is_add);
1423 }
1424 
1425 /**
1426  * Handler for add/del remote mapping CLI.
1427  *
1428  * @param vm vlib context
1429  * @param input input from user
1430  * @param cmd cmd
1431  * @return pointer to clib error structure
1432  */
1433 static clib_error_t *
1435  unformat_input_t * input,
1436  vlib_cli_command_t * cmd)
1437 {
1438  clib_error_t *error = 0;
1439  unformat_input_t _line_input, *line_input = &_line_input;
1440  u8 is_add = 1, del_all = 0;
1441  locator_t rloc, *rlocs = 0, *curr_rloc = 0;
1442  gid_address_t eid;
1443  u8 eid_set = 0;
1444  u32 vni, action = ~0, p, w;
1445  int rv;
1446 
1447  /* Get a line of input. */
1448  if (!unformat_user (input, unformat_line_input, line_input))
1449  return 0;
1450 
1451  memset (&eid, 0, sizeof (eid));
1452  memset (&rloc, 0, sizeof (rloc));
1453 
1454  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1455  {
1456  if (unformat (line_input, "del-all"))
1457  del_all = 1;
1458  else if (unformat (line_input, "del"))
1459  is_add = 0;
1460  else if (unformat (line_input, "add"))
1461  ;
1462  else if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
1463  eid_set = 1;
1464  else if (unformat (line_input, "vni %u", &vni))
1465  {
1466  gid_address_vni (&eid) = vni;
1467  }
1468  else if (unformat (line_input, "p %d w %d", &p, &w))
1469  {
1470  if (!curr_rloc)
1471  {
1472  clib_warning
1473  ("No RLOC configured for setting priority/weight!");
1474  goto done;
1475  }
1476  curr_rloc->priority = p;
1477  curr_rloc->weight = w;
1478  }
1479  else if (unformat (line_input, "rloc %U", unformat_ip_address,
1480  &gid_address_ip (&rloc.address)))
1481  {
1482  /* since rloc is stored in ip prefix we need to set prefix length */
1483  ip_prefix_t *pref = &gid_address_ippref (&rloc.address);
1484 
1485  u8 version = gid_address_ip_version (&rloc.address);
1486  ip_prefix_len (pref) = ip_address_max_len (version);
1487 
1488  vec_add1 (rlocs, rloc);
1489  curr_rloc = &rlocs[vec_len (rlocs) - 1];
1490  }
1491  else if (unformat (line_input, "action %U",
1493  ;
1494  else
1495  {
1496  clib_warning ("parse error");
1497  goto done;
1498  }
1499  }
1500 
1501  if (!eid_set)
1502  {
1503  clib_warning ("missing eid!");
1504  goto done;
1505  }
1506 
1507  if (!del_all)
1508  {
1509  if (is_add && (~0 == action) && 0 == vec_len (rlocs))
1510  {
1511  clib_warning ("no action set for negative map-reply!");
1512  goto done;
1513  }
1514  }
1515  else
1516  {
1518  goto done;
1519  }
1520 
1521  /* TODO build src/dst with seid */
1522 
1523  /* if it's a delete, clean forwarding */
1524  if (!is_add)
1525  {
1527  rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0);
1528  if (rv)
1529  {
1530  goto done;
1531  }
1532  }
1533 
1534  /* add as static remote mapping, i.e., not authoritative and infinite
1535  * ttl */
1536  rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add,
1537  1 /* is_static */ , 0);
1538 
1539  if (rv)
1540  clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete");
1541 
1542 done:
1543  vec_free (rlocs);
1544  unformat_free (line_input);
1545  return error;
1546 }
1547 
1548 VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) =
1549 {
1550 .path = "lisp remote-mapping",.short_help =
1551  "lisp remote-mapping add|del [del-all] vni <vni> "
1552  "eid <est-eid> [action <no-action|natively-forward|"
1553  "send-map-request|drop>] rloc <dst-locator> p <prio> w <weight> "
1554  "[rloc <dst-locator> ... ]",.function =
1556 
1557 /**
1558  * Handler for add/del adjacency CLI.
1559  */
1560 static clib_error_t *
1562  vlib_cli_command_t * cmd)
1563 {
1564  clib_error_t *error = 0;
1565  unformat_input_t _line_input, *line_input = &_line_input;
1567  u8 is_add = 1;
1568  ip_prefix_t *reid_ippref, *leid_ippref;
1569  gid_address_t leid, reid;
1570  u8 *dmac = gid_address_mac (&reid);
1571  u8 *smac = gid_address_mac (&leid);
1572  u8 reid_set = 0, leid_set = 0;
1573  u32 vni;
1574  int rv;
1575 
1576  /* Get a line of input. */
1577  if (!unformat_user (input, unformat_line_input, line_input))
1578  return 0;
1579 
1580  memset (&reid, 0, sizeof (reid));
1581  memset (&leid, 0, sizeof (leid));
1582 
1583  leid_ippref = &gid_address_ippref (&leid);
1584  reid_ippref = &gid_address_ippref (&reid);
1585 
1586  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1587  {
1588  if (unformat (line_input, "del"))
1589  is_add = 0;
1590  else if (unformat (line_input, "add"))
1591  ;
1592  else if (unformat (line_input, "reid %U",
1593  unformat_ip_prefix, reid_ippref))
1594  {
1596  reid_set = 1;
1597  }
1598  else if (unformat (line_input, "reid %U", unformat_mac_address, dmac))
1599  {
1600  gid_address_type (&reid) = GID_ADDR_MAC;
1601  reid_set = 1;
1602  }
1603  else if (unformat (line_input, "vni %u", &vni))
1604  {
1605  gid_address_vni (&leid) = vni;
1606  gid_address_vni (&reid) = vni;
1607  }
1608  else if (unformat (line_input, "leid %U",
1609  unformat_ip_prefix, leid_ippref))
1610  {
1612  leid_set = 1;
1613  }
1614  else if (unformat (line_input, "leid %U", unformat_mac_address, smac))
1615  {
1616  gid_address_type (&leid) = GID_ADDR_MAC;
1617  leid_set = 1;
1618  }
1619  else
1620  {
1621  clib_warning ("parse error");
1622  goto done;
1623  }
1624  }
1625 
1626  if (!reid_set || !leid_set)
1627  {
1628  clib_warning ("missing remote or local eid!");
1629  goto done;
1630  }
1631 
1632  if ((gid_address_type (&leid) != gid_address_type (&reid))
1633  || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX
1634  && ip_prefix_version (reid_ippref)
1635  != ip_prefix_version (leid_ippref)))
1636  {
1637  clib_warning ("remote and local EIDs are of different types!");
1638  return error;
1639  }
1640 
1641  memset (a, 0, sizeof (a[0]));
1642  gid_address_copy (&a->leid, &leid);
1643  gid_address_copy (&a->reid, &reid);
1644 
1645  a->is_add = is_add;
1646  rv = vnet_lisp_add_del_adjacency (a);
1647 
1648  if (rv)
1649  clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete");
1650 
1651 done:
1652  unformat_free (line_input);
1653  return error;
1654 }
1655 
1656 /* *INDENT-OFF* */
1657 VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
1658  .path = "lisp adjacency",
1659  .short_help = "lisp adjacency add|del vni <vni> reid <remote-eid> "
1660  "leid <local-eid>",
1662 };
1663 /* *INDENT-ON* */
1664 
1665 int
1667 {
1669 
1670  if (vnet_lisp_enable_disable_status () == 0)
1671  {
1672  clib_warning ("LISP is disabled!");
1673  return VNET_API_ERROR_LISP_DISABLED;
1674  }
1675 
1676  if (mode >= _MR_MODE_MAX)
1677  {
1678  clib_warning ("Invalid LISP map request mode %d!", mode);
1679  return VNET_API_ERROR_INVALID_ARGUMENT;
1680  }
1681 
1682  lcm->map_request_mode = mode;
1683  return 0;
1684 }
1685 
1686 static clib_error_t *
1688  unformat_input_t * input,
1689  vlib_cli_command_t * cmd)
1690 {
1691  unformat_input_t _i, *i = &_i;
1692  map_request_mode_t mr_mode = _MR_MODE_MAX;
1693 
1694  /* Get a line of input. */
1695  if (!unformat_user (input, unformat_line_input, i))
1696  return 0;
1697 
1699  {
1700  if (unformat (i, "dst-only"))
1701  mr_mode = MR_MODE_DST_ONLY;
1702  else if (unformat (i, "src-dst"))
1703  mr_mode = MR_MODE_SRC_DST;
1704  else
1705  {
1706  clib_warning ("parse error '%U'", format_unformat_error, i);
1707  goto done;
1708  }
1709  }
1710 
1711  if (_MR_MODE_MAX == mr_mode)
1712  {
1713  clib_warning ("No LISP map request mode entered!");
1714  return 0;
1715  }
1716 
1718 done:
1719  return 0;
1720 }
1721 
1722 /* *INDENT-OFF* */
1723 VLIB_CLI_COMMAND (lisp_map_request_mode_command) = {
1724  .path = "lisp map-request mode",
1725  .short_help = "lisp map-request mode dst-only|src-dst",
1727 };
1728 /* *INDENT-ON* */
1729 
1730 static u8 *
1731 format_lisp_map_request_mode (u8 * s, va_list * args)
1732 {
1733  u32 mode = va_arg (*args, u32);
1734 
1735  switch (mode)
1736  {
1737  case 0:
1738  return format (0, "dst-only");
1739  case 1:
1740  return format (0, "src-dst");
1741  }
1742  return 0;
1743 }
1744 
1745 static clib_error_t *
1747  unformat_input_t * input,
1748  vlib_cli_command_t * cmd)
1749 {
1750  vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode,
1752  return 0;
1753 }
1754 
1755 /* *INDENT-OFF* */
1756 VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = {
1757  .path = "show lisp map-request mode",
1758  .short_help = "show lisp map-request mode",
1760 };
1761 /* *INDENT-ON* */
1762 
1763 static clib_error_t *
1765  unformat_input_t * input,
1766  vlib_cli_command_t * cmd)
1767 {
1768  lisp_msmr_t *mr;
1770 
1771  vec_foreach (mr, lcm->map_resolvers)
1772  {
1773  vlib_cli_output (vm, "%U", format_ip_address, &mr->address);
1774  }
1775  return 0;
1776 }
1777 
1778 /* *INDENT-OFF* */
1779 VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = {
1780  .path = "show lisp map-resolvers",
1781  .short_help = "show lisp map-resolvers",
1783 };
1784 /* *INDENT-ON* */
1785 
1786 int
1787 vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
1788 {
1790  u32 locator_set_index = ~0;
1791  mapping_t *m;
1792  uword *p;
1793 
1794  if (vnet_lisp_enable_disable_status () == 0)
1795  {
1796  clib_warning ("LISP is disabled!");
1797  return VNET_API_ERROR_LISP_DISABLED;
1798  }
1799 
1800  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1801  if (!p)
1802  {
1803  clib_warning ("locator-set %v doesn't exist", locator_set_name);
1804  return -1;
1805  }
1806  locator_set_index = p[0];
1807 
1808  if (is_add)
1809  {
1810  pool_get (lcm->mapping_pool, m);
1811  m->locator_set_index = locator_set_index;
1812  m->local = 1;
1813  lcm->pitr_map_index = m - lcm->mapping_pool;
1814 
1815  /* enable pitr mode */
1816  lcm->lisp_pitr = 1;
1817  }
1818  else
1819  {
1820  /* remove pitr mapping */
1822 
1823  /* disable pitr mode */
1824  lcm->lisp_pitr = 0;
1825  }
1826  return 0;
1827 }
1828 
1829 static clib_error_t *
1831  unformat_input_t * input,
1832  vlib_cli_command_t * cmd)
1833 {
1834  u8 locator_name_set = 0;
1835  u8 *locator_set_name = 0;
1836  u8 is_add = 1;
1837  unformat_input_t _line_input, *line_input = &_line_input;
1838  clib_error_t *error = 0;
1839  int rv = 0;
1840 
1841  /* Get a line of input. */
1842  if (!unformat_user (input, unformat_line_input, line_input))
1843  return 0;
1844 
1845  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1846  {
1847  if (unformat (line_input, "ls %_%v%_", &locator_set_name))
1848  locator_name_set = 1;
1849  else if (unformat (line_input, "disable"))
1850  is_add = 0;
1851  else
1852  return clib_error_return (0, "parse error");
1853  }
1854 
1855  if (!locator_name_set)
1856  {
1857  clib_warning ("No locator set specified!");
1858  goto done;
1859  }
1860  rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add);
1861  if (0 != rv)
1862  {
1863  error = clib_error_return (0, "failed to %s pitr!",
1864  is_add ? "add" : "delete");
1865  }
1866 
1867 done:
1868  if (locator_set_name)
1869  vec_free (locator_set_name);
1870  return error;
1871 }
1872 
1873 /* *INDENT-OFF* */
1874 VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = {
1875  .path = "lisp pitr",
1876  .short_help = "lisp pitr [disable] ls <locator-set-name>",
1878 };
1879 /* *INDENT-ON* */
1880 
1881 static clib_error_t *
1883  unformat_input_t * input, vlib_cli_command_t * cmd)
1884 {
1886  mapping_t *m;
1887  locator_set_t *ls;
1888  u8 *tmp_str = 0;
1889 
1890  vlib_cli_output (vm, "%=20s%=16s",
1891  "pitr", lcm->lisp_pitr ? "locator-set" : "");
1892 
1893  if (!lcm->lisp_pitr)
1894  {
1895  vlib_cli_output (vm, "%=20s", "disable");
1896  return 0;
1897  }
1898 
1899  if (~0 == lcm->pitr_map_index)
1900  {
1901  tmp_str = format (0, "N/A");
1902  }
1903  else
1904  {
1906  if (~0 != m->locator_set_index)
1907  {
1908  ls =
1910  tmp_str = format (0, "%s", ls->name);
1911  }
1912  else
1913  {
1914  tmp_str = format (0, "N/A");
1915  }
1916  }
1917  vec_add1 (tmp_str, 0);
1918 
1919  vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str);
1920 
1921  vec_free (tmp_str);
1922 
1923  return 0;
1924 }
1925 
1926 /* *INDENT-OFF* */
1927 VLIB_CLI_COMMAND (lisp_show_pitr_command) = {
1928  .path = "show lisp pitr",
1929  .short_help = "Show pitr",
1930  .function = lisp_show_pitr_command_fn,
1931 };
1932 /* *INDENT-ON* */
1933 
1934 static u8 *
1935 format_eid_entry (u8 * s, va_list * args)
1936 {
1937  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
1938  lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *);
1939  mapping_t *mapit = va_arg (*args, mapping_t *);
1940  locator_set_t *ls = va_arg (*args, locator_set_t *);
1941  gid_address_t *gid = &mapit->eid;
1942  u32 ttl = mapit->ttl;
1943  u8 aut = mapit->authoritative;
1944  u32 *loc_index;
1945  u8 first_line = 1;
1946  u8 *loc;
1947 
1948  u8 *type = ls->local ? format (0, "local(%s)", ls->name)
1949  : format (0, "remote");
1950 
1951  if (vec_len (ls->locator_indices) == 0)
1952  {
1953  s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid,
1954  type, ttl, aut);
1955  }
1956  else
1957  {
1958  vec_foreach (loc_index, ls->locator_indices)
1959  {
1960  locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]);
1961  if (l->local)
1962  loc = format (0, "%U", format_vnet_sw_if_index_name, vnm,
1963  l->sw_if_index);
1964  else
1965  loc = format (0, "%U", format_ip_address,
1966  &gid_address_ip (&l->address));
1967 
1968  if (first_line)
1969  {
1970  s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address,
1971  gid, type, loc, ttl, aut);
1972  first_line = 0;
1973  }
1974  else
1975  s = format (s, "%55s%v\n", "", loc);
1976  }
1977  }
1978  return s;
1979 }
1980 
1981 static clib_error_t *
1983  unformat_input_t * input,
1984  vlib_cli_command_t * cmd)
1985 {
1987  mapping_t *mapit;
1988  unformat_input_t _line_input, *line_input = &_line_input;
1989  u32 mi;
1990  gid_address_t eid;
1991  u8 print_all = 1;
1992  u8 filter = 0;
1993 
1994  memset (&eid, 0, sizeof (eid));
1995 
1996  /* Get a line of input. */
1997  if (!unformat_user (input, unformat_line_input, line_input))
1998  return 0;
1999 
2000  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2001  {
2002  if (unformat (line_input, "eid %U", unformat_gid_address, &eid))
2003  print_all = 0;
2004  else if (unformat (line_input, "local"))
2005  filter = 1;
2006  else if (unformat (line_input, "remote"))
2007  filter = 2;
2008  else
2009  return clib_error_return (0, "parse error: '%U'",
2010  format_unformat_error, line_input);
2011  }
2012 
2013  vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s",
2014  "EID", "type", "locators", "ttl", "autoritative");
2015 
2016  if (print_all)
2017  {
2018  /* *INDENT-OFF* */
2019  pool_foreach (mapit, lcm->mapping_pool,
2020  ({
2021  locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
2022  mapit->locator_set_index);
2023  if (filter && !((1 == filter && ls->local) ||
2024  (2 == filter && !ls->local)))
2025  {
2026  continue;
2027  }
2028  vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main,
2029  lcm, mapit, ls);
2030  }));
2031  /* *INDENT-ON* */
2032  }
2033  else
2034  {
2035  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid);
2036  if ((u32) ~ 0 == mi)
2037  return 0;
2038 
2039  mapit = pool_elt_at_index (lcm->mapping_pool, mi);
2040  locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool,
2041  mapit->locator_set_index);
2042 
2043  if (filter && !((1 == filter && ls->local) ||
2044  (2 == filter && !ls->local)))
2045  {
2046  return 0;
2047  }
2048 
2049  vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main,
2050  lcm, mapit, ls);
2051  }
2052 
2053  return 0;
2054 }
2055 
2056 /* *INDENT-OFF* */
2057 VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = {
2058  .path = "show lisp eid-table",
2059  .short_help = "Shows EID table",
2060  .function = lisp_show_eid_table_command_fn,
2061 };
2062 /* *INDENT-ON* */
2063 
2064 /* cleans locator to locator-set data and removes locators not part of
2065  * any locator-set */
2066 static void
2068 {
2069  u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0;
2071  for (i = 0; i < vec_len (ls->locator_indices); i++)
2072  {
2073  loc_indexp = vec_elt_at_index (ls->locator_indices, i);
2074  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
2075  loc_indexp[0]);
2076  for (j = 0; j < vec_len (ls_indexes[0]); j++)
2077  {
2078  ls_indexp = vec_elt_at_index (ls_indexes[0], j);
2079  if (ls_indexp[0] == lsi)
2080  break;
2081  }
2082 
2083  /* delete index for removed locator-set */
2084  vec_del1 (ls_indexes[0], j);
2085 
2086  /* delete locator if it's part of no locator-set */
2087  if (vec_len (ls_indexes[0]) == 0)
2088  {
2089  pool_put_index (lcm->locator_pool, loc_indexp[0]);
2090  vec_add1 (to_be_deleted, i);
2091  }
2092  }
2093 
2094  if (to_be_deleted)
2095  {
2096  for (i = 0; i < vec_len (to_be_deleted); i++)
2097  {
2098  loc_indexp = vec_elt_at_index (to_be_deleted, i);
2099  vec_del1 (ls->locator_indices, loc_indexp[0]);
2100  }
2101  vec_free (to_be_deleted);
2102  }
2103 }
2104 
2105 static inline uword *
2107 {
2109 
2110  ASSERT (a != NULL);
2111  ASSERT (p != NULL);
2112 
2113  /* find locator-set */
2114  if (a->local)
2115  {
2117  }
2118  else
2119  {
2120  *p = a->index;
2121  }
2122 
2123  return p;
2124 }
2125 
2126 static inline int
2128  locator_t * loc)
2129 {
2130  locator_t *itloc;
2131  u32 *locit;
2132 
2133  ASSERT (ls != NULL);
2134  ASSERT (loc != NULL);
2135 
2136  vec_foreach (locit, ls->locator_indices)
2137  {
2138  itloc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2139  if ((ls->local && itloc->sw_if_index == loc->sw_if_index) ||
2140  (!ls->local && !gid_address_cmp (&itloc->address, &loc->address)))
2141  {
2142  clib_warning ("Duplicate locator");
2143  return VNET_API_ERROR_VALUE_EXIST;
2144  }
2145  }
2146 
2147  return 0;
2148 }
2149 
2150 static inline void
2152  u32 ls_index, u32 loc_id)
2153 {
2155  u32 **ls_indexes = NULL;
2156 
2157  ASSERT (ls != NULL);
2158  ASSERT (locit != NULL);
2159 
2160  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, locit[0]);
2161  pool_put_index (lcm->locator_pool, locit[0]);
2162  vec_del1 (ls->locator_indices, loc_id);
2163  vec_del1 (ls_indexes[0], ls_index);
2164 }
2165 
2166 int
2168  locator_set_t * ls, u32 * ls_result)
2169 {
2171  locator_t *loc = NULL, *itloc = NULL;
2172  uword _p = (u32) ~ 0, *p = &_p;
2173  u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL;
2174  u32 loc_id = ~0;
2175  int ret = 0;
2176 
2177  ASSERT (a != NULL);
2178 
2179  if (vnet_lisp_enable_disable_status () == 0)
2180  {
2181  clib_warning ("LISP is disabled!");
2182  return VNET_API_ERROR_LISP_DISABLED;
2183  }
2184 
2185  p = get_locator_set_index (a, p);
2186  if (!p)
2187  {
2188  clib_warning ("locator-set %v doesn't exist", a->name);
2189  return VNET_API_ERROR_INVALID_ARGUMENT;
2190  }
2191 
2192  if (ls == 0)
2193  {
2194  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2195  if (!ls)
2196  {
2197  clib_warning ("locator-set %d to be overwritten doesn't exist!",
2198  p[0]);
2199  return VNET_API_ERROR_INVALID_ARGUMENT;
2200  }
2201  }
2202 
2203  if (a->is_add)
2204  {
2205  if (ls_result)
2206  ls_result[0] = p[0];
2207 
2208  /* allocate locators */
2209  vec_foreach (itloc, a->locators)
2210  {
2211  ret = is_locator_in_locator_set (lcm, ls, itloc);
2212  if (0 != ret)
2213  {
2214  return ret;
2215  }
2216 
2217  pool_get (lcm->locator_pool, loc);
2218  loc[0] = itloc[0];
2219  loc_index = loc - lcm->locator_pool;
2220 
2221  vec_add1 (ls->locator_indices, loc_index);
2222 
2223  vec_validate (lcm->locator_to_locator_sets, loc_index);
2224  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
2225  loc_index);
2226  vec_add1 (ls_indexes[0], p[0]);
2227  }
2228  }
2229  else
2230  {
2231  ls_index = p[0];
2232 
2233  itloc = a->locators;
2234  loc_id = 0;
2235  vec_foreach (locit, ls->locator_indices)
2236  {
2237  loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2238 
2239  if (loc->local && loc->sw_if_index == itloc->sw_if_index)
2240  {
2241  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
2242  }
2243  if (0 == loc->local &&
2244  !gid_address_cmp (&loc->address, &itloc->address))
2245  {
2246  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
2247  }
2248 
2249  loc_id++;
2250  }
2251  }
2252 
2253  return 0;
2254 }
2255 
2256 int
2258  u32 * ls_result)
2259 {
2261  locator_set_t *ls;
2262  uword _p = (u32) ~ 0, *p = &_p;
2263  u32 ls_index;
2264  u32 **eid_indexes;
2265  int ret = 0;
2266 
2267  if (vnet_lisp_enable_disable_status () == 0)
2268  {
2269  clib_warning ("LISP is disabled!");
2270  return VNET_API_ERROR_LISP_DISABLED;
2271  }
2272 
2273  if (a->is_add)
2274  {
2275  p = get_locator_set_index (a, p);
2276 
2277  /* overwrite */
2278  if (p && p[0] != (u32) ~ 0)
2279  {
2280  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2281  if (!ls)
2282  {
2283  clib_warning ("locator-set %d to be overwritten doesn't exist!",
2284  p[0]);
2285  return -1;
2286  }
2287 
2288  /* clean locator to locator-set vectors and remove locators if
2289  * they're not part of another locator-set */
2290  clean_locator_to_locator_set (lcm, p[0]);
2291 
2292  /* remove locator indices from locator set */
2293  vec_free (ls->locator_indices);
2294 
2295  ls_index = p[0];
2296 
2297  if (ls_result)
2298  ls_result[0] = p[0];
2299  }
2300  /* new locator-set */
2301  else
2302  {
2303  pool_get (lcm->locator_set_pool, ls);
2304  memset (ls, 0, sizeof (*ls));
2305  ls_index = ls - lcm->locator_set_pool;
2306 
2307  if (a->local)
2308  {
2309  ls->name = vec_dup (a->name);
2310 
2311  if (!lcm->locator_set_index_by_name)
2313  /* size */
2314  0,
2315  sizeof
2316  (ls->name
2317  [0]),
2318  sizeof
2319  (uword));
2321  ls_index);
2322 
2323  /* mark as local locator-set */
2324  vec_add1 (lcm->local_locator_set_indexes, ls_index);
2325  }
2326  ls->local = a->local;
2327  if (ls_result)
2328  ls_result[0] = ls_index;
2329  }
2330 
2331  ret = vnet_lisp_add_del_locator (a, ls, NULL);
2332  if (0 != ret)
2333  {
2334  return ret;
2335  }
2336  }
2337  else
2338  {
2339  p = get_locator_set_index (a, p);
2340  if (!p)
2341  {
2342  clib_warning ("locator-set %v doesn't exists", a->name);
2343  return -1;
2344  }
2345 
2346  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
2347  if (!ls)
2348  {
2349  clib_warning ("locator-set with index %d doesn't exists", p[0]);
2350  return -1;
2351  }
2352 
2353  if (lcm->mreq_itr_rlocs == p[0])
2354  {
2355  clib_warning ("Can't delete the locator-set used to constrain "
2356  "the itr-rlocs in map-requests!");
2357  return -1;
2358  }
2359 
2360  if (vec_len (lcm->locator_set_to_eids) != 0)
2361  {
2362  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]);
2363  if (vec_len (eid_indexes[0]) != 0)
2364  {
2365  clib_warning
2366  ("Can't delete a locator that supports a mapping!");
2367  return -1;
2368  }
2369  }
2370 
2371  /* clean locator to locator-sets data */
2372  clean_locator_to_locator_set (lcm, p[0]);
2373 
2374  if (ls->local)
2375  {
2376  u32 it, lsi;
2377 
2379  {
2380  lsi = vec_elt (lcm->local_locator_set_indexes, it);
2381  if (lsi == p[0])
2382  {
2384  break;
2385  }
2386  }
2388  }
2389  vec_free (ls->name);
2390  vec_free (ls->locator_indices);
2391  pool_put (lcm->locator_set_pool, ls);
2392  }
2393  return 0;
2394 }
2395 
2396 int
2398 {
2400 
2401  lcm->rloc_probing = is_enable;
2402  return 0;
2403 }
2404 
2405 int
2407 {
2409 
2410  lcm->map_registering = is_enable;
2411  return 0;
2412 }
2413 
2414 clib_error_t *
2416 {
2417  u32 vni, dp_table;
2418  clib_error_t *error = 0;
2421 
2422  a->is_en = is_enable;
2423  error = vnet_lisp_gpe_enable_disable (a);
2424  if (error)
2425  {
2426  return clib_error_return (0, "failed to %s data-plane!",
2427  a->is_en ? "enable" : "disable");
2428  }
2429 
2430  if (is_enable)
2431  {
2432  /* enable all l2 and l3 ifaces */
2433 
2434  /* *INDENT-OFF* */
2435  hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({
2436  dp_add_del_iface(lcm, vni, 0, 1);
2437  }));
2438  hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({
2439  dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1);
2440  }));
2441  /* *INDENT-ON* */
2442  }
2443  else
2444  {
2445  /* clear interface table */
2447  pool_free (lcm->fwd_entry_pool);
2448  }
2449 
2450  /* update global flag */
2451  lcm->is_enabled = is_enable;
2452 
2453  return 0;
2454 }
2455 
2456 static clib_error_t *
2458  vlib_cli_command_t * cmd)
2459 {
2460  unformat_input_t _line_input, *line_input = &_line_input;
2461  u8 is_enabled = 0;
2462  u8 is_set = 0;
2463 
2464  /* Get a line of input. */
2465  if (!unformat_user (input, unformat_line_input, line_input))
2466  return 0;
2467 
2468  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2469  {
2470  if (unformat (line_input, "enable"))
2471  {
2472  is_set = 1;
2473  is_enabled = 1;
2474  }
2475  else if (unformat (line_input, "disable"))
2476  is_set = 1;
2477  else
2478  {
2479  return clib_error_return (0, "parse error: '%U'",
2480  format_unformat_error, line_input);
2481  }
2482  }
2483 
2484  if (!is_set)
2485  return clib_error_return (0, "state not set");
2486 
2487  vnet_lisp_enable_disable (is_enabled);
2488  return 0;
2489 }
2490 
2491 /* *INDENT-OFF* */
2492 VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = {
2493  .path = "lisp",
2494  .short_help = "lisp [enable|disable]",
2495  .function = lisp_enable_disable_command_fn,
2496 };
2497 /* *INDENT-ON* */
2498 
2499 static clib_error_t *
2501  unformat_input_t * input,
2502  vlib_cli_command_t * cmd)
2503 {
2504  unformat_input_t _line_input, *line_input = &_line_input;
2505  u8 is_enabled = 0;
2506  u8 is_set = 0;
2507 
2508  /* Get a line of input. */
2509  if (!unformat_user (input, unformat_line_input, line_input))
2510  return 0;
2511 
2512  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2513  {
2514  if (unformat (line_input, "enable"))
2515  {
2516  is_set = 1;
2517  is_enabled = 1;
2518  }
2519  else if (unformat (line_input, "disable"))
2520  is_set = 1;
2521  else
2522  {
2523  vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
2524  line_input);
2525  return 0;
2526  }
2527  }
2528 
2529  if (!is_set)
2530  {
2531  vlib_cli_output (vm, "state not set!");
2532  return 0;
2533  }
2534 
2536  return 0;
2537 }
2538 
2539 /* *INDENT-OFF* */
2540 VLIB_CLI_COMMAND (lisp_map_register_enable_disable_command) = {
2541  .path = "lisp map-register",
2542  .short_help = "lisp map-register [enable|disable]",
2544 };
2545 /* *INDENT-ON* */
2546 
2547 static clib_error_t *
2549  unformat_input_t * input,
2550  vlib_cli_command_t * cmd)
2551 {
2552  unformat_input_t _line_input, *line_input = &_line_input;
2553  u8 is_enabled = 0;
2554  u8 is_set = 0;
2555 
2556  /* Get a line of input. */
2557  if (!unformat_user (input, unformat_line_input, line_input))
2558  return 0;
2559 
2560  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2561  {
2562  if (unformat (line_input, "enable"))
2563  {
2564  is_set = 1;
2565  is_enabled = 1;
2566  }
2567  else if (unformat (line_input, "disable"))
2568  is_set = 1;
2569  else
2570  {
2571  vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
2572  line_input);
2573  return 0;
2574  }
2575  }
2576 
2577  if (!is_set)
2578  {
2579  vlib_cli_output (vm, "state not set!");
2580  return 0;
2581  }
2582 
2584  return 0;
2585 }
2586 
2587 /* *INDENT-OFF* */
2588 VLIB_CLI_COMMAND (lisp_rloc_probe_enable_disable_command) = {
2589  .path = "lisp rloc-probe",
2590  .short_help = "lisp rloc-probe [enable|disable]",
2592 };
2593 /* *INDENT-ON* */
2594 
2595 u8
2597 {
2599  return lcm->is_enabled;
2600 }
2601 
2602 static u8 *
2603 format_lisp_status (u8 * s, va_list * args)
2604 {
2606  return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled");
2607 }
2608 
2609 static clib_error_t *
2611  vlib_cli_command_t * cmd)
2612 {
2613  u8 *msg = 0;
2614  msg = format (msg, "feature: %U\ngpe: %U\n",
2616  vlib_cli_output (vm, "%v", msg);
2617  vec_free (msg);
2618  return 0;
2619 }
2620 
2621 /* *INDENT-OFF* */
2622 VLIB_CLI_COMMAND (lisp_show_status_command) = {
2623  .path = "show lisp status",
2624  .short_help = "show lisp status",
2625  .function = lisp_show_status_command_fn,
2626 };
2627 /* *INDENT-ON* */
2628 
2629 static clib_error_t *
2631  unformat_input_t * input,
2632  vlib_cli_command_t * cmd)
2633 {
2634  hash_pair_t *p;
2635  unformat_input_t _line_input, *line_input = &_line_input;
2637  uword *vni_table = 0;
2638  u8 is_l2 = 0;
2639 
2640  /* Get a line of input. */
2641  if (!unformat_user (input, unformat_line_input, line_input))
2642  return 0;
2643 
2644  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2645  {
2646  if (unformat (line_input, "l2"))
2647  {
2648  vni_table = lcm->bd_id_by_vni;
2649  is_l2 = 1;
2650  }
2651  else if (unformat (line_input, "l3"))
2652  {
2653  vni_table = lcm->table_id_by_vni;
2654  is_l2 = 0;
2655  }
2656  else
2657  return clib_error_return (0, "parse error: '%U'",
2658  format_unformat_error, line_input);
2659  }
2660 
2661  if (!vni_table)
2662  {
2663  vlib_cli_output (vm, "Error: expected l2|l3 param!\n");
2664  return 0;
2665  }
2666 
2667  vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF");
2668 
2669  /* *INDENT-OFF* */
2670  hash_foreach_pair (p, vni_table,
2671  ({
2672  vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
2673  }));
2674  /* *INDENT-ON* */
2675 
2676  return 0;
2677 }
2678 
2679 /* *INDENT-OFF* */
2680 VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
2681  .path = "show lisp eid-table map",
2682  .short_help = "show lisp eid-table l2|l3",
2684 };
2685 /* *INDENT-ON* */
2686 
2687 static clib_error_t *
2689  unformat_input_t * input,
2690  vlib_cli_command_t * cmd)
2691 {
2693  vnet_main_t *vnm = lgm->vnet_main;
2694  unformat_input_t _line_input, *line_input = &_line_input;
2695  u8 is_add = 1;
2696  clib_error_t *error = 0;
2697  u8 *locator_set_name = 0;
2698  locator_t locator, *locators = 0;
2700  u32 ls_index = 0;
2701  int rv = 0;
2702 
2703  memset (&locator, 0, sizeof (locator));
2704  memset (a, 0, sizeof (a[0]));
2705 
2706  /* Get a line of input. */
2707  if (!unformat_user (input, unformat_line_input, line_input))
2708  return 0;
2709 
2710  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2711  {
2712  if (unformat (line_input, "add %_%v%_", &locator_set_name))
2713  is_add = 1;
2714  else if (unformat (line_input, "del %_%v%_", &locator_set_name))
2715  is_add = 0;
2716  else if (unformat (line_input, "iface %U p %d w %d",
2718  &locator.sw_if_index, &locator.priority,
2719  &locator.weight))
2720  {
2721  locator.local = 1;
2722  vec_add1 (locators, locator);
2723  }
2724  else
2725  {
2726  error = unformat_parse_error (line_input);
2727  goto done;
2728  }
2729  }
2730 
2731  a->name = locator_set_name;
2732  a->locators = locators;
2733  a->is_add = is_add;
2734  a->local = 1;
2735 
2736  rv = vnet_lisp_add_del_locator_set (a, &ls_index);
2737  if (0 != rv)
2738  {
2739  error = clib_error_return (0, "failed to %s locator-set!",
2740  is_add ? "add" : "delete");
2741  }
2742 
2743 done:
2744  vec_free (locators);
2745  if (locator_set_name)
2746  vec_free (locator_set_name);
2747  return error;
2748 }
2749 
2750 /* *INDENT-OFF* */
2751 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = {
2752  .path = "lisp locator-set",
2753  .short_help = "lisp locator-set add/del <name> [iface <iface-name> "
2754  "p <priority> w <weight>]",
2756 };
2757 /* *INDENT-ON* */
2758 
2759 static clib_error_t *
2761  unformat_input_t * input,
2762  vlib_cli_command_t * cmd)
2763 {
2765  vnet_main_t *vnm = lgm->vnet_main;
2766  unformat_input_t _line_input, *line_input = &_line_input;
2767  u8 is_add = 1;
2768  clib_error_t *error = 0;
2769  u8 *locator_set_name = 0;
2770  u8 locator_set_name_set = 0;
2771  locator_t locator, *locators = 0;
2773  u32 ls_index = 0;
2774 
2775  memset (&locator, 0, sizeof (locator));
2776  memset (a, 0, sizeof (a[0]));
2777 
2778  /* Get a line of input. */
2779  if (!unformat_user (input, unformat_line_input, line_input))
2780  return 0;
2781 
2782  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2783  {
2784  if (unformat (line_input, "add"))
2785  is_add = 1;
2786  else if (unformat (line_input, "del"))
2787  is_add = 0;
2788  else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name))
2789  locator_set_name_set = 1;
2790  else if (unformat (line_input, "iface %U p %d w %d",
2792  &locator.sw_if_index, &locator.priority,
2793  &locator.weight))
2794  {
2795  locator.local = 1;
2796  vec_add1 (locators, locator);
2797  }
2798  else
2799  {
2800  error = unformat_parse_error (line_input);
2801  goto done;
2802  }
2803  }
2804 
2805  if (!locator_set_name_set)
2806  {
2807  error = clib_error_return (0, "locator_set name not set!");
2808  goto done;
2809  }
2810 
2811  a->name = locator_set_name;
2812  a->locators = locators;
2813  a->is_add = is_add;
2814  a->local = 1;
2815 
2816  vnet_lisp_add_del_locator (a, 0, &ls_index);
2817 
2818 done:
2819  vec_free (locators);
2820  vec_free (locator_set_name);
2821  return error;
2822 }
2823 
2824 /* *INDENT-OFF* */
2825 VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = {
2826  .path = "lisp locator",
2827  .short_help = "lisp locator add/del locator-set <name> iface <iface-name> "
2828  "p <priority> w <weight>",
2830 };
2831 /* *INDENT-ON* */
2832 
2833 static clib_error_t *
2835  unformat_input_t * input,
2836  vlib_cli_command_t * cmd)
2837 {
2838  locator_set_t *lsit;
2839  locator_t *loc;
2840  u32 *locit;
2842 
2843  vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator",
2844  "Priority", "Weight");
2845 
2846  /* *INDENT-OFF* */
2847  pool_foreach (lsit, lcm->locator_set_pool,
2848  ({
2849  u8 * msg = 0;
2850  int next_line = 0;
2851  if (lsit->local)
2852  {
2853  msg = format (msg, "%v", lsit->name);
2854  }
2855  else
2856  {
2857  msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool);
2858  }
2859  vec_foreach (locit, lsit->locator_indices)
2860  {
2861  if (next_line)
2862  {
2863  msg = format (msg, "%16s", " ");
2864  }
2865  loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
2866  if (loc->local)
2867  msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority,
2868  loc->weight);
2869  else
2870  msg = format (msg, "%16U%16d%16d\n", format_ip_address,
2871  &gid_address_ip(&loc->address), loc->priority,
2872  loc->weight);
2873  next_line = 1;
2874  }
2875  vlib_cli_output (vm, "%v", msg);
2876  vec_free (msg);
2877  }));
2878  /* *INDENT-ON* */
2879  return 0;
2880 }
2881 
2882 /* *INDENT-OFF* */
2883 VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = {
2884  .path = "show lisp locator-set",
2885  .short_help = "Shows locator-sets",
2887 };
2888 /* *INDENT-ON* */
2889 
2890 int
2892 {
2894  u32 i;
2895  lisp_msmr_t _mr, *mr = &_mr;
2896 
2897  if (vnet_lisp_enable_disable_status () == 0)
2898  {
2899  clib_warning ("LISP is disabled!");
2900  return VNET_API_ERROR_LISP_DISABLED;
2901  }
2902 
2903  if (a->is_add)
2904  {
2905 
2906  if (get_map_resolver (&a->address))
2907  {
2908  clib_warning ("map-resolver %U already exists!", format_ip_address,
2909  &a->address);
2910  return -1;
2911  }
2912 
2913  memset (mr, 0, sizeof (*mr));
2914  ip_address_copy (&mr->address, &a->address);
2915  vec_add1 (lcm->map_resolvers, *mr);
2916 
2917  if (vec_len (lcm->map_resolvers) == 1)
2918  lcm->do_map_resolver_election = 1;
2919  }
2920  else
2921  {
2922  for (i = 0; i < vec_len (lcm->map_resolvers); i++)
2923  {
2924  mr = vec_elt_at_index (lcm->map_resolvers, i);
2925  if (!ip_address_cmp (&mr->address, &a->address))
2926  {
2927  if (!ip_address_cmp (&mr->address, &lcm->active_map_resolver))
2928  lcm->do_map_resolver_election = 1;
2929 
2930  vec_del1 (lcm->map_resolvers, i);
2931  break;
2932  }
2933  }
2934  }
2935  return 0;
2936 }
2937 
2938 static clib_error_t *
2940  unformat_input_t * input,
2941  vlib_cli_command_t * cmd)
2942 {
2943  unformat_input_t _line_input, *line_input = &_line_input;
2944  u8 is_add = 1, addr_set = 0;
2945  ip_address_t ip_addr;
2946  clib_error_t *error = 0;
2947  int rv = 0;
2949 
2950  /* Get a line of input. */
2951  if (!unformat_user (input, unformat_line_input, line_input))
2952  return 0;
2953 
2954  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2955  {
2956  if (unformat (line_input, "add"))
2957  is_add = 1;
2958  else if (unformat (line_input, "del"))
2959  is_add = 0;
2960  else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr))
2961  addr_set = 1;
2962  else
2963  {
2964  error = unformat_parse_error (line_input);
2965  goto done;
2966  }
2967  }
2968 
2969  if (!addr_set)
2970  {
2971  error = clib_error_return (0, "Map-resolver address must be set!");
2972  goto done;
2973  }
2974 
2975  a->is_add = is_add;
2976  a->address = ip_addr;
2978  if (0 != rv)
2979  {
2980  error = clib_error_return (0, "failed to %s map-resolver!",
2981  is_add ? "add" : "delete");
2982  }
2983 
2984 done:
2985  return error;
2986 }
2987 
2988 /* *INDENT-OFF* */
2989 VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = {
2990  .path = "lisp map-resolver",
2991  .short_help = "lisp map-resolver add/del <ip_address>",
2993 };
2994 /* *INDENT-ON* */
2995 
2996 int
2998 {
3000  uword *p = 0;
3001 
3002  if (vnet_lisp_enable_disable_status () == 0)
3003  {
3004  clib_warning ("LISP is disabled!");
3005  return VNET_API_ERROR_LISP_DISABLED;
3006  }
3007 
3008  if (a->is_add)
3009  {
3011  if (!p)
3012  {
3013  clib_warning ("locator-set %v doesn't exist", a->locator_set_name);
3014  return VNET_API_ERROR_INVALID_ARGUMENT;
3015  }
3016 
3017  lcm->mreq_itr_rlocs = p[0];
3018  }
3019  else
3020  {
3021  lcm->mreq_itr_rlocs = ~0;
3022  }
3023 
3024  return 0;
3025 }
3026 
3027 static clib_error_t *
3029  unformat_input_t * input,
3030  vlib_cli_command_t * cmd)
3031 {
3032  unformat_input_t _line_input, *line_input = &_line_input;
3033  u8 is_add = 1;
3034  u8 *locator_set_name = 0;
3035  clib_error_t *error = 0;
3036  int rv = 0;
3038 
3039  /* Get a line of input. */
3040  if (!unformat_user (input, unformat_line_input, line_input))
3041  return 0;
3042 
3043  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3044  {
3045  if (unformat (line_input, "del"))
3046  is_add = 0;
3047  else if (unformat (line_input, "add %_%v%_", &locator_set_name))
3048  is_add = 1;
3049  else
3050  {
3051  error = unformat_parse_error (line_input);
3052  goto done;
3053  }
3054  }
3055 
3056  a->is_add = is_add;
3057  a->locator_set_name = locator_set_name;
3059  if (0 != rv)
3060  {
3061  error = clib_error_return (0, "failed to %s map-request itr-rlocs!",
3062  is_add ? "add" : "delete");
3063  }
3064 
3065  vec_free (locator_set_name);
3066 
3067 done:
3068  return error;
3069 
3070 }
3071 
3072 /* *INDENT-OFF* */
3073 VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = {
3074  .path = "lisp map-request itr-rlocs",
3075  .short_help = "lisp map-request itr-rlocs add/del <locator_set_name>",
3077 };
3078 /* *INDENT-ON* */
3079 
3080 static clib_error_t *
3082  unformat_input_t * input,
3083  vlib_cli_command_t * cmd)
3084 {
3086  locator_set_t *loc_set;
3087 
3088  vlib_cli_output (vm, "%=20s", "itr-rlocs");
3089 
3090  if (~0 == lcm->mreq_itr_rlocs)
3091  {
3092  return 0;
3093  }
3094 
3095  loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
3096 
3097  vlib_cli_output (vm, "%=20s", loc_set->name);
3098 
3099  return 0;
3100 }
3101 
3102 /* *INDENT-OFF* */
3103 VLIB_CLI_COMMAND (lisp_show_map_request_command) = {
3104  .path = "show lisp map-request itr-rlocs",
3105  .short_help = "Shows map-request itr-rlocs",
3107 };
3108 /* *INDENT-ON* */
3109 
3110 /* Statistics (not really errors) */
3111 #define foreach_lisp_cp_lookup_error \
3112 _(DROP, "drop") \
3113 _(MAP_REQUESTS_SENT, "map-request sent")
3114 
3116 #define _(sym,string) string,
3118 #undef _
3119 };
3120 
3121 typedef enum
3122 {
3123 #define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
3125 #undef _
3128 
3129 typedef enum
3130 {
3134 
3135 typedef struct
3136 {
3138  ip_address_t map_resolver_ip;
3140 
3141 u8 *
3142 format_lisp_cp_lookup_trace (u8 * s, va_list * args)
3143 {
3144  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
3145  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
3146  lisp_cp_lookup_trace_t *t = va_arg (*args, lisp_cp_lookup_trace_t *);
3147 
3148  s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
3150  &t->dst_eid);
3151  return s;
3152 }
3153 
3154 int
3155 get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
3156  ip_address_t * sloc)
3157 {
3158  lisp_msmr_t *mrit;
3159  ip_address_t *a;
3160 
3161  if (vec_len (lcm->map_resolvers) == 0)
3162  {
3163  clib_warning ("No map-resolver configured");
3164  return 0;
3165  }
3166 
3167  /* find the first mr ip we have a route to and the ip of the
3168  * iface that has a route to it */
3169  vec_foreach (mrit, lcm->map_resolvers)
3170  {
3171  a = &mrit->address;
3172  if (0 != ip_fib_get_first_egress_ip_for_dst (lcm, a, sloc))
3173  {
3174  ip_address_copy (mr_ip, a);
3175 
3176  /* also update globals */
3177  return 1;
3178  }
3179  }
3180 
3181  clib_warning ("Can't find map-resolver and local interface ip!");
3182  return 0;
3183 }
3184 
3185 static gid_address_t *
3187 {
3188  void *addr;
3189  u32 i;
3190  locator_t *loc;
3191  u32 *loc_indexp;
3192  ip_interface_address_t *ia = 0;
3193  gid_address_t gid_data, *gid = &gid_data;
3194  gid_address_t *rlocs = 0;
3195  ip_prefix_t *ippref = &gid_address_ippref (gid);
3196  ip_address_t *rloc = &ip_prefix_addr (ippref);
3197 
3198  memset (gid, 0, sizeof (gid[0]));
3200  for (i = 0; i < vec_len (loc_set->locator_indices); i++)
3201  {
3202  loc_indexp = vec_elt_at_index (loc_set->locator_indices, i);
3203  loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
3204 
3205  /* Add ipv4 locators first TODO sort them */
3206 
3207  /* *INDENT-OFF* */
3209  loc->sw_if_index, 1 /* unnumbered */,
3210  ({
3211  addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
3212  ip_address_set (rloc, addr, IP4);
3213  ip_prefix_len (ippref) = 32;
3214  ip_prefix_normalize (ippref);
3215  vec_add1 (rlocs, gid[0]);
3216  }));
3217 
3218  /* Add ipv6 locators */
3220  loc->sw_if_index, 1 /* unnumbered */,
3221  ({
3222  addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
3223  ip_address_set (rloc, addr, IP6);
3224  ip_prefix_len (ippref) = 128;
3225  ip_prefix_normalize (ippref);
3226  vec_add1 (rlocs, gid[0]);
3227  }));
3228  /* *INDENT-ON* */
3229 
3230  }
3231  return rlocs;
3232 }
3233 
3234 static vlib_buffer_t *
3236  ip_address_t * sloc, ip_address_t * rloc,
3237  gid_address_t * itr_rlocs, u64 * nonce_res, u32 * bi_res)
3238 {
3239  vlib_buffer_t *b;
3240  u32 bi;
3241  vlib_main_t *vm = lcm->vlib_main;
3242 
3243  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3244  {
3245  clib_warning ("Can't allocate buffer for Map-Request!");
3246  return 0;
3247  }
3248 
3249  b = vlib_get_buffer (vm, bi);
3250 
3251  /* leave some space for the encap headers */
3253 
3254  /* put lisp msg */
3255  lisp_msg_put_mreq (lcm, b, NULL, deid, itr_rlocs, 0 /* smr invoked */ ,
3256  1 /* rloc probe */ , nonce_res);
3257 
3258  /* push outer ip header */
3260  rloc);
3261 
3262  bi_res[0] = bi;
3263 
3264  return b;
3265 }
3266 
3267 static vlib_buffer_t *
3269  gid_address_t * seid, gid_address_t * deid,
3270  locator_set_t * loc_set, ip_address_t * mr_ip,
3271  ip_address_t * sloc, u8 is_smr_invoked,
3272  u64 * nonce_res, u32 * bi_res)
3273 {
3274  vlib_buffer_t *b;
3275  u32 bi;
3276  gid_address_t *rlocs = 0;
3277  vlib_main_t *vm = lcm->vlib_main;
3278 
3279  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3280  {
3281  clib_warning ("Can't allocate buffer for Map-Request!");
3282  return 0;
3283  }
3284 
3285  b = vlib_get_buffer (vm, bi);
3286 
3287  /* leave some space for the encap headers */
3289 
3290  /* get rlocs */
3291  rlocs = build_itr_rloc_list (lcm, loc_set);
3292 
3293  if (MR_MODE_SRC_DST == lcm->map_request_mode
3294  && GID_ADDR_SRC_DST != gid_address_type (deid))
3295  {
3296  gid_address_t sd;
3297  memset (&sd, 0, sizeof (sd));
3298  build_src_dst (&sd, seid, deid);
3299  lisp_msg_put_mreq (lcm, b, seid, &sd, rlocs, is_smr_invoked,
3300  0 /* rloc probe */ , nonce_res);
3301  }
3302  else
3303  {
3304  /* put lisp msg */
3305  lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked,
3306  0 /* rloc probe */ , nonce_res);
3307  }
3308 
3309  /* push ecm: udp-ip-lisp */
3311 
3312  /* push outer ip header */
3314  mr_ip);
3315 
3316  bi_res[0] = bi;
3317 
3318  vec_free (rlocs);
3319  return b;
3320 }
3321 
3322 static void
3324 {
3326  r->retries_num = 0;
3327 }
3328 
3329 static int
3331 {
3332  lisp_msmr_t *mr;
3333 
3334  vec_foreach (mr, lcm->map_resolvers)
3335  {
3336  if (!mr->is_down)
3337  {
3339  lcm->do_map_resolver_election = 0;
3340  return 1;
3341  }
3342  }
3343  return 0;
3344 }
3345 
3346 static void
3348 {
3349  mapping_t *map;
3350  vec_foreach (map, maps) vec_free (map->locators);
3351 
3352  vec_free (maps);
3353 }
3354 
3355 static void
3356 add_locators (lisp_cp_main_t * lcm, mapping_t * m, u32 locator_set_index,
3357  ip_address_t * probed_loc)
3358 {
3359  u32 *li;
3360  locator_t *loc, new;
3361  ip_interface_address_t *ia = 0;
3362  void *addr;
3363  ip_address_t *new_ip = &gid_address_ip (&new.address);
3364 
3365  m->locators = 0;
3367  locator_set_index);
3368  vec_foreach (li, ls->locator_indices)
3369  {
3370  loc = pool_elt_at_index (lcm->locator_pool, li[0]);
3371  new = loc[0];
3372  if (loc->local)
3373  {
3374  /* *INDENT-OFF* */
3376  loc->sw_if_index, 1 /* unnumbered */,
3377  ({
3378  addr = ip_interface_address_get_address (&lcm->im4->lookup_main,
3379  ia);
3380  ip_address_set (new_ip, addr, IP4);
3381  }));
3382 
3383  /* Add ipv6 locators */
3385  loc->sw_if_index, 1 /* unnumbered */,
3386  ({
3387  addr = ip_interface_address_get_address (&lcm->im6->lookup_main,
3388  ia);
3389  ip_address_set (new_ip, addr, IP6);
3390  }));
3391  /* *INDENT-ON* */
3392 
3393  if (probed_loc && ip_address_cmp (probed_loc, new_ip) == 0)
3394  new.probed = 1;
3395  }
3396  vec_add1 (m->locators, new);
3397  }
3398 }
3399 
3400 static mapping_t *
3402 {
3403  mapping_t *recs = 0, rec, *m;
3404 
3405  /* *INDENT-OFF* */
3406  pool_foreach(m, lcm->mapping_pool,
3407  {
3408  /* for now build only local mappings */
3409  if (!m->local)
3410  continue;
3411 
3412  rec = m[0];
3413  add_locators (lcm, &rec, m->locator_set_index, NULL);
3414  vec_add1 (recs, rec);
3415  });
3416  /* *INDENT-ON* */
3417 
3418  return recs;
3419 }
3420 
3421 static int
3423  lisp_key_type_t key_id, u8 * key,
3424  u16 auth_data_len, u32 msg_len)
3425 {
3426  MREG_KEY_ID (map_reg_hdr) = clib_host_to_net_u16 (key_id);
3427  MREG_AUTH_DATA_LEN (map_reg_hdr) = clib_host_to_net_u16 (auth_data_len);
3428 
3429  unsigned char *result = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
3430  (unsigned char *) map_reg_hdr, msg_len, NULL,
3431  NULL);
3432  clib_memcpy (MREG_DATA (map_reg_hdr), result, auth_data_len);
3433 
3434  return 0;
3435 }
3436 
3437 static vlib_buffer_t *
3438 build_map_register (lisp_cp_main_t * lcm, ip_address_t * sloc,
3439  ip_address_t * ms_ip, u64 * nonce_res, u8 want_map_notif,
3440  mapping_t * records, lisp_key_type_t key_id, u8 * key,
3441  u32 * bi_res)
3442 {
3443  void *map_reg_hdr;
3444  vlib_buffer_t *b;
3445  u32 bi, auth_data_len = 0, msg_len = 0;
3446  vlib_main_t *vm = lcm->vlib_main;
3447 
3448  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3449  {
3450  clib_warning ("Can't allocate buffer for Map-Register!");
3451  return 0;
3452  }
3453 
3454  b = vlib_get_buffer (vm, bi);
3455 
3456  /* leave some space for the encap headers */
3458 
3459  auth_data_len = auth_data_len_by_key_id (key_id);
3460  map_reg_hdr = lisp_msg_put_map_register (b, records, want_map_notif,
3461  auth_data_len, nonce_res,
3462  &msg_len);
3463 
3464  update_map_register_auth_data (map_reg_hdr, key_id, key, auth_data_len,
3465  msg_len);
3466 
3467  /* push outer ip header */
3469  ms_ip);
3470 
3471  bi_res[0] = bi;
3472  return b;
3473 }
3474 
3475 static int
3476 get_egress_map_resolver_ip (lisp_cp_main_t * lcm, ip_address_t * ip)
3477 {
3478  lisp_msmr_t *mr;
3479  while (lcm->do_map_resolver_election
3481  &lcm->active_map_resolver,
3482  ip)))
3483  {
3484  if (0 == elect_map_resolver (lcm))
3485  /* all map resolvers are down */
3486  {
3487  /* restart MR checking by marking all of them up */
3488  vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0;
3489  return -1;
3490  }
3491  }
3492  return 0;
3493 }
3494 
3495 static int
3497  u32 local_locator_set_index, ip_address_t * sloc,
3498  ip_address_t * rloc)
3499 {
3500  locator_set_t *ls;
3501  u32 bi;
3502  vlib_buffer_t *b;
3503  vlib_frame_t *f;
3504  u64 nonce = 0;
3505  u32 next_index, *to_next;
3506  gid_address_t *itr_rlocs;
3507 
3508  ls = pool_elt_at_index (lcm->locator_set_pool, local_locator_set_index);
3509  itr_rlocs = build_itr_rloc_list (lcm, ls);
3510 
3511  b = build_map_request (lcm, deid, sloc, rloc, itr_rlocs, &nonce, &bi);
3512  vec_free (itr_rlocs);
3513  if (!b)
3514  return -1;
3515 
3516  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3517 
3518  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3519  ip4_lookup_node.index : ip6_lookup_node.index;
3520 
3521  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3522 
3523  /* Enqueue the packet */
3524  to_next = vlib_frame_vector_args (f);
3525  to_next[0] = bi;
3526  f->n_vectors = 1;
3527  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3528 
3529  hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
3530  return 0;
3531 }
3532 
3533 static int
3535 {
3536  u8 lprio = 0;
3537  mapping_t *lm;
3538  fwd_entry_t *e;
3539  locator_pair_t *lp;
3540  u32 si;
3541 
3542  /* *INDENT-OFF* */
3543  pool_foreach (e, lcm->fwd_entry_pool,
3544  {
3545  if (vec_len (e->locator_pairs) == 0)
3546  continue;
3547 
3548  si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &e->leid);
3549  if (~0 == si)
3550  {
3551  clib_warning ("internal error: cannot find local eid %U in "
3552  "map-cache!", format_gid_address, &e->leid);
3553  continue;
3554  }
3555  lm = pool_elt_at_index (lcm->mapping_pool, si);
3556 
3557  /* get the best (lowest) priority */
3558  lprio = e->locator_pairs[0].priority;
3559 
3560  /* send rloc-probe for pair(s) with the best remote locator priority */
3561  vec_foreach (lp, e->locator_pairs)
3562  {
3563  if (lp->priority != lprio)
3564  break;
3565 
3566  /* get first remote locator */
3567  send_rloc_probe (lcm, &e->reid, lm->locator_set_index, &lp->lcl_loc,
3568  &lp->rmt_loc);
3569  }
3570  });
3571  /* *INDENT-ON* */
3572 
3573  return 0;
3574 }
3575 
3576 static int
3577 send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif)
3578 {
3579  u32 bi;
3580  vlib_buffer_t *b;
3581  ip_address_t sloc;
3582  vlib_frame_t *f;
3583  u64 nonce = 0;
3584  u32 next_index, *to_next;
3585  ip_address_t *ms = 0;
3586  mapping_t *records, *r, *g;
3587 
3588  // TODO: support multiple map servers and do election
3589  if (0 == vec_len (lcm->map_servers))
3590  return -1;
3591 
3592  ms = &lcm->map_servers[0].address;
3593 
3594  if (0 == ip_fib_get_first_egress_ip_for_dst (lcm, ms, &sloc))
3595  {
3596  clib_warning ("no eligible interface address found for %U!",
3597  format_ip_address, &lcm->map_servers[0]);
3598  return -1;
3599  }
3600 
3601  records = build_map_register_record_list (lcm);
3602  if (!records)
3603  return -1;
3604 
3605  vec_foreach (r, records)
3606  {
3607  u8 *key = r->key;
3608  u8 key_id = r->key_id;
3609 
3610  if (!key)
3611  continue; /* no secret key -> map-register cannot be sent */
3612 
3613  g = 0;
3614  // TODO: group mappings that share common key
3615  vec_add1 (g, r[0]);
3616  b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, g,
3617  key_id, key, &bi);
3618  vec_free (g);
3619  if (!b)
3620  continue;
3621 
3622  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3623 
3624  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3625  ip4_lookup_node.index : ip6_lookup_node.index;
3626 
3627  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3628 
3629  /* Enqueue the packet */
3630  to_next = vlib_frame_vector_args (f);
3631  to_next[0] = bi;
3632  f->n_vectors = 1;
3633  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3634 
3635  hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
3636  }
3637  free_map_register_records (records);
3638 
3639  return 0;
3640 }
3641 
3642 #define send_encapsulated_map_request(lcm, seid, deid, smr) \
3643  _send_encapsulated_map_request(lcm, seid, deid, smr, 0)
3644 
3645 #define resend_encapsulated_map_request(lcm, seid, deid, smr) \
3646  _send_encapsulated_map_request(lcm, seid, deid, smr, 1)
3647 
3648 static int
3649 _send_encapsulated_map_request (lisp_cp_main_t * lcm,
3650  gid_address_t * seid, gid_address_t * deid,
3651  u8 is_smr_invoked, u8 is_resend)
3652 {
3653  u32 next_index, bi = 0, *to_next, map_index;
3654  vlib_buffer_t *b;
3655  vlib_frame_t *f;
3656  u64 nonce = 0;
3657  locator_set_t *loc_set;
3658  mapping_t *map;
3659  pending_map_request_t *pmr, *duplicate_pmr = 0;
3660  ip_address_t sloc;
3661  u32 ls_index;
3662 
3663  /* if there is already a pending request remember it */
3664 
3665  /* *INDENT-OFF* */
3667  ({
3668  if (!gid_address_cmp (&pmr->src, seid)
3669  && !gid_address_cmp (&pmr->dst, deid))
3670  {
3671  duplicate_pmr = pmr;
3672  break;
3673  }
3674  }));
3675  /* *INDENT-ON* */
3676 
3677  if (!is_resend && duplicate_pmr)
3678  {
3679  /* don't send the request if there is a pending map request already */
3680  return 0;
3681  }
3682 
3683  /* get locator-set for seid */
3684  if (!lcm->lisp_pitr)
3685  {
3686  map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
3687  if (map_index == ~0)
3688  {
3689  clib_warning ("No local mapping found in eid-table for %U!",
3690  format_gid_address, seid);
3691  return -1;
3692  }
3693 
3694  map = pool_elt_at_index (lcm->mapping_pool, map_index);
3695 
3696  if (!map->local)
3697  {
3698  clib_warning
3699  ("Mapping found for src eid %U is not marked as local!",
3700  format_gid_address, seid);
3701  return -1;
3702  }
3703  ls_index = map->locator_set_index;
3704  }
3705  else
3706  {
3707  map_index = lcm->pitr_map_index;
3708  map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
3709  ls_index = map->locator_set_index;
3710  }
3711 
3712  /* overwrite locator set if map-request itr-rlocs configured */
3713  if (~0 != lcm->mreq_itr_rlocs)
3714  {
3715  ls_index = lcm->mreq_itr_rlocs;
3716  }
3717 
3718  loc_set = pool_elt_at_index (lcm->locator_set_pool, ls_index);
3719 
3720  if (get_egress_map_resolver_ip (lcm, &sloc) < 0)
3721  {
3722  if (duplicate_pmr)
3723  duplicate_pmr->to_be_removed = 1;
3724  return -1;
3725  }
3726 
3727  /* build the encapsulated map request */
3728  b = build_encapsulated_map_request (lcm, seid, deid, loc_set,
3729  &lcm->active_map_resolver,
3730  &sloc, is_smr_invoked, &nonce, &bi);
3731 
3732  if (!b)
3733  return -1;
3734 
3735  /* set fib index to default and lookup node */
3736  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3737  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3738  ip4_lookup_node.index : ip6_lookup_node.index;
3739 
3740  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3741 
3742  /* Enqueue the packet */
3743  to_next = vlib_frame_vector_args (f);
3744  to_next[0] = bi;
3745  f->n_vectors = 1;
3746  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3747 
3748  if (duplicate_pmr)
3749  /* if there is a pending request already update it */
3750  {
3751  if (clib_fifo_elts (duplicate_pmr->nonces) >= PENDING_MREQ_QUEUE_LEN)
3752  {
3753  /* remove the oldest nonce */
3754  u64 CLIB_UNUSED (tmp), *nonce_del;
3755  nonce_del = clib_fifo_head (duplicate_pmr->nonces);
3756  hash_unset (lcm->pending_map_requests_by_nonce, nonce_del[0]);
3757  clib_fifo_sub1 (duplicate_pmr->nonces, tmp);
3758  }
3759 
3760  clib_fifo_add1 (duplicate_pmr->nonces, nonce);
3761  hash_set (lcm->pending_map_requests_by_nonce, nonce,
3762  duplicate_pmr - lcm->pending_map_requests_pool);
3763  }
3764  else
3765  {
3766  /* add map-request to pending requests table */
3767  pool_get (lcm->pending_map_requests_pool, pmr);
3768  memset (pmr, 0, sizeof (*pmr));
3769  gid_address_copy (&pmr->src, seid);
3770  gid_address_copy (&pmr->dst, deid);
3771  clib_fifo_add1 (pmr->nonces, nonce);
3772  pmr->is_smr_invoked = is_smr_invoked;
3774  hash_set (lcm->pending_map_requests_by_nonce, nonce,
3775  pmr - lcm->pending_map_requests_pool);
3776  }
3777 
3778  return 0;
3779 }
3780 
3781 static void
3782 get_src_and_dst_ip (void *hdr, ip_address_t * src, ip_address_t * dst)
3783 {
3784  ip4_header_t *ip4 = hdr;
3785  ip6_header_t *ip6;
3786 
3787  if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
3788  {
3789  ip_address_set (src, &ip4->src_address, IP4);
3790  ip_address_set (dst, &ip4->dst_address, IP4);
3791  }
3792  else
3793  {
3794  ip6 = hdr;
3795  ip_address_set (src, &ip6->src_address, IP6);
3796  ip_address_set (dst, &ip6->dst_address, IP6);
3797  }
3798 }
3799 
3800 static u32
3802  u8 version)
3803 {
3804  uword *vnip;
3805  u32 vni = ~0, table_id = ~0;
3806 
3807  table_id = fib_table_get_table_id_for_sw_if_index ((version ==
3808  IP4 ? FIB_PROTOCOL_IP4 :
3810  vnet_buffer
3811  (b)->sw_if_index
3812  [VLIB_RX]);
3813 
3814  vnip = hash_get (lcm->vni_by_table_id, table_id);
3815  if (vnip)
3816  vni = vnip[0];
3817  else
3818  clib_warning ("vrf %d is not mapped to any vni!", table_id);
3819 
3820  return vni;
3821 }
3822 
3825 {
3826  uword *vnip;
3827  u32 vni = ~0;
3828  u32 sw_if_index0;
3829 
3830  l2input_main_t *l2im = &l2input_main;
3831  l2_input_config_t *config;
3832  l2_bridge_domain_t *bd_config;
3833 
3834  sw_if_index0 = vnet_buffer (b)->sw_if_index[VLIB_RX];
3835  config = vec_elt_at_index (l2im->configs, sw_if_index0);
3836  bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
3837 
3838  vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id);
3839  if (vnip)
3840  vni = vnip[0];
3841  else
3842  clib_warning ("bridge domain %d is not mapped to any vni!",
3843  config->bd_index);
3844 
3845  return vni;
3846 }
3847 
3848 always_inline void
3850  gid_address_t * src, gid_address_t * dst)
3851 {
3852  u32 vni = 0;
3853  u16 type;
3854 
3855  memset (src, 0, sizeof (*src));
3856  memset (dst, 0, sizeof (*dst));
3857  type = vnet_buffer (b)->lisp.overlay_afi;
3858 
3859  if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
3860  {
3861  ip4_header_t *ip;
3862  u8 version, preflen;
3863 
3866 
3867  ip = vlib_buffer_get_current (b);
3868  get_src_and_dst_ip (ip, &gid_address_ip (src), &gid_address_ip (dst));
3869 
3870  version = gid_address_ip_version (src);
3871  preflen = ip_address_max_len (version);
3872  gid_address_ippref_len (src) = preflen;
3873  gid_address_ippref_len (dst) = preflen;
3874 
3875  vni = lisp_get_vni_from_buffer_ip (lcm, b, version);
3876  gid_address_vni (dst) = vni;
3877  gid_address_vni (src) = vni;
3878  }
3879  else if (LISP_AFI_MAC == type)
3880  {
3881  ethernet_header_t *eh;
3882 
3883  eh = vlib_buffer_get_current (b);
3884 
3887  mac_copy (&gid_address_mac (src), eh->src_address);
3888  mac_copy (&gid_address_mac (dst), eh->dst_address);
3889 
3890  /* get vni */
3891  vni = lisp_get_vni_from_buffer_eth (lcm, b);
3892 
3893  gid_address_vni (dst) = vni;
3894  gid_address_vni (src) = vni;
3895  }
3896 }
3897 
3898 static uword
3900  vlib_node_runtime_t * node,
3901  vlib_frame_t * from_frame, int overlay)
3902 {
3903  u32 *from, *to_next_drop, di, si;
3905  u32 pkts_mapped = 0;
3906  uword n_left_from, n_left_to_next_drop;
3907 
3908  from = vlib_frame_vector_args (from_frame);
3909  n_left_from = from_frame->n_vectors;
3910 
3911  while (n_left_from > 0)
3912  {
3914  to_next_drop, n_left_to_next_drop);
3915 
3916  while (n_left_from > 0 && n_left_to_next_drop > 0)
3917  {
3918  u32 pi0;
3919  vlib_buffer_t *b0;
3920  gid_address_t src, dst;
3921 
3922  pi0 = from[0];
3923  from += 1;
3924  n_left_from -= 1;
3925  to_next_drop[0] = pi0;
3926  to_next_drop += 1;
3927  n_left_to_next_drop -= 1;
3928 
3929  b0 = vlib_get_buffer (vm, pi0);
3930  b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
3931  vnet_buffer (b0)->lisp.overlay_afi = overlay;
3932 
3933  /* src/dst eid pair */
3934  get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
3935 
3936  /* if we have remote mapping for destination already in map-chache
3937  add forwarding tunnel directly. If not send a map-request */
3939  &src);
3940  if (~0 != di)
3941  {
3942  mapping_t *m = vec_elt_at_index (lcm->mapping_pool, di);
3943  /* send a map-request also in case of negative mapping entry
3944  with corresponding action */
3945  if (m->action == LISP_SEND_MAP_REQUEST)
3946  {
3947  /* send map-request */
3948  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
3949  0 /* is_resend */ );
3950  pkts_mapped++;
3951  }
3952  else
3953  {
3955  &src);
3956  if (~0 != si)
3957  {
3958  dp_add_fwd_entry (lcm, si, di);
3959  }
3960  }
3961  }
3962  else
3963  {
3964  /* send map-request */
3965  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
3966  0 /* is_resend */ );
3967  pkts_mapped++;
3968  }
3969 
3971  {
3972  lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
3973  sizeof (*tr));
3974 
3975  memset (tr, 0, sizeof (*tr));
3976  gid_address_copy (&tr->dst_eid, &dst);
3978  &lcm->active_map_resolver);
3979  }
3980  gid_address_free (&dst);
3981  gid_address_free (&src);
3982  }
3983 
3985  n_left_to_next_drop);
3986  }
3988  LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
3989  pkts_mapped);
3990  return from_frame->n_vectors;
3991 }
3992 
3993 static uword
3995  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
3996 {
3997  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP));
3998 }
3999 
4000 static uword
4002  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
4003 {
4004  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP6));
4005 }
4006 
4007 static uword
4009  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
4010 {
4011  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_MAC));
4012 }
4013 
4014 /* *INDENT-OFF* */
4016  .function = lisp_cp_lookup_ip4,
4017  .name = "lisp-cp-lookup-ip4",
4018  .vector_size = sizeof (u32),
4019  .format_trace = format_lisp_cp_lookup_trace,
4021 
4022  .n_errors = LISP_CP_LOOKUP_N_ERROR,
4023  .error_strings = lisp_cp_lookup_error_strings,
4024 
4025  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4026 
4027  .next_nodes = {
4028  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4029  },
4030 };
4031 /* *INDENT-ON* */
4032 
4033 /* *INDENT-OFF* */
4035  .function = lisp_cp_lookup_ip6,
4036  .name = "lisp-cp-lookup-ip6",
4037  .vector_size = sizeof (u32),
4038  .format_trace = format_lisp_cp_lookup_trace,
4040 
4041  .n_errors = LISP_CP_LOOKUP_N_ERROR,
4042  .error_strings = lisp_cp_lookup_error_strings,
4043 
4044  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4045 
4046  .next_nodes = {
4047  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4048  },
4049 };
4050 /* *INDENT-ON* */
4051 
4052 /* *INDENT-OFF* */
4054  .function = lisp_cp_lookup_l2,
4055  .name = "lisp-cp-lookup-l2",
4056  .vector_size = sizeof (u32),
4057  .format_trace = format_lisp_cp_lookup_trace,
4059 
4060  .n_errors = LISP_CP_LOOKUP_N_ERROR,
4061  .error_strings = lisp_cp_lookup_error_strings,
4062 
4063  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
4064 
4065  .next_nodes = {
4066  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
4067  },
4068 };
4069 /* *INDENT-ON* */
4070 
4071 /* lisp_cp_input statistics */
4072 #define foreach_lisp_cp_input_error \
4073 _(DROP, "drop") \
4074 _(MAP_REPLIES_RECEIVED, "map-replies received")
4075 
4077 #define _(sym,string) string,
4079 #undef _
4080 };
4081 
4082 typedef enum
4083 {
4084 #define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
4086 #undef _
4089 
4090 typedef enum
4091 {
4095 
4096 typedef struct
4097 {
4101 
4102 u8 *
4103 format_lisp_cp_input_trace (u8 * s, va_list * args)
4104 {
4105  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
4106  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
4108  va_arg (*args, lisp_cp_input_trace_t *);
4109 
4110  s = format (s, "LISP-CP-INPUT: TODO");
4111  return s;
4112 }
4113 
4114 static void
4116 {
4117  mapping_t *m;
4118 
4119  m = pool_elt_at_index (lcm->mapping_pool, mi);
4120  lisp_add_del_adjacency (lcm, 0, &m->eid, 0 /* is_add */ );
4121  vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ ,
4122  0 /* is_static */ , 0);
4123  mapping_delete_timer (lcm, mi);
4124 }
4125 
4126 static void
4128  f64 expiration_time)
4129 {
4130  mapping_t *m;
4131  u64 now = clib_cpu_time_now ();
4132  u64 cpu_cps = lcm->vlib_main->clib_time.clocks_per_second;
4133  u64 exp_clock_time = now + expiration_time * cpu_cps;
4134 
4135  m = pool_elt_at_index (lcm->mapping_pool, mi);
4136 
4137  m->timer_set = 1;
4138  timing_wheel_insert (&lcm->wheel, exp_clock_time, mi);
4139 }
4140 
4141 static void
4143 {
4144  mapping_t *m;
4145  vec_foreach (m, a->mappings)
4146  {
4147  vec_free (m->locators);
4148  gid_address_free (&m->eid);
4149  }
4150 
4151  clib_mem_free (a);
4152 }
4153 
4154 void *
4156 {
4157  mapping_t *m;
4159  u32 dst_map_index = 0;
4160  pending_map_request_t *pmr;
4161  u64 *noncep;
4162  uword *pmr_index;
4163 
4164  if (a->is_rloc_probe)
4165  goto done;
4166 
4167  /* Check pending requests table and nonce */
4168  pmr_index = hash_get (lcm->pending_map_requests_by_nonce, a->nonce);
4169  if (!pmr_index)
4170  {
4171  clib_warning ("No pending map-request entry with nonce %lu!", a->nonce);
4172  goto done;
4173  }
4174  pmr = pool_elt_at_index (lcm->pending_map_requests_pool, pmr_index[0]);
4175 
4176  vec_foreach (m, a->mappings)
4177  {
4178  /* insert/update mappings cache */
4180  m->authoritative, m->ttl,
4181  1, 0 /* is_static */ , &dst_map_index);
4182 
4183  /* try to program forwarding only if mapping saved or updated */
4184  if ((u32) ~ 0 != dst_map_index)
4185  {
4186  lisp_add_del_adjacency (lcm, &pmr->src, &m->eid, 1);
4187  if ((u32) ~ 0 != m->ttl)
4188  mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60);
4189  }
4190  }
4191 
4192  /* remove pending map request entry */
4193 
4194  /* *INDENT-OFF* */
4195  clib_fifo_foreach (noncep, pmr->nonces, ({
4196  hash_unset(lcm->pending_map_requests_by_nonce, noncep[0]);
4197  }));
4198  /* *INDENT-ON* */
4199 
4200  clib_fifo_free (pmr->nonces);
4201  pool_put (lcm->pending_map_requests_pool, pmr);
4202 
4203 done:
4205  return 0;
4206 }
4207 
4208 static int
4210  lisp_key_type_t key_id, u8 * key)
4211 {
4212  u8 *auth_data = 0;
4213  u16 auth_data_len;
4214  int result;
4215 
4216  auth_data_len = auth_data_len_by_key_id (key_id);
4217  if ((u16) ~ 0 == auth_data_len)
4218  {
4219  clib_warning ("invalid length for key_id %d!", key_id);
4220  return 0;
4221  }
4222 
4223  /* save auth data */
4224  vec_validate (auth_data, auth_data_len - 1);
4225  clib_memcpy (auth_data, MNOTIFY_DATA (h), auth_data_len);
4226 
4227  /* clear auth data */
4228  memset (MNOTIFY_DATA (h), 0, auth_data_len);
4229 
4230  /* get hash of the message */
4231  unsigned char *code = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
4232  (unsigned char *) h, msg_len, NULL, NULL);
4233 
4234  result = memcmp (code, auth_data, auth_data_len);
4235 
4236  vec_free (auth_data);
4237 
4238  return !result;
4239 }
4240 
4241 static void
4243 {
4245  uword *pmr_index;
4246 
4247  pmr_index = hash_get (lcm->map_register_messages_by_nonce, a->nonce);
4248  if (!pmr_index)
4249  {
4250  clib_warning ("No pending map-register entry with nonce %lu!",
4251  a->nonce);
4252  return;
4253  }
4254 
4257 }
4258 
4259 static mapping_t *
4261 {
4262  u32 mi;
4263 
4265  if (~0 == mi)
4266  {
4267  clib_warning ("eid %U not found in map-cache!", unformat_gid_address,
4268  e);
4269  return 0;
4270  }
4271  return pool_elt_at_index (lcm->mapping_pool, mi);
4272 }
4273 
4274 /**
4275  * When map-notify is received it is necessary that all EIDs in the record
4276  * list share common key. The key is then used to verify authentication
4277  * data in map-notify message.
4278  */
4279 static int
4281  u32 key_id, u8 ** key_out)
4282 {
4283  u32 i, len = vec_len (maps);
4284  mapping_t *m;
4285 
4286  /* get key of the first mapping */
4287  m = get_mapping (lcm, &maps[0].eid);
4288  if (!m || !m->key)
4289  return -1;
4290 
4291  key_out[0] = m->key;
4292 
4293  for (i = 1; i < len; i++)
4294  {
4295  m = get_mapping (lcm, &maps[i].eid);
4296  if (!m || !m->key)
4297  return -1;
4298 
4299  if (key_id != m->key_id || vec_cmp (m->key, key_out[0]))
4300  {
4301  clib_warning ("keys does not match! %v, %v", key_out[0], m->key);
4302  return -1;
4303  }
4304  }
4305  return 0;
4306 }
4307 
4308 static int
4310 {
4311  locator_t *locators = 0;
4312  u32 i, len;
4313  gid_address_t deid;
4314  mapping_t m;
4315  locator_t *loc;
4316 
4317  /* parse record eid */
4318  for (i = 0; i < count; i++)
4319  {
4320  len = lisp_msg_parse_mapping_record (b, &deid, &locators, NULL);
4321  if (len == ~0)
4322  {
4323  clib_warning ("Failed to parse mapping record!");
4324  vec_foreach (loc, locators) locator_free (loc);
4325  vec_free (locators);
4326  return -1;
4327  }
4328 
4329  m.locators = locators;
4330  gid_address_copy (&m.eid, &deid);
4331  vec_add1 (a->mappings, m);
4332  }
4333 
4334  return 0;
4335 }
4336 
4337 static map_records_arg_t *
4339 {
4340  int rc = 0;
4341  map_notify_hdr_t *mnotif_hdr;
4342  lisp_key_type_t key_id;
4344  u8 *key = 0;
4345  gid_address_t deid;
4346  u16 auth_data_len = 0;
4347  u8 record_count;
4348  map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
4349 
4350  memset (a, 0, sizeof (*a));
4351  mnotif_hdr = vlib_buffer_get_current (b);
4352  vlib_buffer_pull (b, sizeof (*mnotif_hdr));
4353  memset (&deid, 0, sizeof (deid));
4354 
4355  a->nonce = MNOTIFY_NONCE (mnotif_hdr);
4356  key_id = clib_net_to_host_u16 (MNOTIFY_KEY_ID (mnotif_hdr));
4357  auth_data_len = auth_data_len_by_key_id (key_id);
4358 
4359  /* advance buffer by authentication data */
4360  vlib_buffer_pull (b, auth_data_len);
4361 
4362  record_count = MNOTIFY_REC_COUNT (mnotif_hdr);
4363  rc = parse_map_records (b, a, record_count);
4364  if (rc != 0)
4365  {
4367  return 0;
4368  }
4369 
4370  rc = map_record_integrity_check (lcm, a->mappings, key_id, &key);
4371  if (rc != 0)
4372  {
4374  return 0;
4375  }
4376 
4377  /* verify authentication data */
4378  if (!is_auth_data_valid (mnotif_hdr, vlib_buffer_get_tail (b)
4379  - (u8 *) mnotif_hdr, key_id, key))
4380  {
4381  clib_warning ("Map-notify auth data verification failed for nonce %lu!",
4382  a->nonce);
4384  return 0;
4385  }
4386  return a;
4387 }
4388 
4389 static vlib_buffer_t *
4390 build_map_reply (lisp_cp_main_t * lcm, ip_address_t * sloc,
4391  ip_address_t * dst, u64 nonce, u8 probe_bit,
4392  mapping_t * records, u16 dst_port, u32 * bi_res)
4393 {
4394  vlib_buffer_t *b;
4395  u32 bi;
4396  vlib_main_t *vm = lcm->vlib_main;
4397 
4398  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
4399  {
4400  clib_warning ("Can't allocate buffer for Map-Register!");
4401  return 0;
4402  }
4403 
4404  b = vlib_get_buffer (vm, bi);
4405 
4406  /* leave some space for the encap headers */
4408 
4409  lisp_msg_put_map_reply (b, records, nonce, probe_bit);
4410 
4411  /* push outer ip header */
4412  pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst);
4413 
4414  bi_res[0] = bi;
4415  return b;
4416 }
4417 
4418 static int
4419 send_map_reply (lisp_cp_main_t * lcm, u32 mi, ip_address_t * dst,
4420  u8 probe_bit, u64 nonce, u16 dst_port,
4421  ip_address_t * probed_loc)
4422 {
4423  ip_address_t src;
4424  u32 bi;
4425  vlib_buffer_t *b;
4426  vlib_frame_t *f;
4427  u32 next_index, *to_next;
4428  mapping_t *records = 0, *m;
4429 
4430  m = pool_elt_at_index (lcm->mapping_pool, mi);
4431  if (!m)
4432  return -1;
4433 
4434  vec_add1 (records, m[0]);
4435  add_locators (lcm, &records[0], m->locator_set_index, probed_loc);
4436  memset (&src, 0, sizeof (src));
4437 
4438  if (!ip_fib_get_first_egress_ip_for_dst (lcm, dst, &src))
4439  {
4440  clib_warning ("can't find inteface address for %U", format_ip_address,
4441  dst);
4442  return -1;
4443  }
4444 
4445  b = build_map_reply (lcm, &src, dst, nonce, probe_bit, records, dst_port,
4446  &bi);
4447  if (!b)
4448  return -1;
4449  free_map_register_records (records);
4450 
4451  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
4452  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
4453  ip4_lookup_node.index : ip6_lookup_node.index;
4454 
4455  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
4456 
4457  /* Enqueue the packet */
4458  to_next = vlib_frame_vector_args (f);
4459  to_next[0] = bi;
4460  f->n_vectors = 1;
4461  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
4462  return 0;
4463 }
4464 
4465 void
4467  vlib_buffer_t * b)
4468 {
4469  u8 *ip_hdr = 0, *udp_hdr;
4470  ip4_header_t *ip4;
4471  ip6_header_t *ip6;
4472  ip_address_t *dst_loc = 0, probed_loc, src_loc;
4473  mapping_t m;
4474  map_request_hdr_t *mreq_hdr;
4475  gid_address_t src, dst;
4476  u64 nonce;
4477  u32 i, len = 0;
4478  gid_address_t *itr_rlocs = 0;
4479 
4480  mreq_hdr = vlib_buffer_get_current (b);
4481 
4482  // TODO ugly workaround to find out whether LISP is carried by ip4 or 6
4483  // and needs to be fixed
4484  udp_hdr = (u8 *) vlib_buffer_get_current (b) - sizeof (udp_header_t);
4485  ip4 = (ip4_header_t *) (udp_hdr - sizeof (ip4_header_t));
4486  ip6 = (ip6_header_t *) (udp_hdr - sizeof (ip6_header_t));
4487 
4488  if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
4489  ip_hdr = (u8 *) ip4;
4490  else
4491  {
4492  u32 flags = clib_net_to_host_u32
4494  if ((flags & 0xF0000000) == 0x60000000)
4495  ip_hdr = (u8 *) ip6;
4496  else
4497  {
4498  clib_warning ("internal error: cannot determine whether packet "
4499  "is ip4 or 6!");
4500  return;
4501  }
4502  }
4503 
4504  vlib_buffer_pull (b, sizeof (*mreq_hdr));
4505 
4506  nonce = MREQ_NONCE (mreq_hdr);
4507 
4508  if (!MREQ_SMR (mreq_hdr) && !MREQ_RLOC_PROBE (mreq_hdr))
4509  {
4510  clib_warning
4511  ("Only SMR Map-Requests and RLOC probe supported for now!");
4512  return;
4513  }
4514 
4515  /* parse src eid */
4516  len = lisp_msg_parse_addr (b, &src);
4517  if (len == ~0)
4518  return;
4519 
4520  len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs,
4521  MREQ_ITR_RLOC_COUNT (mreq_hdr) + 1);
4522  if (len == ~0)
4523  return;
4524 
4525  /* parse eid records and send SMR-invoked map-requests */
4526  for (i = 0; i < MREQ_REC_COUNT (mreq_hdr); i++)
4527  {
4528  memset (&dst, 0, sizeof (dst));
4529  len = lisp_msg_parse_eid_rec (b, &dst);
4530  if (len == ~0)
4531  {
4532  clib_warning ("Can't parse map-request EID-record");
4533  goto done;
4534  }
4535 
4536  if (MREQ_SMR (mreq_hdr))
4537  {
4538  /* send SMR-invoked map-requests */
4539  queue_map_request (&dst, &src, 1 /* invoked */ , 0 /* resend */ );
4540  }
4541  else if (MREQ_RLOC_PROBE (mreq_hdr))
4542  {
4543  memset (&m, 0, sizeof (m));
4544  u32 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
4545 
4546  // TODO: select best locator; for now use the first one
4547  dst_loc = &gid_address_ip (&itr_rlocs[0]);
4548 
4549  /* get src/dst IP addresses */
4550  get_src_and_dst_ip (ip_hdr, &src_loc, &probed_loc);
4551 
4552  // TODO get source port from buffer
4553  u16 src_port = LISP_CONTROL_PORT;
4554 
4555  send_map_reply (lcm, mi, dst_loc, 1 /* probe-bit */ , nonce,
4556  src_port, &probed_loc);
4557  }
4558  }
4559 
4560 done:
4561  vec_free (itr_rlocs);
4562 }
4563 
4564 static map_records_arg_t *
4566 {
4567  locator_t probed;
4568  gid_address_t deid;
4569  void *h;
4570  u32 i, len = 0;
4571  mapping_t m;
4572  map_reply_hdr_t *mrep_hdr;
4573  map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
4574  memset (a, 0, sizeof (*a));
4575  locator_t *locators;
4576 
4577  mrep_hdr = vlib_buffer_get_current (b);
4578  a->nonce = MREP_NONCE (mrep_hdr);
4579  a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr);
4580  vlib_buffer_pull (b, sizeof (*mrep_hdr));
4581 
4582  for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
4583  {
4584  memset (&m, 0, sizeof (m));
4585  locators = 0;
4586  h = vlib_buffer_get_current (b);
4587 
4588  m.ttl = clib_net_to_host_u32 (MAP_REC_TTL (h));
4589  m.action = MAP_REC_ACTION (h);
4590  m.authoritative = MAP_REC_AUTH (h);
4591 
4592  len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
4593  if (len == ~0)
4594  {
4595  clib_warning ("Failed to parse mapping record!");
4597  return 0;
4598  }
4599 
4600  m.locators = locators;
4601  gid_address_copy (&m.eid, &deid);
4602  vec_add1 (a->mappings, m);
4603  }
4604  return a;
4605 }
4606 
4607 static void
4609 {
4610  vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (a));
4611 }
4612 
4613 static void
4615 {
4616  vl_api_rpc_call_main_thread (process_map_notify, (u8 *) a, sizeof (a[0]));
4617 }
4618 
4619 static uword
4621  vlib_frame_t * from_frame)
4622 {
4623  u32 n_left_from, *from, *to_next_drop;
4627 
4628  from = vlib_frame_vector_args (from_frame);
4629  n_left_from = from_frame->n_vectors;
4630 
4631 
4632  while (n_left_from > 0)
4633  {
4634  u32 n_left_to_next_drop;
4635 
4637  to_next_drop, n_left_to_next_drop);
4638  while (n_left_from > 0 && n_left_to_next_drop > 0)
4639  {
4640  u32 bi0;
4641  vlib_buffer_t *b0;
4642 
4643  bi0 = from[0];
4644  from += 1;
4645  n_left_from -= 1;
4646  to_next_drop[0] = bi0;
4647  to_next_drop += 1;
4648  n_left_to_next_drop -= 1;
4649 
4650  b0 = vlib_get_buffer (vm, bi0);
4651 
4652  type = lisp_msg_type (vlib_buffer_get_current (b0));
4653  switch (type)
4654  {
4655  case LISP_MAP_REPLY:
4656  a = parse_map_reply (b0);
4657  if (a)
4659  break;
4660  case LISP_MAP_REQUEST:
4661  process_map_request (vm, lcm, b0);
4662  break;
4663  case LISP_MAP_NOTIFY:
4664  a = parse_map_notify (b0);
4665  if (a)
4667  break;
4668  default:
4669  clib_warning ("Unsupported LISP message type %d", type);
4670  break;
4671  }
4672 
4673  b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
4674 
4676  {
4677 
4678  }
4679  }
4680 
4682  n_left_to_next_drop);
4683  }
4684  return from_frame->n_vectors;
4685 }
4686 
4687 /* *INDENT-OFF* */
4689  .function = lisp_cp_input,
4690  .name = "lisp-cp-input",
4691  .vector_size = sizeof (u32),
4692  .format_trace = format_lisp_cp_input_trace,
4694 
4695  .n_errors = LISP_CP_INPUT_N_ERROR,
4696  .error_strings = lisp_cp_input_error_strings,
4697 
4698  .n_next_nodes = LISP_CP_INPUT_N_NEXT,
4699 
4700  .next_nodes = {
4701  [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
4702  },
4703 };
4704 /* *INDENT-ON* */
4705 
4706 clib_error_t *
4708 {
4710  clib_error_t *error = 0;
4711 
4712  if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
4713  return error;
4714 
4715  lcm->im4 = &ip4_main;
4716  lcm->im6 = &ip6_main;
4717  lcm->vlib_main = vm;
4718  lcm->vnet_main = vnet_get_main ();
4719  lcm->mreq_itr_rlocs = ~0;
4720  lcm->lisp_pitr = 0;
4721  memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver));
4722 
4724  lcm->do_map_resolver_election = 1;
4726 
4727  /* default vrf mapped to vni 0 */
4728  hash_set (lcm->table_id_by_vni, 0, 0);
4729  hash_set (lcm->vni_by_table_id, 0, 0);
4730 
4731  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
4732  lisp_cp_input_node.index, 1 /* is_ip4 */ );
4733  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
4734  lisp_cp_input_node.index, 0 /* is_ip4 */ );
4735 
4736  u64 now = clib_cpu_time_now ();
4738  return 0;
4739 }
4740 
4741 static void *
4743 {
4744  map_request_args_t *a = arg;
4746 
4747  if (a->is_resend)
4749  else
4750  send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
4751 
4752  return 0;
4753 }
4754 
4755 static int
4757  u8 smr_invoked, u8 is_resend)
4758 {
4760 
4761  a.is_resend = is_resend;
4762  gid_address_copy (&a.seid, seid);
4763  gid_address_copy (&a.deid, deid);
4764  a.smr_invoked = smr_invoked;
4765 
4767  (u8 *) & a, sizeof (a));
4768  return 0;
4769 }
4770 
4771 /**
4772  * Take an action with a pending map request depending on expiration time
4773  * and re-try counters.
4774  */
4775 static void
4777 {
4779  lisp_msmr_t *mr;
4780 
4781  if (r->time_to_expire - dt < 0)
4782  /* it's time to decide what to do with this pending request */
4783  {
4784  if (r->retries_num >= NUMBER_OF_RETRIES)
4785  /* too many retries -> assume current map resolver is not available */
4786  {
4788  if (!mr)
4789  {
4790  clib_warning ("Map resolver %U not found - probably deleted "
4791  "by the user recently.", format_ip_address,
4792  &lcm->active_map_resolver);
4793  }
4794  else
4795  {
4796  clib_warning ("map resolver %U is unreachable, ignoring",
4798 
4799  /* mark current map resolver unavailable so it won't be
4800  * selected next time */
4801  mr->is_down = 1;
4802  mr->last_update = vlib_time_now (lcm->vlib_main);
4803  }
4804 
4806  elect_map_resolver (lcm);
4807 
4808  /* try to find a next eligible map resolver and re-send */
4809  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4810  1 /* resend */ );
4811  }
4812  else
4813  {
4814  /* try again */
4815  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4816  1 /* resend */ );
4817  r->retries_num++;
4819  }
4820  }
4821  else
4822  r->time_to_expire -= dt;
4823 }
4824 
4825 static void
4827 {
4828  u64 *nonce;
4829  pending_map_request_t *pmr;
4830  u32 *to_be_removed = 0, *pmr_index;
4831 
4832  /* *INDENT-OFF* */
4834  ({
4835  if (pmr->to_be_removed)
4836  {
4837  clib_fifo_foreach (nonce, pmr->nonces, ({
4838  hash_unset (lcm->pending_map_requests_by_nonce, nonce[0]);
4839  }));
4840 
4841  vec_add1 (to_be_removed, pmr - lcm->pending_map_requests_pool);
4842  }
4843  }));
4844  /* *INDENT-ON* */
4845 
4846  vec_foreach (pmr_index, to_be_removed)
4847  pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]);
4848 
4849  vec_free (to_be_removed);
4850 }
4851 
4852 static void
4854 {
4855  static f64 time_left = RLOC_PROBING_INTERVAL;
4856 
4857  if (!lcm->is_enabled || !lcm->rloc_probing)
4858  return;
4859 
4860  time_left -= dt;
4861  if (time_left <= 0)
4862  {
4863  time_left = RLOC_PROBING_INTERVAL;
4864  send_rloc_probes (lcm);
4865  }
4866 }
4867 
4868 static void
4870 {
4871  static f64 time_left = QUICK_MAP_REGISTER_INTERVAL;
4872  static u64 mreg_sent_counter = 0;
4873 
4874  if (!lcm->is_enabled || !lcm->map_registering)
4875  return;
4876 
4877  time_left -= dt;
4878  if (time_left <= 0)
4879  {
4880  if (mreg_sent_counter >= QUICK_MAP_REGISTER_MSG_COUNT)
4881  time_left = MAP_REGISTER_INTERVAL;
4882  else
4883  {
4884  mreg_sent_counter++;
4885  time_left = QUICK_MAP_REGISTER_INTERVAL;
4886  }
4887  send_map_register (lcm, 1 /* want map notify */ );
4888  }
4889 }
4890 
4891 static uword
4894 {
4895  u32 *expired = 0;
4896  f64 period = 2.0;
4897  pending_map_request_t *pmr;
4899 
4900  while (1)
4901  {
4903 
4904  /* currently no signals are expected - just wait for clock */
4905  (void) vlib_process_get_events (vm, 0);
4906 
4907  /* *INDENT-OFF* */
4909  ({
4910  if (!pmr->to_be_removed)
4911  update_pending_request (pmr, period);
4912  }));
4913  /* *INDENT-ON* */
4914 
4916 
4917  update_map_register (lcm, period);
4918  update_rloc_probing (lcm, period);
4919 
4920  u64 now = clib_cpu_time_now ();
4921 
4922  expired = timing_wheel_advance (&lcm->wheel, now, expired, 0);
4923  if (vec_len (expired) > 0)
4924  {
4925  u32 *mi = 0;
4926  vec_foreach (mi, expired)
4927  {
4928  remove_expired_mapping (lcm, mi[0]);
4929  }
4930  _vec_len (expired) = 0;
4931  }
4932  }
4933 
4934  /* unreachable */
4935  return 0;
4936 }
4937 
4938 /* *INDENT-OFF* */
4940  .function = send_map_resolver_service,
4941  .type = VLIB_NODE_TYPE_PROCESS,
4942  .name = "lisp-retry-service",
4943  .process_log2_n_stack_bytes = 16,
4944 };
4945 /* *INDENT-ON* */
4946 
4948 
4949 /*
4950  * fd.io coding-style-patch-verification: ON
4951  *
4952  * Local Variables:
4953  * eval: (c-set-style "gnu")
4954  * End:
4955  */
void lisp_gpe_tenant_l2_iface_unlock(u32 vni)
Release the lock held on the tenant&#39;s L3 interface.
static u8 * vlib_buffer_get_tail(vlib_buffer_t *b)
Definition: packets.h:30
#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:1764
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:459
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:460
#define QUICK_MAP_REGISTER_INTERVAL
Definition: control.h:34
#define MNOTIFY_REC_COUNT(h_)
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:154
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:535
#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:4620
#define gid_address_ip_version(_a)
Definition: lisp_types.h:232
#define vec_foreach_index(var, v)
Iterate over vector indices.
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, u8 rloc_probe_set, u64 *nonce)
u8 is_down
Definition: control.h:76
u32 pitr_map_index
Definition: control.h:174
void * lisp_msg_put_map_register(vlib_buffer_t *b, mapping_t *records, u8 want_map_notify, u16 auth_data_len, u64 *nonce, u32 *msg_len)
#define MREP_REC_COUNT(h_)
static int send_map_register(lisp_cp_main_t *lcm, u8 want_map_notif)
Definition: control.c:3577
#define hash_set(h, key, value)
Definition: hash.h:254
l2_input_config_t * configs
Definition: l2_input.h:66
gid_address_t leid
Definition: control.h:63
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_fifo_head(v)
Definition: fifo.h:254
static clib_error_t * lisp_map_request_mode_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1687
#define gid_address_type(_a)
Definition: lisp_types.h:228
#define CLIB_UNUSED(x)
Definition: clib.h:79
u8 timer_set
Definition: lisp_types.h:324
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
vlib_node_registration_t lisp_cp_lookup_ip4_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node)
Definition: control.c:4015
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:1830
static void mapping_start_expiration_timer(lisp_cp_main_t *lcm, u32 mi, f64 expiration_time)
Definition: control.c:4127
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:684
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
gid_address_t deid
Definition: control.c:33
#define SHA256_AUTH_DATA_LEN
Definition: lisp_types.h:23
lisp_cp_lookup_next_t
Definition: control.c:3129
ip4_address_t src_address
Definition: ip4_packet.h:163
static uword clib_fifo_elts(void *v)
Definition: fifo.h:66
ip_address_t active_map_resolver
Definition: control.h:155
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define RLOC_PROBING_INTERVAL
Definition: control.h:28
lisp_msmr_t * map_resolvers
Definition: control.h:146
#define MAP_REC_TTL(h)
gid_address_t dst_eid
Definition: control.c:4098
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
void ip_prefix_to_fib_prefix(const ip_prefix_t *ip_prefix, fib_prefix_t *fib_prefix)
convert from a LISP to a FIB prefix
Definition: control.c:159
#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:3268
static u8 * format_lisp_map_request_mode(u8 *s, va_list *args)
Definition: control.c:1731
locator_pair_t * locator_pairs
Definition: control.h:58
uword * table_id_by_vni
Definition: control.h:163
static void queue_map_notify_for_processing(map_records_arg_t *a)
Definition: control.c:4614
void timing_wheel_init(timing_wheel_t *w, u64 current_cpu_time, f64 cpu_clocks_per_second)
Definition: timing_wheel.c:21
void lisp_gpe_tenant_l3_iface_unlock(u32 vni)
Release the lock held on the tenant&#39;s L3 interface.
static map_records_arg_t * parse_map_reply(vlib_buffer_t *b)
Definition: control.c:4565
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static clib_error_t * lisp_show_adjacencies_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:557
clib_error_t * vnet_lisp_gpe_enable_disable(vnet_lisp_gpe_enable_disable_args_t *a)
Enable/disable LISP-GPE.
Definition: lisp_gpe.c:183
#define NULL
Definition: clib.h:55
#define foreach_lisp_cp_input_error
Definition: control.c:4072
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:2610
u32 * local_mappings_indexes
Definition: control.h:127
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
locator_t * locator_pool
Definition: control.h:112
f64 clocks_per_second
Definition: time.h:53
#define PENDING_MREQ_QUEUE_LEN
Definition: control.h:25
u8 src_address[6]
Definition: packet.h:54
LISP-GPE global state.
Definition: lisp_gpe.h:89
u8 vnet_lisp_get_map_request_mode(void)
Definition: control.c:49
static int elect_map_resolver(lisp_cp_main_t *lcm)
Definition: control.c:3330
#define ip_prefix_len(_a)
Definition: lisp_types.h:73
void ip_address_to_fib_prefix(const ip_address_t *addr, fib_prefix_t *prefix)
convert from a LISP address to a FIB prefix
Definition: control.c:138
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:53
static u64 clib_cpu_time_now(void)
Definition: time.h:73
LISP-GPE definitions.
lisp_cp_input_next_t
Definition: control.c:4090
#define QUICK_MAP_REGISTER_MSG_COUNT
Definition: control.h:33
#define MREG_KEY_ID(h_)
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:171
#define hash_set_mem(h, key, value)
Definition: hash.h:274
static char * lisp_cp_input_error_strings[]
Definition: control.c:4076
ip_lookup_main_t lookup_main
Definition: ip4.h:97
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
clib_time_t clib_time
Definition: main.h:62
#define SHA1_AUTH_DATA_LEN
Definition: lisp_types.h:22
static void remove_dead_pending_map_requests(lisp_cp_main_t *lcm)
Definition: control.c:4826
void ip_address_copy(ip_address_t *dst, const ip_address_t *src)
Definition: lisp_types.c:750
ip_address_t address
Definition: control.h:78
void ip_address_set(ip_address_t *dst, const void *src, u8 version)
Definition: lisp_types.c:772
static lisp_msmr_t * get_map_server(ip_address_t *a)
Definition: control.c:609
void timing_wheel_insert(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
Definition: timing_wheel.c:292
vlib_error_t * errors
Definition: node.h:419
static clib_error_t * lisp_map_register_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2500
uword * vni_by_table_id
Definition: control.h:164
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
uword unformat_hmac_key_id(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:273
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:2760
ip6_address_t src_address
Definition: ip6_packet.h:337
#define ip_prefix_version(_a)
Definition: lisp_types.h:72
format_function_t format_vnet_sw_if_index_name
#define fid_addr_mac(_a)
Definition: lisp_types.h:126
void gid_dictionary_init(gid_dictionary_t *db)
u8 vnet_lisp_map_register_state_get(void)
Definition: control.c:413
static int send_map_reply(lisp_cp_main_t *lcm, u32 mi, ip_address_t *dst, u8 probe_bit, u64 nonce, u16 dst_port, ip_address_t *probed_loc)
Definition: control.c:4419
int vnet_lisp_set_map_request_mode(u8 mode)
Definition: control.c:1666
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:1033
static void clean_locator_to_locator_set(lisp_cp_main_t *lcm, u32 lsi)
Definition: control.c:2067
int vnet_lisp_add_del_adjacency(vnet_lisp_add_del_adjacency_args_t *a)
Definition: control.c:1419
uword value[0]
Definition: hash.h:164
#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:2834
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:511
uword unformat_negative_mapping_action(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:333
#define MNOTIFY_NONCE(h_)
static int update_map_register_auth_data(map_register_hdr_t *map_reg_hdr, lisp_key_type_t key_id, u8 *key, u16 auth_data_len, u32 msg_len)
Definition: control.c:3422
lisp_msmr_t * map_servers
Definition: control.h:149
#define MREQ_NONCE(h_)
static void reset_pending_mr_counters(pending_map_request_t *r)
Definition: control.c:3323
u32 ** locator_to_locator_sets
Definition: control.h:118
vlib_main_t * vlib_main
Definition: control.h:194
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static clib_error_t * lisp_rloc_probe_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:2548
#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:873
#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:527
#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:188
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
u8 * key
Definition: lisp_types.h:322
u16 bd_id
bridge domain id
Definition: lisp_gpe.h:216
gid_address_t * eids_to_be_deleted
Definition: control.c:1100
ip4_address_t dst_address
Definition: ip4_packet.h:163
u8 dst_address[6]
Definition: packet.h:53
u8 is_add
Definition: lisp_gpe.h:180
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:418
void di(unformat_input_t *i)
Definition: unformat.c:163
#define gid_address_sd_src(_a)
Definition: lisp_types.h:242
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:145
u32 * fwd_entry_by_mapping_index
Definition: control.h:131
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1268
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
static mapping_t * get_mapping(lisp_cp_main_t *lcm, gid_address_t *e)
Definition: control.c:4260
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
int vnet_lisp_eid_table_map(u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
Definition: control.c:977
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:296
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
uword * bd_id_by_vni
Definition: control.h:167
u32 lisp_gpe_tenant_l2_iface_add_or_lock(u32 vni, u32 bd_id)
Add/create and lock a new or find and lock the existing L2 interface for the tenant.
static lisp_cp_main_t * vnet_lisp_cp_get_main()
Definition: control.h:208
u16 fp_len
The mask length.
Definition: fib_types.h:149
#define vlib_call_init_function(vm, x)
Definition: init.h:161
static void * send_map_request_thread_fn(void *arg)
Definition: control.c:4742
uword * vni_by_bd_id
Definition: control.h:168
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:66
Definition: lisp_gpe.h:178
gid_address_t src
Definition: control.h:44
#define ip_addr_version(_a)
Definition: lisp_types.h:56
ip6_main_t * im6
Definition: control.h:193
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:4776
clib_error_t * vnet_lisp_enable_disable(u8 is_enable)
Definition: control.c:2415
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:2457
vlib_node_registration_t lisp_cp_lookup_ip6_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node)
Definition: control.c:4034
static void add_locators(lisp_cp_main_t *lcm, mapping_t *m, u32 locator_set_index, ip_address_t *probed_loc)
Definition: control.c:3356
u32 gid_dictionary_lookup(gid_dictionary_t *db, gid_address_t *key)
#define hash_get(h, key)
Definition: hash.h:248
#define MREQ_RLOC_PROBE(h_)
static void mapping_delete_timer(lisp_cp_main_t *lcm, u32 mi)
Definition: control.c:1179
u8 is_src_dst
Definition: control.h:57
int vnet_lisp_pitr_set_locator_set(u8 *locator_set_name, u8 is_add)
Definition: control.c:1787
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
u8 vnet_lisp_rloc_probe_state_get(void)
Definition: control.c:420
static void queue_map_reply_for_processing(map_records_arg_t *a)
Definition: control.c:4608
#define hash_unset_mem(h, key)
Definition: hash.h:280
lisp_cp_lookup_error_t
Definition: control.c:3121
u8 do_map_resolver_election
Definition: control.h:157
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
u32 table_id
table (vrf) id
Definition: lisp_gpe.h:213
f64 last_update
Definition: control.h:77
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:168
void gid_dict_foreach_subprefix(gid_dictionary_t *db, gid_address_t *eid, foreach_subprefix_match_cb_t cb, void *arg)
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:234
static u16 auth_data_len_by_key_id(lisp_key_type_t key_id)
Definition: control.c:56
int get_mr_and_local_iface_ip(lisp_cp_main_t *lcm, ip_address_t *mr_ip, ip_address_t *sloc)
Definition: control.c:3155
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:738
#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:839
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:4939
vlib_node_registration_t lisp_cp_input_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_input_node)
Definition: control.c:4688
#define MNOTIFY_KEY_ID(h_)
#define hash_free(h)
Definition: hash.h:286
void gid_address_free(gid_address_t *a)
Definition: lisp_types.c:714
vlib_node_registration_t lisp_cp_lookup_l2_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node)
Definition: control.c:4053
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define gid_address_sd_dst_type(_a)
Definition: lisp_types.h:245
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
u8 authoritative
Definition: lisp_types.h:317
#define unformat_parse_error(input)
Definition: format.h:267
static void remove_expired_mapping(lisp_cp_main_t *lcm, u32 mi)
Definition: control.c:4115
u32 * local_locator_set_indexes
Definition: control.h:128
#define PREDICT_FALSE(x)
Definition: clib.h:97
static int map_record_integrity_check(lisp_cp_main_t *lcm, mapping_t *maps, u32 key_id, u8 **key_out)
When map-notify is received it is necessary that all EIDs in the record list share common key...
Definition: control.c:4280
uword unformat_gid_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:298
gid_address_t reid
Definition: control.h:56
#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:226
static uword lisp_cp_lookup_ip4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3994
ip_address_t lcl_loc
Definition: lisp_types.h:334
u8 map_request_mode
Definition: control.h:180
static u8 compare_locators(lisp_cp_main_t *lcm, u32 *old_ls_indexes, locator_t *new_locators)
Definition: control.c:1074
#define foreach_lisp_cp_lookup_error
Definition: control.c:3111
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
#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:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
ip_address_t map_resolver_ip
Definition: control.c:3138
#define MREG_AUTH_DATA_LEN(h_)
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:1198
#define clib_fifo_foreach(v, f, body)
Definition: fifo.h:279
static void process_map_notify(map_records_arg_t *a)
Definition: control.c:4242
u32 decap_next_index
Definition: lisp_gpe.h:204
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:2939
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:121
u8 map_registering
Definition: control.h:183
static int queue_map_request(gid_address_t *seid, gid_address_t *deid, u8 smr_invoked, u8 is_resend)
Definition: control.c:4756
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1113
static void remove_locator_from_locator_set(locator_set_t *ls, u32 *locit, u32 ls_index, u32 loc_id)
Definition: control.c:2151
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:2630
#define gid_address_ippref(_a)
Definition: lisp_types.h:229
static void * vlib_buffer_pull(vlib_buffer_t *b, u8 size)
Definition: packets.h:64
lisp_adjacency_t * vnet_lisp_adjacencies_get_by_vni(u32 vni)
Returns vector of adjacencies.
Definition: control.c:535
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1301
u8 is_negative
type of mapping
Definition: lisp_gpe.h:183
static int is_locator_in_locator_set(lisp_cp_main_t *lcm, locator_set_t *ls, locator_t *loc)
Definition: control.c:2127
#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:279
clib_error_t * lisp_cp_init(vlib_main_t *vm)
Definition: control.c:4707
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:3028
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Definition: packets.h:56
u32 vni
VNI/tenant id in HOST byte order.
Definition: lisp_gpe.h:207
static vlib_buffer_t * build_map_reply(lisp_cp_main_t *lcm, ip_address_t *sloc, ip_address_t *dst, u64 nonce, u8 probe_bit, mapping_t *records, u16 dst_port, u32 *bi_res)
Definition: control.c:4390
static uword lisp_cp_lookup_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:4008
uword * pending_map_requests_by_nonce
Definition: control.h:137
static void dp_add_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:427
int vnet_lisp_add_del_mreq_itr_rlocs(vnet_lisp_add_del_mreq_itr_rloc_args_t *a)
Definition: control.c:2997
u16 n_vectors
Definition: node.h:344
u8 * format_lisp_cp_input_trace(u8 *s, va_list *args)
Definition: control.c:4103
static lisp_msmr_t * get_map_resolver(ip_address_t *a)
Definition: control.c:625
#define MAP_REC_ACTION(h)
int gid_address_cmp(gid_address_t *a1, gid_address_t *a2)
Definition: lisp_types.c:1433
#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:230
static map_records_arg_t * parse_map_notify(vlib_buffer_t *b)
Definition: control.c:4338
vnet_main_t * vnet_main
Definition: lisp_gpe.h:124
u32 lisp_msg_parse_mapping_record(vlib_buffer_t *b, gid_address_t *eid, locator_t **locs, locator_t *probed_)
static void remove_mapping_if_needed(u32 mi, void *arg)
Callback invoked when a sub-prefix is found.
Definition: control.c:1107
u32 locator_set_index
Definition: lisp_types.h:311
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:69
u32 * timing_wheel_advance(timing_wheel_t *w, u64 advance_cpu_time, u32 *expired_user_data, u64 *next_expiring_element_cpu_time)
Definition: timing_wheel.c:588
void timing_wheel_delete(timing_wheel_t *w, u32 user_data)
Definition: timing_wheel.c:329
u32 locator_cmp(locator_t *l1, locator_t *l2)
Definition: lisp_types.c:1516
static void update_map_register(lisp_cp_main_t *lcm, f64 dt)
Definition: control.c:4869
int vnet_lisp_map_register_enable_disable(u8 is_enable)
Definition: control.c:2406
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
void * lisp_msg_put_map_reply(vlib_buffer_t *b, mapping_t *records, u64 nonce, u8 probe_bit)
ip4_address_t map_resolver_ip
Definition: control.c:4099
static int send_rloc_probe(lisp_cp_main_t *lcm, gid_address_t *deid, u32 local_locator_set_index, ip_address_t *sloc, ip_address_t *rloc)
Definition: control.c:3496
lisp_key_type_t key_id
Definition: lisp_types.h:323
lisp_gpe_main_t lisp_gpe_main
LISP-GPE global state.
Definition: lisp_gpe.c:27
void * ip_interface_get_first_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 version)
Definition: control.c:107
static 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:1369
#define fid_addr_ippref(_a)
Definition: lisp_types.h:125
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
int vnet_lisp_gpe_add_del_fwd_entry(vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u32 *hw_if_indexp)
Forwarding entry create/remove dispatcher.
u8 vnet_lisp_enable_disable_status(void)
Definition: control.c:2596
timing_wheel_t wheel
Definition: control.h:189
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:675
static uword send_map_resolver_service(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: control.c:4892
struct _gid_address_t gid_address_t
u32 fib_table_get_table_id_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the Table-ID of the FIB bound to the interface.
Definition: fib_table.c:935
uword unformat_mac_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:190
u8 * format_vnet_lisp_gpe_status(u8 *s, va_list *args)
Format LISP-GPE status.
Definition: lisp_gpe.c:282
#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:119
int vnet_lisp_add_del_map_server(ip_address_t *addr, u8 is_add)
Definition: control.c:641
#define ASSERT(truth)
#define fid_addr_type(_a)
Definition: lisp_types.h:127
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
static int send_rloc_probes(lisp_cp_main_t *lcm)
Definition: control.c:3534
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:361
int vnet_lisp_clear_all_remote_adjacencies(void)
Definition: control.c:1318
ip6_main_t ip6_main
Definition: ip6_forward.c:2828
ip_lookup_main_t lookup_main
Definition: ip6.h:135
#define gid_address_sd_dst(_a)
Definition: lisp_types.h:243
#define MAP_REGISTER_INTERVAL
Definition: control.h:37
gid_address_t seid
Definition: control.c:32
static void get_src_and_dst_ip(void *hdr, ip_address_t *src, ip_address_t *dst)
Definition: control.c:3782
clib_error_t * lisp_gpe_init(vlib_main_t *vm)
LISP-GPE init function.
Definition: lisp_gpe.c:291
gid_dictionary_t mapping_index_by_gid
Definition: control.h:103
ip_interface_address_t * ip_interface_get_first_interface_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 loop)
Definition: control.c:92
u32 gid_dictionary_sd_lookup(gid_dictionary_t *db, gid_address_t *dst, gid_address_t *src)
static u32 lisp_get_vni_from_buffer_ip(lisp_cp_main_t *lcm, vlib_buffer_t *b, u8 version)
Definition: control.c:3801
locator_set_t * locator_set_pool
Definition: control.h:115
static void clib_mem_free(void *p)
Definition: mem.h:176
static clib_error_t * lisp_show_map_request_mode_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:1746
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:3081
u8 is_static
Definition: lisp_types.h:321
static void gid_address_sd_to_flat(gid_address_t *dst, gid_address_t *src, fid_address_t *fid)
Definition: control.c:389
int vnet_lisp_rloc_probe_enable_disable(u8 is_enable)
Definition: control.c:2397
u32 ** locator_set_to_eids
Definition: control.h:124
#define LISP_CONTROL_PORT
static u8 * format_eid_entry(u8 *s, va_list *args)
Definition: control.c:1935
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:880
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
gid_address_t rmt_eid
remote eid
Definition: lisp_gpe.h:192
uword unformat_ip_prefix(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:170
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:1561
#define clib_fifo_free(f)
Definition: fifo.h:257
static void * clib_mem_alloc(uword size)
Definition: mem.h:109
fwd_entry_t * fwd_entry_pool
Definition: control.h:134
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
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:140
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:324
int vnet_lisp_add_del_locator_set(vnet_lisp_add_del_locator_set_args_t *a, u32 *ls_result)
Definition: control.c:2257
#define gid_address_ip(_a)
Definition: lisp_types.h:231
Definition: defs.h:47
negative_fwd_actions_e action
action for negative mappings
Definition: lisp_gpe.h:186
#define clib_fifo_add1(f, e)
Definition: fifo.h:192
unsigned short u16
Definition: types.h:57
lisp_key_type_t
Definition: lisp_types.h:25
l2input_main_t l2input_main
Definition: l2_input.c:87
#define gid_address_vni(_a)
Definition: lisp_types.h:235
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:644
static u32 lisp_get_vni_from_buffer_eth(lisp_cp_main_t *lcm, vlib_buffer_t *b)
Definition: control.c:3824
#define MNOTIFY_DATA(h_)
static vlib_buffer_t * build_map_register(lisp_cp_main_t *lcm, ip_address_t *sloc, ip_address_t *ms_ip, u64 *nonce_res, u8 want_map_notif, mapping_t *records, lisp_key_type_t key_id, u8 *key, u32 *bi_res)
Definition: control.c:3438
map_request_mode_t
Definition: control.h:90
static uword * get_locator_set_index(vnet_lisp_add_del_locator_set_args_t *a, uword *p)
Definition: control.c:2106
void locator_free(locator_t *l)
Definition: lisp_types.c:1534
static void remove_overlapping_sub_prefixes(lisp_cp_main_t *lcm, gid_address_t *eid, u8 is_negative)
This function searches map cache and looks for IP prefixes that are subset of the provided one...
Definition: control.c:1147
#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:3115
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:216
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
static void dp_del_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:260
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
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:2167
locator_pair_t * locator_pairs
vector of locator pairs
Definition: lisp_gpe.h:195
mapping_t * mapping_pool
Definition: control.h:106
static int get_egress_map_resolver_ip(lisp_cp_main_t *lcm, ip_address_t *ip)
Definition: control.c:3476
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:1982
u8 ip_address_max_len(u8 version)
Definition: lisp_types.c:491
uword * locator_set_index_by_name
Definition: control.h:121
static gid_address_t * build_itr_rloc_list(lisp_cp_main_t *lcm, locator_set_t *loc_set)
Definition: control.c:3186
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:1295
Definition: lisp_types.h:37
static vlib_buffer_t * build_map_request(lisp_cp_main_t *lcm, gid_address_t *deid, ip_address_t *sloc, ip_address_t *rloc, gid_address_t *itr_rlocs, u64 *nonce_res, u32 *bi_res)
Definition: control.c:3235
gid_address_t eid
Definition: lisp_types.h:306
gid_address_t reid
Definition: control.h:64
gid_address_t address
Definition: lisp_types.h:280
#define hash_get_mem(h, key)
Definition: hash.h:268
void mac_copy(void *dst, void *src)
Definition: lisp_types.c:915
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:3849
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:1882
#define MREG_DATA(h_)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
gid_address_t dst
Definition: control.h:45
static void map_records_arg_free(map_records_arg_t *a)
Definition: control.c:4142
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
int vnet_lisp_add_del_map_resolver(vnet_lisp_add_del_map_resolver_args_t *a)
Definition: control.c:2891
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1099
void process_map_request(vlib_main_t *vm, lisp_cp_main_t *lcm, vlib_buffer_t *b)
Definition: control.c:4466
ip_address_t rmt_loc
Definition: lisp_types.h:335
#define vec_foreach(var, vec)
Vector iterator.
uword * map_register_messages_by_nonce
Definition: control.h:143
static void free_map_register_records(mapping_t *maps)
Definition: control.c:3347
static void update_rloc_probing(lisp_cp_main_t *lcm, f64 dt)
Definition: control.c:4853
vhost_vring_addr_t addr
Definition: vhost-user.h:81
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:495
void * process_map_reply(map_records_arg_t *a)
Definition: control.c:4155
gid_address_t dst_eid
Definition: control.c:3137
#define clib_error_return(e, args...)
Definition: error.h:111
static int parse_map_records(vlib_buffer_t *b, map_records_arg_t *a, u8 count)
Definition: control.c:4309
u8 ip_version_and_header_length
Definition: ip4_packet.h:131
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:453
#define MREP_NONCE(h_)
mapping_t * mappings
Definition: control.c:41
#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:187
u32 flags
Definition: vhost-user.h:75
Definition: lisp_types.h:38
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static const EVP_MD * get_encrypt_fcn(lisp_key_type_t key_id)
Definition: control.c:72
void build_src_dst(gid_address_t *sd, gid_address_t *src, gid_address_t *dst)
Definition: lisp_types.c:1541
static uword lisp_cp_lookup_ip6(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:4001
gid_address_t lcl_eid
local eid
Definition: lisp_gpe.h:189
unformat_function_t unformat_line_input
Definition: format.h:281
static u8 * format_lisp_status(u8 *s, va_list *args)
Definition: control.c:2603
u32 mreq_itr_rlocs
Definition: control.h:160
u32 lisp_gpe_tenant_l3_iface_add_or_lock(u32 vni, u32 table_id)
Add/create and lock a new or find and lock the existing L3 interface for the tenant.
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
u32 * locator_indices
Definition: lisp_types.h:300
#define send_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:3642
vnet_main_t * vnet_main
Definition: control.h:195
#define MREP_RLOC_PROBE(h_)
static int is_auth_data_valid(map_notify_hdr_t *h, u32 msg_len, lisp_key_type_t key_id, u8 *key)
Definition: control.c:4209
uword key
Definition: hash.h:161
static mapping_t * build_map_register_record_list(lisp_cp_main_t *lcm)
Definition: control.c:3401
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:2688
LISP-GPE definitions.
u8 * format_lisp_cp_lookup_trace(u8 *s, va_list *args)
Definition: control.c:3142
ip4_main_t * im4
Definition: control.h:192
gid_address_t leid
Definition: control.h:55
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:1434
#define ip_prefix_addr(_a)
Definition: lisp_types.h:71
static clib_error_t * lisp_add_del_map_server_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: control.c:683
ip6_address_t dst_address
Definition: ip6_packet.h:337
#define resend_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:3645
#define PENDING_MREQ_EXPIRATION_TIME
Definition: control.h:24
locator_t * locators
Definition: lisp_types.h:312
lisp_cp_input_error_t
Definition: control.c:4082
static uword lisp_cp_lookup_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, int overlay)
Definition: control.c:3899
int ip_address_cmp(const ip_address_t *ip1, const ip_address_t *ip2)
Definition: lisp_types.c:733