FD.io VPP  v17.07.01-10-g3be13f0
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>
23 #include <vnet/fib/fib_entry.h>
24 #include <vnet/fib/fib_table.h>
26 #include <vnet/ethernet/packet.h>
27 
28 #include <openssl/evp.h>
29 #include <openssl/hmac.h>
30 
31 #define MAX_VALUE_U24 0xffffff
32 
34 
35 u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
36 
37 typedef enum
38 {
42 
43 typedef struct
44 {
50 
51 u8
53 {
55  return lcm->map_request_mode;
56 }
57 
58 static u16
60 {
61  switch (key_id)
62  {
63  case HMAC_SHA_1_96:
64  return SHA1_AUTH_DATA_LEN;
65  case HMAC_SHA_256_128:
66  return SHA256_AUTH_DATA_LEN;
67  default:
68  clib_warning ("unsupported key type: %d!", key_id);
69  return (u16) ~ 0;
70  }
71  return (u16) ~ 0;
72 }
73 
74 static const EVP_MD *
76 {
77  switch (key_id)
78  {
79  case HMAC_SHA_1_96:
80  return EVP_sha1 ();
81  case HMAC_SHA_256_128:
82  return EVP_sha256 ();
83  default:
84  clib_warning ("unsupported encryption key type: %d!", key_id);
85  break;
86  }
87  return 0;
88 }
89 
90 static int
92  u8 smr_invoked, u8 is_resend);
93 
96  u32 sw_if_index, u8 loop)
97 {
98  vnet_main_t *vnm = vnet_get_main ();
99  vnet_sw_interface_t *swif = vnet_get_sw_interface (vnm, sw_if_index);
100  if (loop && swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
101  sw_if_index = swif->unnumbered_sw_if_index;
102  u32 ia =
103  (vec_len ((lm)->if_address_pool_index_by_sw_if_index) > (sw_if_index)) ?
104  vec_elt ((lm)->if_address_pool_index_by_sw_if_index, (sw_if_index)) :
105  (u32) ~ 0;
106  return pool_elt_at_index ((lm)->if_address_pool, ia);
107 }
108 
109 void *
111  u8 version)
112 {
114 
115  ia = ip_interface_get_first_interface_address (lm, sw_if_index, 1);
116  if (!ia)
117  return 0;
118  return ip_interface_address_get_address (lm, ia);
119 }
120 
121 int
123  u8 version, ip_address_t * result)
124 {
125  ip_lookup_main_t *lm;
126  void *addr;
127 
128  lm = (version == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
129  addr = ip_interface_get_first_address (lm, sw_if_index, version);
130  if (!addr)
131  return 0;
132 
133  ip_address_set (result, addr, version);
134  return 1;
135 }
136 
137 /**
138  * convert from a LISP address to a FIB prefix
139  */
140 void
141 ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
142 {
143  if (addr->version == IP4)
144  {
145  prefix->fp_len = 32;
146  prefix->fp_proto = FIB_PROTOCOL_IP4;
147  memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
148  memcpy (&prefix->fp_addr.ip4, &addr->ip, sizeof (prefix->fp_addr.ip4));
149  }
150  else
151  {
152  prefix->fp_len = 128;
153  prefix->fp_proto = FIB_PROTOCOL_IP6;
154  memcpy (&prefix->fp_addr.ip6, &addr->ip, sizeof (prefix->fp_addr.ip6));
155  }
156 }
157 
158 /**
159  * convert from a LISP to a FIB prefix
160  */
161 void
162 ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
163  fib_prefix_t * fib_prefix)
164 {
165  ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
166  fib_prefix->fp_len = ip_prefix->len;
167 }
168 
169 /**
170  * Find the sw_if_index of the interface that would be used to egress towards
171  * dst.
172  */
173 u32
175 {
176  fib_node_index_t fei;
177  fib_prefix_t prefix;
178 
179  ip_address_to_fib_prefix (dst, &prefix);
180 
181  fei = fib_table_lookup (0, &prefix);
182 
183  return (fib_entry_get_resolving_interface (fei));
184 }
185 
186 /**
187  * Find first IP of the interface that would be used to egress towards dst.
188  * Returns 1 if the address is found 0 otherwise.
189  */
190 int
192  ip_address_t * result)
193 {
194  u32 si;
195  ip_lookup_main_t *lm;
196  void *addr = 0;
197  u8 ipver;
198 
199  ASSERT (result != 0);
200 
201  ipver = ip_addr_version (dst);
202 
203  lm = (ipver == IP4) ? &lcm->im4->lookup_main : &lcm->im6->lookup_main;
204  si = ip_fib_get_egress_iface_for_dst (lcm, dst);
205 
206  if ((u32) ~ 0 == si)
207  return 0;
208 
209  /* find the first ip address */
210  addr = ip_interface_get_first_address (lm, si, ipver);
211  if (0 == addr)
212  return 0;
213 
214  ip_address_set (result, addr, ipver);
215  return 1;
216 }
217 
218 static int
219 dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add)
220 {
221  uword *dp_table;
222 
223  if (!is_l2)
224  {
225  dp_table = hash_get (lcm->table_id_by_vni, vni);
226 
227  if (!dp_table)
228  {
229  clib_warning ("vni %d not associated to a vrf!", vni);
230  return VNET_API_ERROR_INVALID_VALUE;
231  }
232  }
233  else
234  {
235  dp_table = hash_get (lcm->bd_id_by_vni, vni);
236  if (!dp_table)
237  {
238  clib_warning ("vni %d not associated to a bridge domain!", vni);
239  return VNET_API_ERROR_INVALID_VALUE;
240  }
241  }
242 
243  /* enable/disable data-plane interface */
244  if (is_add)
245  {
246  if (is_l2)
247  lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table[0]);
248  else
249  lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0]);
250  }
251  else
252  {
253  if (is_l2)
255  else
257  }
258 
259  return 0;
260 }
261 
262 static void
263 dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
264 {
266  fwd_entry_t *fe = 0;
267  uword *feip = 0;
268  memset (a, 0, sizeof (*a));
269 
270  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
271  if (!feip)
272  return;
273 
274  fe = pool_elt_at_index (lcm->fwd_entry_pool, feip[0]);
275 
276  /* delete dp fwd entry */
277  u32 sw_if_index;
278  a->is_add = 0;
279  a->locator_pairs = fe->locator_pairs;
280  a->vni = gid_address_vni (&fe->reid);
281  gid_address_copy (&a->rmt_eid, &fe->reid);
282  if (fe->is_src_dst)
283  gid_address_copy (&a->lcl_eid, &fe->leid);
284 
285  vnet_lisp_gpe_del_fwd_counters (a, feip[0]);
286  vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
287 
288  /* delete entry in fwd table */
289  hash_unset (lcm->fwd_entry_by_mapping_index, dst_map_index);
290  vec_free (fe->locator_pairs);
291  pool_put (lcm->fwd_entry_pool, fe);
292 }
293 
294 /**
295  * Finds first remote locator with best (lowest) priority that has a local
296  * peer locator with an underlying route to it.
297  *
298  */
299 static u32
301  mapping_t * rmt_map, locator_pair_t ** locator_pairs)
302 {
303  u32 i, limitp = 0, li, found = 0, esi;
304  locator_set_t *rmt_ls, *lcl_ls;
305  ip_address_t _lcl_addr, *lcl_addr = &_lcl_addr;
306  locator_t *lp, *rmt = 0;
307  uword *checked = 0;
308  locator_pair_t pair;
309 
310  rmt_ls =
312  lcl_ls =
314 
315  if (!rmt_ls || vec_len (rmt_ls->locator_indices) == 0)
316  return 0;
317 
318  while (1)
319  {
320  rmt = 0;
321 
322  /* find unvisited remote locator with best priority */
323  for (i = 0; i < vec_len (rmt_ls->locator_indices); i++)
324  {
325  if (0 != hash_get (checked, i))
326  continue;
327 
328  li = vec_elt (rmt_ls->locator_indices, i);
329  lp = pool_elt_at_index (lcm->locator_pool, li);
330 
331  /* we don't support non-IP locators for now */
333  continue;
334 
335  if ((found && lp->priority == limitp)
336  || (!found && lp->priority >= limitp))
337  {
338  rmt = lp;
339 
340  /* don't search for locators with lower priority and don't
341  * check this locator again*/
342  limitp = lp->priority;
343  hash_set (checked, i, 1);
344  break;
345  }
346  }
347  /* check if a local locator with a route to remote locator exists */
348  if (rmt != 0)
349  {
350  /* find egress sw_if_index for rmt locator */
351  esi =
353  &gid_address_ip (&rmt->address));
354  if ((u32) ~ 0 == esi)
355  continue;
356 
357  for (i = 0; i < vec_len (lcl_ls->locator_indices); i++)
358  {
359  li = vec_elt (lcl_ls->locator_indices, i);
360  locator_t *sl = pool_elt_at_index (lcm->locator_pool, li);
361 
362  /* found local locator with the needed sw_if_index */
363  if (sl->sw_if_index == esi)
364  {
365  /* and it has an address */
366  if (0 == ip_interface_get_first_ip_address (lcm,
367  sl->sw_if_index,
369  (&rmt->address),
370  lcl_addr))
371  continue;
372 
373  memset (&pair, 0, sizeof (pair));
374  ip_address_copy (&pair.rmt_loc,
375  &gid_address_ip (&rmt->address));
376  ip_address_copy (&pair.lcl_loc, lcl_addr);
377  pair.weight = rmt->weight;
378  pair.priority = rmt->priority;
379  vec_add1 (locator_pairs[0], pair);
380  found = 1;
381  }
382  }
383  }
384  else
385  break;
386  }
387 
388  hash_free (checked);
389  return found;
390 }
391 
392 static void
394  fid_address_t * fid)
395 {
397 
398  dst[0] = src[0];
399 
400  switch (fid_addr_type (fid))
401  {
402  case FID_ADDR_IP_PREF:
404  gid_address_ippref (dst) = fid_addr_ippref (fid);
405  break;
406  case FID_ADDR_MAC:
408  mac_copy (gid_address_mac (dst), fid_addr_mac (fid));
409  break;
410  default:
411  clib_warning ("Unsupported fid type %d!", fid_addr_type (fid));
412  break;
413  }
414 }
415 
416 u8
418 {
420  return lcm->map_registering;
421 }
422 
423 u8
425 {
427  return lcm->rloc_probing;
428 }
429 
430 static void
431 dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
432 {
434  gid_address_t *rmt_eid, *lcl_eid;
435  mapping_t *lcl_map, *rmt_map;
436  u32 sw_if_index;
437  uword *feip = 0, *dpid;
438  fwd_entry_t *fe;
439  u8 type, is_src_dst = 0;
440  int rv;
441 
442  memset (a, 0, sizeof (*a));
443 
444  /* remove entry if it already exists */
445  feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
446  if (feip)
447  dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
448 
449  /*
450  * Determine local mapping and eid
451  */
452  if (lcm->lisp_pitr)
453  lcl_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
454  else
455  lcl_map = pool_elt_at_index (lcm->mapping_pool, src_map_index);
456  lcl_eid = &lcl_map->eid;
457 
458  /*
459  * Determine remote mapping and eid
460  */
461  rmt_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index);
462  rmt_eid = &rmt_map->eid;
463 
464  /*
465  * Build and insert data plane forwarding entry
466  */
467  a->is_add = 1;
468 
469  if (MR_MODE_SRC_DST == lcm->map_request_mode)
470  {
471  if (GID_ADDR_SRC_DST == gid_address_type (rmt_eid))
472  {
473  gid_address_sd_to_flat (&a->rmt_eid, rmt_eid,
474  &gid_address_sd_dst (rmt_eid));
475  gid_address_sd_to_flat (&a->lcl_eid, rmt_eid,
476  &gid_address_sd_src (rmt_eid));
477  }
478  else
479  {
480  gid_address_copy (&a->rmt_eid, rmt_eid);
481  gid_address_copy (&a->lcl_eid, lcl_eid);
482  }
483  is_src_dst = 1;
484  }
485  else
486  gid_address_copy (&a->rmt_eid, rmt_eid);
487 
488  a->vni = gid_address_vni (&a->rmt_eid);
489  a->is_src_dst = is_src_dst;
490 
491  /* get vrf or bd_index associated to vni */
492  type = gid_address_type (&a->rmt_eid);
493  if (GID_ADDR_IP_PREFIX == type)
494  {
495  dpid = hash_get (lcm->table_id_by_vni, a->vni);
496  if (!dpid)
497  {
498  clib_warning ("vni %d not associated to a vrf!", a->vni);
499  return;
500  }
501  a->table_id = dpid[0];
502  }
503  else if (GID_ADDR_MAC == type)
504  {
505  dpid = hash_get (lcm->bd_id_by_vni, a->vni);
506  if (!dpid)
507  {
508  clib_warning ("vni %d not associated to a bridge domain !", a->vni);
509  return;
510  }
511  a->bd_id = dpid[0];
512  }
513 
514  /* find best locator pair that 1) verifies LISP policy 2) are connected */
515  rv = get_locator_pairs (lcm, lcl_map, rmt_map, &a->locator_pairs);
516 
517  /* Either rmt mapping is negative or we can't find underlay path.
518  * Try again with petr if configured */
519  if (rv == 0 && (lcm->flags & LISP_FLAG_USE_PETR))
520  {
521  rmt_map = lisp_get_petr_mapping (lcm);
522  rv = get_locator_pairs (lcm, lcl_map, rmt_map, &a->locator_pairs);
523  }
524 
525  /* negative entry */
526  if (rv == 0)
527  {
528  a->is_negative = 1;
529  a->action = rmt_map->action;
530  }
531 
532  rv = vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
533  if (rv)
534  {
535  if (a->locator_pairs)
536  vec_free (a->locator_pairs);
537  return;
538  }
539 
540  /* add tunnel to fwd entry table */
541  pool_get (lcm->fwd_entry_pool, fe);
543 
544  fe->locator_pairs = a->locator_pairs;
545  gid_address_copy (&fe->reid, &a->rmt_eid);
546 
547  if (is_src_dst)
548  gid_address_copy (&fe->leid, &a->lcl_eid);
549  else
550  gid_address_copy (&fe->leid, lcl_eid);
551 
552  fe->is_src_dst = is_src_dst;
553  hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
554  fe - lcm->fwd_entry_pool);
555 }
556 
557 typedef struct
558 {
562 
563 static void *
565 {
566  fwd_entry_mt_arg_t *a = arg;
568  dp_add_fwd_entry (lcm, a->si, a->di);
569  return 0;
570 }
571 
572 static int
574 {
576 
577  memset (&a, 0, sizeof (a));
578  a.si = si;
579  a.di = di;
580 
582  (u8 *) & a, sizeof (a));
583  return 0;
584 }
585 
586 /**
587  * Returns vector of adjacencies.
588  *
589  * The caller must free the vector returned by this function.
590  *
591  * @param vni virtual network identifier
592  * @return vector of adjacencies
593  */
596 {
598  fwd_entry_t *fwd;
599  lisp_adjacency_t *adjs = 0, adj;
600 
601  /* *INDENT-OFF* */
602  pool_foreach(fwd, lcm->fwd_entry_pool,
603  ({
604  if (gid_address_vni (&fwd->reid) != vni)
605  continue;
606 
607  gid_address_copy (&adj.reid, &fwd->reid);
608  gid_address_copy (&adj.leid, &fwd->leid);
609  vec_add1 (adjs, adj);
610  }));
611  /* *INDENT-ON* */
612 
613  return adjs;
614 }
615 
616 static lisp_msmr_t *
617 get_map_server (ip_address_t * a)
618 {
620  lisp_msmr_t *m;
621 
622  vec_foreach (m, lcm->map_servers)
623  {
624  if (!ip_address_cmp (&m->address, a))
625  {
626  return m;
627  }
628  }
629  return 0;
630 }
631 
632 static lisp_msmr_t *
633 get_map_resolver (ip_address_t * a)
634 {
636  lisp_msmr_t *m;
637 
638  vec_foreach (m, lcm->map_resolvers)
639  {
640  if (!ip_address_cmp (&m->address, a))
641  {
642  return m;
643  }
644  }
645  return 0;
646 }
647 
648 int
649 vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add)
650 {
651  u32 i;
653  lisp_msmr_t _ms, *ms = &_ms;
654 
656  {
657  clib_warning ("LISP is disabled!");
658  return VNET_API_ERROR_LISP_DISABLED;
659  }
660 
661  if (is_add)
662  {
663  if (get_map_server (addr))
664  {
665  clib_warning ("map-server %U already exists!", format_ip_address,
666  addr);
667  return -1;
668  }
669 
670  memset (ms, 0, sizeof (*ms));
671  ip_address_copy (&ms->address, addr);
672  vec_add1 (lcm->map_servers, ms[0]);
673  }
674  else
675  {
676  for (i = 0; i < vec_len (lcm->map_servers); i++)
677  {
678  ms = vec_elt_at_index (lcm->map_servers, i);
679  if (!ip_address_cmp (&ms->address, addr))
680  {
681  vec_del1 (lcm->map_servers, i);
682  break;
683  }
684  }
685  }
686 
687  return 0;
688 }
689 
690 /**
691  * Add/remove mapping to/from map-cache. Overwriting not allowed.
692  */
693 int
695  u32 * map_index_result)
696 {
698  u32 mi, *map_indexp, map_index, i;
699  mapping_t *m, *old_map;
700  u32 **eid_indexes;
701 
702  if (gid_address_type (&a->eid) == GID_ADDR_NSH)
703  {
704  if (gid_address_vni (&a->eid) != 0)
705  {
706  clib_warning ("Supported only default VNI for NSH!");
707  return VNET_API_ERROR_INVALID_ARGUMENT;
708  }
710  {
711  clib_warning ("SPI is greater than 24bit!");
712  return VNET_API_ERROR_INVALID_ARGUMENT;
713  }
714  }
715 
717  old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
718  if (a->is_add)
719  {
720  /* TODO check if overwriting and take appropriate actions */
721  if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid, &a->eid))
722  {
723  clib_warning ("eid %U found in the eid-table", format_gid_address,
724  &a->eid);
725  return VNET_API_ERROR_VALUE_EXIST;
726  }
727 
728  pool_get (lcm->mapping_pool, m);
729  gid_address_copy (&m->eid, &a->eid);
731  m->ttl = a->ttl;
732  m->action = a->action;
733  m->local = a->local;
734  m->is_static = a->is_static;
735  m->key = vec_dup (a->key);
736  m->key_id = a->key_id;
737 
738  map_index = m - lcm->mapping_pool;
739  gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, map_index,
740  1);
741 
743  {
744  clib_warning ("Locator set with index %d doesn't exist",
745  a->locator_set_index);
746  return VNET_API_ERROR_INVALID_VALUE;
747  }
748 
749  /* add eid to list of eids supported by locator-set */
751  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
752  a->locator_set_index);
753  vec_add1 (eid_indexes[0], map_index);
754 
755  if (a->local)
756  {
757  /* mark as local */
758  vec_add1 (lcm->local_mappings_indexes, map_index);
759  }
760  map_index_result[0] = map_index;
761  }
762  else
763  {
764  if (mi == GID_LOOKUP_MISS)
765  {
766  clib_warning ("eid %U not found in the eid-table",
767  format_gid_address, &a->eid);
768  return VNET_API_ERROR_INVALID_VALUE;
769  }
770 
771  /* clear locator-set to eids binding */
772  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids,
773  a->locator_set_index);
774  for (i = 0; i < vec_len (eid_indexes[0]); i++)
775  {
776  map_indexp = vec_elt_at_index (eid_indexes[0], i);
777  if (map_indexp[0] == mi)
778  break;
779  }
780  vec_del1 (eid_indexes[0], i);
781 
782  /* remove local mark if needed */
783  m = pool_elt_at_index (lcm->mapping_pool, mi);
784  if (m->local)
785  {
786  u32 k, *lm_indexp;
787  for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
788  {
789  lm_indexp = vec_elt_at_index (lcm->local_mappings_indexes, k);
790  if (lm_indexp[0] == mi)
791  break;
792  }
794  }
795 
796  /* remove mapping from dictionary */
798  gid_address_free (&m->eid);
799  pool_put_index (lcm->mapping_pool, mi);
800  }
801 
802  return 0;
803 }
804 
805 /**
806  * Add/update/delete mapping to/in/from map-cache.
807  */
808 int
810  u32 * map_index_result)
811 {
812  uword *dp_table = 0;
813  u32 vni;
814  u8 type;
815 
817 
819  {
820  clib_warning ("LISP is disabled!");
821  return VNET_API_ERROR_LISP_DISABLED;
822  }
823 
824  vni = gid_address_vni (&a->eid);
825  type = gid_address_type (&a->eid);
826  if (GID_ADDR_IP_PREFIX == type)
827  dp_table = hash_get (lcm->table_id_by_vni, vni);
828  else if (GID_ADDR_MAC == type)
829  dp_table = hash_get (lcm->bd_id_by_vni, vni);
830 
831  if (!dp_table && GID_ADDR_NSH != type)
832  {
833  clib_warning ("vni %d not associated to a %s!", vni,
834  GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
835  return VNET_API_ERROR_INVALID_VALUE;
836  }
837 
838  /* store/remove mapping from map-cache */
839  return vnet_lisp_map_cache_add_del (a, map_index_result);
840 }
841 
842 static void
843 add_l2_arp_bd (BVT (clib_bihash_kv) * kvp, void *arg)
844 {
845  u32 **ht = arg;
846  u32 bd = (u32) kvp->key[0];
847  hash_set (ht[0], bd, 0);
848 }
849 
850 u32 *
852 {
854  u32 *bds = 0;
855 
857  add_l2_arp_bd, &bds);
858  return bds;
859 }
860 
861 typedef struct
862 {
863  void *vector;
866 
867 static void
868 add_l2_arp_entry (BVT (clib_bihash_kv) * kvp, void *arg)
869 {
870  lisp_add_l2_arp_args_t *a = arg;
871  lisp_api_l2_arp_entry_t **vector = a->vector, e;
872 
873  if ((u32) kvp->key[0] == a->bd)
874  {
875  mac_copy (e.mac, (void *) &kvp->value);
876  e.ip4 = (u32) kvp->key[1];
877  vec_add1 (vector[0], e);
878  }
879 }
880 
883 {
884  lisp_api_l2_arp_entry_t *entries = 0;
887 
888  a.vector = &entries;
889  a.bd = bd;
890 
892  add_l2_arp_entry, &a);
893  return entries;
894 }
895 
896 int
898 {
900  {
901  clib_warning ("LISP is disabled!");
902  return VNET_API_ERROR_LISP_DISABLED;
903  }
904 
906  int rc = 0;
907 
909  if (is_add)
910  {
911  if (res != GID_LOOKUP_MISS_L2)
912  {
913  clib_warning ("Entry %U exists in DB!", format_gid_address, key);
914  return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
915  }
916  u64 val = mac_to_u64 (mac);
918  1 /* is_add */ );
919  }
920  else
921  {
922  if (res == GID_LOOKUP_MISS_L2)
923  {
924  clib_warning ("ONE ARP entry %U not found - cannot delete!",
925  format_gid_address, key);
926  return -1;
927  }
929  0 /* is_add */ );
930  }
931 
932  return rc;
933 }
934 
935 int
936 vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
937 {
939  uword *dp_idp, *vnip, **dp_table_by_vni, **vni_by_dp_table;
940 
942  {
943  clib_warning ("LISP is disabled!");
944  return VNET_API_ERROR_LISP_DISABLED;
945  }
946 
947  dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
948  vni_by_dp_table = is_l2 ? &lcm->vni_by_bd_id : &lcm->vni_by_table_id;
949 
950  if (!is_l2 && (vni == 0 || dp_id == 0))
951  {
952  clib_warning ("can't add/del default vni-vrf mapping!");
953  return -1;
954  }
955 
956  dp_idp = hash_get (dp_table_by_vni[0], vni);
957  vnip = hash_get (vni_by_dp_table[0], dp_id);
958 
959  if (is_add)
960  {
961  if (dp_idp || vnip)
962  {
963  clib_warning ("vni %d or vrf %d already used in vrf/vni "
964  "mapping!", vni, dp_id);
965  return -1;
966  }
967  hash_set (dp_table_by_vni[0], vni, dp_id);
968  hash_set (vni_by_dp_table[0], dp_id, vni);
969 
970  /* create dp iface */
971  dp_add_del_iface (lcm, vni, is_l2, 1);
972  }
973  else
974  {
975  if (!dp_idp || !vnip)
976  {
977  clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
978  "mapping!", vni, dp_id);
979  return -1;
980  }
981  /* remove dp iface */
982  dp_add_del_iface (lcm, vni, is_l2, 0);
983 
984  hash_unset (dp_table_by_vni[0], vni);
985  hash_unset (vni_by_dp_table[0], dp_id);
986  }
987  return 0;
988 
989 }
990 
991 /* return 0 if the two locator sets are identical 1 otherwise */
992 static u8
993 compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes,
994  locator_t * new_locators)
995 {
996  u32 i, old_li;
997  locator_t *old_loc, *new_loc;
998 
999  if (vec_len (old_ls_indexes) != vec_len (new_locators))
1000  return 1;
1001 
1002  for (i = 0; i < vec_len (new_locators); i++)
1003  {
1004  old_li = vec_elt (old_ls_indexes, i);
1005  old_loc = pool_elt_at_index (lcm->locator_pool, old_li);
1006 
1007  new_loc = vec_elt_at_index (new_locators, i);
1008 
1009  if (locator_cmp (old_loc, new_loc))
1010  return 1;
1011  }
1012  return 0;
1013 }
1014 
1015 typedef struct
1016 {
1018  void *lcm;
1021 
1022 /**
1023  * Callback invoked when a sub-prefix is found
1024  */
1025 static void
1027 {
1028  u8 delete = 0;
1029  remove_mapping_args_t *a = arg;
1030  lisp_cp_main_t *lcm = a->lcm;
1031  mapping_t *m;
1032  locator_set_t *ls;
1033 
1034  m = pool_elt_at_index (lcm->mapping_pool, mi);
1035  if (!m)
1036  return;
1037 
1039 
1040  if (a->is_negative)
1041  {
1042  if (0 != vec_len (ls->locator_indices))
1043  delete = 1;
1044  }
1045  else
1046  {
1047  if (0 == vec_len (ls->locator_indices))
1048  delete = 1;
1049  }
1050 
1051  if (delete)
1052  vec_add1 (a->eids_to_be_deleted, m->eid);
1053 }
1054 
1055 /**
1056  * This function searches map cache and looks for IP prefixes that are subset
1057  * of the provided one. If such prefix is found depending on 'is_negative'
1058  * it does follows:
1059  *
1060  * 1) if is_negative is true and found prefix points to positive mapping,
1061  * then the mapping is removed
1062  * 2) if is_negative is false and found prefix points to negative mapping,
1063  * then the mapping is removed
1064  */
1065 static void
1067  u8 is_negative)
1068 {
1069  gid_address_t *e;
1071 
1072  memset (&a, 0, sizeof (a));
1073 
1074  /* do this only in src/dst mode ... */
1075  if (MR_MODE_SRC_DST != lcm->map_request_mode)
1076  return;
1077 
1078  /* ... and only for IP prefix */
1079  if (GID_ADDR_SRC_DST != gid_address_type (eid)
1081  return;
1082 
1083  a.is_negative = is_negative;
1084  a.lcm = lcm;
1085 
1088 
1090  {
1091  vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args;
1092 
1093  memset (adj_args, 0, sizeof (adj_args[0]));
1094  gid_address_copy (&adj_args->reid, e);
1095  adj_args->is_add = 0;
1096  if (vnet_lisp_add_del_adjacency (adj_args))
1097  clib_warning ("failed to del adjacency!");
1098 
1099  vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0);
1100  }
1101 
1103 }
1104 
1105 static void
1107 {
1108  timing_wheel_delete (&lcm->wheel, mi);
1109 }
1110 
1111 static int
1112 is_local_ip (lisp_cp_main_t * lcm, ip_address_t * addr)
1113 {
1114  fib_node_index_t fei;
1115  fib_prefix_t prefix;
1117 
1118  ip_address_to_fib_prefix (addr, &prefix);
1119 
1120  fei = fib_table_lookup (0, &prefix);
1121  flags = fib_entry_get_flags (fei);
1122  return (FIB_ENTRY_FLAG_LOCAL & flags);
1123 }
1124 
1125 /**
1126  * Adds/removes/updates mapping. Does not program forwarding.
1127  *
1128  * @param eid end-host identifier
1129  * @param rlocs vector of remote locators
1130  * @param action action for negative map-reply
1131  * @param is_add add mapping if non-zero, delete otherwise
1132  * @param res_map_index the map-index that was created/updated/removed. It is
1133  * set to ~0 if no action is taken.
1134  * @param is_static used for distinguishing between statically learned
1135  remote mappings and mappings obtained from MR
1136  * @return return code
1137  */
1138 int
1140  u8 authoritative, u32 ttl, u8 is_add, u8 is_static,
1141  u32 * res_map_index)
1142 {
1143  vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args;
1144  vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
1146  u32 mi, ls_index = 0, dst_map_index;
1147  mapping_t *old_map;
1148  locator_t *loc;
1149 
1150  if (vnet_lisp_enable_disable_status () == 0)
1151  {
1152  clib_warning ("LISP is disabled!");
1153  return VNET_API_ERROR_LISP_DISABLED;
1154  }
1155 
1156  if (res_map_index)
1157  res_map_index[0] = ~0;
1158 
1159  memset (m_args, 0, sizeof (m_args[0]));
1160  memset (ls_args, 0, sizeof (ls_args[0]));
1161 
1162  ls_args->locators = rlocs;
1163 
1164  mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
1165  old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
1166 
1167  if (is_add)
1168  {
1169  /* check if none of the locators match localy configured address */
1170  vec_foreach (loc, rlocs)
1171  {
1172  ip_prefix_t *p = &gid_address_ippref (&loc->address);
1173  if (is_local_ip (lcm, &ip_prefix_addr (p)))
1174  {
1175  clib_warning ("RLOC %U matches a local address!",
1176  format_gid_address, &loc->address);
1177  return VNET_API_ERROR_LISP_RLOC_LOCAL;
1178  }
1179  }
1180 
1181  /* overwrite: if mapping already exists, decide if locators should be
1182  * updated and be done */
1183  if (old_map && gid_address_cmp (&old_map->eid, eid) == 0)
1184  {
1185  if (!is_static && (old_map->is_static || old_map->local))
1186  {
1187  /* do not overwrite local or static remote mappings */
1188  clib_warning ("mapping %U rejected due to collision with local "
1189  "or static remote mapping!", format_gid_address,
1190  eid);
1191  return 0;
1192  }
1193 
1194  locator_set_t *old_ls;
1195 
1196  /* update mapping attributes */
1197  old_map->action = action;
1198  old_map->authoritative = authoritative;
1199  old_map->ttl = ttl;
1200 
1201  old_ls = pool_elt_at_index (lcm->locator_set_pool,
1202  old_map->locator_set_index);
1203  if (compare_locators (lcm, old_ls->locator_indices,
1204  ls_args->locators))
1205  {
1206  /* set locator-set index to overwrite */
1207  ls_args->is_add = 1;
1208  ls_args->index = old_map->locator_set_index;
1209  vnet_lisp_add_del_locator_set (ls_args, 0);
1210  if (res_map_index)
1211  res_map_index[0] = mi;
1212  }
1213  }
1214  /* new mapping */
1215  else
1216  {
1217  remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators);
1218 
1219  ls_args->is_add = 1;
1220  ls_args->index = ~0;
1221 
1222  vnet_lisp_add_del_locator_set (ls_args, &ls_index);
1223 
1224  /* add mapping */
1225  gid_address_copy (&m_args->eid, eid);
1226  m_args->is_add = 1;
1227  m_args->action = action;
1228  m_args->locator_set_index = ls_index;
1229  m_args->is_static = is_static;
1230  m_args->ttl = ttl;
1231  vnet_lisp_map_cache_add_del (m_args, &dst_map_index);
1232 
1233  if (res_map_index)
1234  res_map_index[0] = dst_map_index;
1235  }
1236  }
1237  else
1238  {
1239  if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0)
1240  {
1241  clib_warning ("cannot delete mapping for eid %U",
1242  format_gid_address, eid);
1243  return -1;
1244  }
1245 
1246  m_args->is_add = 0;
1247  gid_address_copy (&m_args->eid, eid);
1248  m_args->locator_set_index = old_map->locator_set_index;
1249 
1250  /* delete mapping associated from map-cache */
1251  vnet_lisp_map_cache_add_del (m_args, 0);
1252 
1253  ls_args->is_add = 0;
1254  ls_args->index = old_map->locator_set_index;
1255  /* delete locator set */
1256  vnet_lisp_add_del_locator_set (ls_args, 0);
1257 
1258  /* delete timer associated to the mapping if any */
1259  if (old_map->timer_set)
1260  mapping_delete_timer (lcm, mi);
1261 
1262  /* return old mapping index */
1263  if (res_map_index)
1264  res_map_index[0] = mi;
1265  }
1266 
1267  /* success */
1268  return 0;
1269 }
1270 
1271 int
1273 {
1274  int rv = 0;
1275  u32 mi, *map_indices = 0, *map_indexp;
1277  vnet_lisp_add_del_mapping_args_t _dm_args, *dm_args = &_dm_args;
1278  vnet_lisp_add_del_locator_set_args_t _ls, *ls = &_ls;
1279 
1280  /* *INDENT-OFF* */
1281  pool_foreach_index (mi, lcm->mapping_pool,
1282  ({
1283  vec_add1 (map_indices, mi);
1284  }));
1285  /* *INDENT-ON* */
1286 
1287  vec_foreach (map_indexp, map_indices)
1288  {
1289  mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
1290  if (!map->local)
1291  {
1292  dp_del_fwd_entry (lcm, 0, map_indexp[0]);
1293 
1294  dm_args->is_add = 0;
1295  gid_address_copy (&dm_args->eid, &map->eid);
1296  dm_args->locator_set_index = map->locator_set_index;
1297 
1298  /* delete mapping associated to fwd entry */
1299  vnet_lisp_map_cache_add_del (dm_args, 0);
1300 
1301  ls->is_add = 0;
1302  ls->local = 0;
1303  ls->index = map->locator_set_index;
1304  /* delete locator set */
1305  rv = vnet_lisp_add_del_locator_set (ls, 0);
1306  if (rv != 0)
1307  goto cleanup;
1308  }
1309  }
1310 
1311 cleanup:
1312  if (map_indices)
1313  vec_free (map_indices);
1314  return rv;
1315 }
1316 
1317 /**
1318  * Adds adjacency or removes forwarding entry associated to remote mapping.
1319  * Note that adjacencies are not stored, they only result in forwarding entries
1320  * being created.
1321  */
1322 int
1324 {
1326  u32 local_mi, remote_mi = ~0;
1327 
1328  if (vnet_lisp_enable_disable_status () == 0)
1329  {
1330  clib_warning ("LISP is disabled!");
1331  return VNET_API_ERROR_LISP_DISABLED;
1332  }
1333 
1335  &a->reid, &a->leid);
1336  if (GID_LOOKUP_MISS == remote_mi)
1337  {
1338  clib_warning ("Remote eid %U not found. Cannot add adjacency!",
1339  format_gid_address, &a->reid);
1340 
1341  return -1;
1342  }
1343 
1344  if (a->is_add)
1345  {
1346  /* check if source eid has an associated mapping. If pitr mode is on,
1347  * just use the pitr's mapping */
1348  if (lcm->lisp_pitr)
1349  local_mi = lcm->pitr_map_index;
1350  else
1351  {
1352  if (gid_address_type (&a->reid) == GID_ADDR_NSH)
1353  {
1354  if (lcm->nsh_map_index == ~0)
1355  local_mi = GID_LOOKUP_MISS;
1356  else
1357  local_mi = lcm->nsh_map_index;
1358  }
1359  else
1360  {
1361  local_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
1362  &a->leid);
1363  }
1364  }
1365 
1366  if (GID_LOOKUP_MISS == local_mi)
1367  {
1368  clib_warning ("Local eid %U not found. Cannot add adjacency!",
1369  format_gid_address, &a->leid);
1370 
1371  return -1;
1372  }
1373 
1374  /* update forwarding */
1375  dp_add_fwd_entry (lcm, local_mi, remote_mi);
1376  }
1377  else
1378  dp_del_fwd_entry (lcm, 0, remote_mi);
1379 
1380  return 0;
1381 }
1382 
1383 int
1385 {
1387 
1388  if (vnet_lisp_enable_disable_status () == 0)
1389  {
1390  clib_warning ("LISP is disabled!");
1391  return VNET_API_ERROR_LISP_DISABLED;
1392  }
1393 
1394  if (mode >= _MR_MODE_MAX)
1395  {
1396  clib_warning ("Invalid LISP map request mode %d!", mode);
1397  return VNET_API_ERROR_INVALID_ARGUMENT;
1398  }
1399 
1400  lcm->map_request_mode = mode;
1401  return 0;
1402 }
1403 
1404 int
1405 vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add)
1406 {
1409  u32 locator_set_index = ~0;
1410  mapping_t *m;
1411  uword *p;
1412 
1413  if (vnet_lisp_enable_disable_status () == 0)
1414  {
1415  clib_warning ("LISP is disabled!");
1416  return VNET_API_ERROR_LISP_DISABLED;
1417  }
1418 
1419  if (is_add)
1420  {
1421  if (lcm->nsh_map_index == (u32) ~ 0)
1422  {
1423  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1424  if (!p)
1425  {
1426  clib_warning ("locator-set %v doesn't exist", locator_set_name);
1427  return -1;
1428  }
1429  locator_set_index = p[0];
1430 
1431  pool_get (lcm->mapping_pool, m);
1432  memset (m, 0, sizeof *m);
1433  m->locator_set_index = locator_set_index;
1434  m->local = 1;
1435  m->nsh_set = 1;
1436  lcm->nsh_map_index = m - lcm->mapping_pool;
1437 
1438  if (~0 == vnet_lisp_gpe_add_nsh_iface (lgm))
1439  return -1;
1440  }
1441  }
1442  else
1443  {
1444  if (lcm->nsh_map_index != (u32) ~ 0)
1445  {
1446  /* remove NSH mapping */
1448  lcm->nsh_map_index = ~0;
1450  }
1451  }
1452  return 0;
1453 }
1454 
1455 int
1456 vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
1457 {
1459  u32 locator_set_index = ~0;
1460  mapping_t *m;
1461  uword *p;
1462 
1463  if (vnet_lisp_enable_disable_status () == 0)
1464  {
1465  clib_warning ("LISP is disabled!");
1466  return VNET_API_ERROR_LISP_DISABLED;
1467  }
1468 
1469  p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
1470  if (!p)
1471  {
1472  clib_warning ("locator-set %v doesn't exist", locator_set_name);
1473  return -1;
1474  }
1475  locator_set_index = p[0];
1476 
1477  if (is_add)
1478  {
1479  pool_get (lcm->mapping_pool, m);
1480  m->locator_set_index = locator_set_index;
1481  m->local = 1;
1482  m->pitr_set = 1;
1483  lcm->pitr_map_index = m - lcm->mapping_pool;
1484 
1485  /* enable pitr mode */
1486  lcm->lisp_pitr = 1;
1487  }
1488  else
1489  {
1490  /* remove pitr mapping */
1492 
1493  /* disable pitr mode */
1494  lcm->lisp_pitr = 0;
1495  }
1496  return 0;
1497 }
1498 
1499 /**
1500  * Configure Proxy-ETR
1501  *
1502  * @param ip PETR's IP address
1503  * @param is_add Flag that indicates if this is an addition or removal
1504  *
1505  * return 0 on success
1506  */
1507 int
1508 vnet_lisp_use_petr (ip_address_t * ip, u8 is_add)
1509 {
1511  u32 ls_index = ~0;
1512  mapping_t *m;
1513  vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args;
1514  locator_t loc;
1515 
1516  if (vnet_lisp_enable_disable_status () == 0)
1517  {
1518  clib_warning ("LISP is disabled!");
1519  return VNET_API_ERROR_LISP_DISABLED;
1520  }
1521 
1522  memset (ls_args, 0, sizeof (*ls_args));
1523 
1524  if (is_add)
1525  {
1526  /* Create dummy petr locator-set */
1527  memset (&loc, 0, sizeof (loc));
1528  gid_address_from_ip (&loc.address, ip);
1529  loc.priority = 1;
1530  loc.state = loc.weight = 1;
1531  loc.local = 0;
1532 
1533  ls_args->is_add = 1;
1534  ls_args->index = ~0;
1535  vec_add1 (ls_args->locators, loc);
1536  vnet_lisp_add_del_locator_set (ls_args, &ls_index);
1537 
1538  /* Add petr mapping */
1539  pool_get (lcm->mapping_pool, m);
1540  m->locator_set_index = ls_index;
1541  lcm->petr_map_index = m - lcm->mapping_pool;
1542 
1543  /* Enable use-petr */
1544  lcm->flags |= LISP_FLAG_USE_PETR;
1545  }
1546  else
1547  {
1549 
1550  /* Remove petr locator */
1551  ls_args->is_add = 0;
1552  ls_args->index = m->locator_set_index;
1553  vnet_lisp_add_del_locator_set (ls_args, 0);
1554 
1555  /* Remove petr mapping */
1557 
1558  /* Disable use-petr */
1559  lcm->flags &= ~LISP_FLAG_USE_PETR;
1560  }
1561  return 0;
1562 }
1563 
1564 /* cleans locator to locator-set data and removes locators not part of
1565  * any locator-set */
1566 static void
1568 {
1569  u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0;
1571  for (i = 0; i < vec_len (ls->locator_indices); i++)
1572  {
1573  loc_indexp = vec_elt_at_index (ls->locator_indices, i);
1574  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
1575  loc_indexp[0]);
1576  for (j = 0; j < vec_len (ls_indexes[0]); j++)
1577  {
1578  ls_indexp = vec_elt_at_index (ls_indexes[0], j);
1579  if (ls_indexp[0] == lsi)
1580  break;
1581  }
1582 
1583  /* delete index for removed locator-set */
1584  vec_del1 (ls_indexes[0], j);
1585 
1586  /* delete locator if it's part of no locator-set */
1587  if (vec_len (ls_indexes[0]) == 0)
1588  {
1589  pool_put_index (lcm->locator_pool, loc_indexp[0]);
1590  vec_add1 (to_be_deleted, i);
1591  }
1592  }
1593 
1594  if (to_be_deleted)
1595  {
1596  for (i = 0; i < vec_len (to_be_deleted); i++)
1597  {
1598  loc_indexp = vec_elt_at_index (to_be_deleted, i);
1599  vec_del1 (ls->locator_indices, loc_indexp[0]);
1600  }
1601  vec_free (to_be_deleted);
1602  }
1603 }
1604 
1605 static inline uword *
1607 {
1609 
1610  ASSERT (a != NULL);
1611  ASSERT (p != NULL);
1612 
1613  /* find locator-set */
1614  if (a->local)
1615  {
1617  }
1618  else
1619  {
1620  *p = a->index;
1621  }
1622 
1623  return p;
1624 }
1625 
1626 static inline int
1628  locator_t * loc)
1629 {
1630  locator_t *itloc;
1631  u32 *locit;
1632 
1633  ASSERT (ls != NULL);
1634  ASSERT (loc != NULL);
1635 
1636  vec_foreach (locit, ls->locator_indices)
1637  {
1638  itloc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1639  if ((ls->local && itloc->sw_if_index == loc->sw_if_index) ||
1640  (!ls->local && !gid_address_cmp (&itloc->address, &loc->address)))
1641  {
1642  clib_warning ("Duplicate locator");
1643  return VNET_API_ERROR_VALUE_EXIST;
1644  }
1645  }
1646 
1647  return 0;
1648 }
1649 
1650 static void
1652  u32 mapping_index, u8 remove_only)
1653 {
1654  fwd_entry_t *fwd;
1655  mapping_t *map;
1657 
1658  map = pool_elt_at_index (lcm->mapping_pool, mapping_index);
1659 
1660  /* *INDENT-OFF* */
1661  pool_foreach(fwd, lcm->fwd_entry_pool,
1662  ({
1663  if ((is_local && 0 == gid_address_cmp (&map->eid, &fwd->leid)) ||
1664  (!is_local && 0 == gid_address_cmp (&map->eid, &fwd->reid)))
1665  {
1666  a->is_add = 0;
1667  gid_address_copy (&a->leid, &fwd->leid);
1668  gid_address_copy (&a->reid, &fwd->reid);
1669 
1670  vnet_lisp_add_del_adjacency (a);
1671 
1672  if (!remove_only)
1673  {
1674  a->is_add = 1;
1675  vnet_lisp_add_del_adjacency (a);
1676  }
1677  }
1678  }));
1679  /* *INDENT-ON* */
1680 }
1681 
1682 static void
1684  u32 ls_index, u8 remove_only)
1685 {
1686  u32 i, *map_indexp;
1687  u32 **eid_indexes;
1688 
1689  if (vec_len (lcm->locator_set_to_eids) <= ls_index)
1690  return;
1691 
1692  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, ls_index);
1693 
1694  for (i = 0; i < vec_len (eid_indexes[0]); i++)
1695  {
1696  map_indexp = vec_elt_at_index (eid_indexes[0], i);
1697  update_adjacencies_by_map_index (lcm, is_local, map_indexp[0],
1698  remove_only);
1699  }
1700 }
1701 
1702 static inline void
1704  u32 ls_index, u32 loc_id)
1705 {
1707  u32 **ls_indexes = NULL;
1708 
1709  ASSERT (ls != NULL);
1710  ASSERT (locit != NULL);
1711 
1712  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, locit[0]);
1713  pool_put_index (lcm->locator_pool, locit[0]);
1714  vec_del1 (ls->locator_indices, loc_id);
1715  vec_del1 (ls_indexes[0], ls_index);
1716 }
1717 
1718 int
1720  locator_set_t * ls, u32 * ls_result)
1721 {
1723  locator_t *loc = NULL, *itloc = NULL;
1724  uword _p = (u32) ~ 0, *p = &_p;
1725  u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL;
1726  u32 loc_id = ~0;
1727  int ret = 0;
1728 
1729  ASSERT (a != NULL);
1730 
1731  if (vnet_lisp_enable_disable_status () == 0)
1732  {
1733  clib_warning ("LISP is disabled!");
1734  return VNET_API_ERROR_LISP_DISABLED;
1735  }
1736 
1737  p = get_locator_set_index (a, p);
1738  if (!p)
1739  {
1740  clib_warning ("locator-set %v doesn't exist", a->name);
1741  return VNET_API_ERROR_INVALID_ARGUMENT;
1742  }
1743 
1744  if (ls == 0)
1745  {
1746  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1747  if (!ls)
1748  {
1749  clib_warning ("locator-set %d to be overwritten doesn't exist!",
1750  p[0]);
1751  return VNET_API_ERROR_INVALID_ARGUMENT;
1752  }
1753  }
1754 
1755  if (a->is_add)
1756  {
1757  if (ls_result)
1758  ls_result[0] = p[0];
1759 
1760  /* allocate locators */
1761  vec_foreach (itloc, a->locators)
1762  {
1763  ret = is_locator_in_locator_set (lcm, ls, itloc);
1764  if (0 != ret)
1765  {
1766  return ret;
1767  }
1768 
1769  pool_get (lcm->locator_pool, loc);
1770  loc[0] = itloc[0];
1771  loc_index = loc - lcm->locator_pool;
1772 
1773  vec_add1 (ls->locator_indices, loc_index);
1774 
1775  vec_validate (lcm->locator_to_locator_sets, loc_index);
1776  ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets,
1777  loc_index);
1778  vec_add1 (ls_indexes[0], p[0]);
1779  }
1780  }
1781  else
1782  {
1783  ls_index = p[0];
1784  u8 removed;
1785 
1786  vec_foreach (itloc, a->locators)
1787  {
1788  removed = 0;
1789  loc_id = 0;
1790  vec_foreach (locit, ls->locator_indices)
1791  {
1792  loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
1793 
1794  if (loc->local && loc->sw_if_index == itloc->sw_if_index)
1795  {
1796  removed = 1;
1797  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
1798  }
1799  if (0 == loc->local &&
1800  !gid_address_cmp (&loc->address, &itloc->address))
1801  {
1802  removed = 1;
1803  remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
1804  }
1805 
1806  if (removed)
1807  {
1808  /* update fwd entries using this locator in DP */
1809  update_fwd_entries_by_locator_set (lcm, loc->local, ls_index,
1810  vec_len (ls->locator_indices)
1811  == 0);
1812  }
1813 
1814  loc_id++;
1815  }
1816  }
1817  }
1818 
1819  return 0;
1820 }
1821 
1822 int
1824  u32 * ls_result)
1825 {
1827  locator_set_t *ls;
1828  uword _p = (u32) ~ 0, *p = &_p;
1829  u32 ls_index;
1830  u32 **eid_indexes;
1831  int ret = 0;
1832 
1833  if (vnet_lisp_enable_disable_status () == 0)
1834  {
1835  clib_warning ("LISP is disabled!");
1836  return VNET_API_ERROR_LISP_DISABLED;
1837  }
1838 
1839  if (a->is_add)
1840  {
1841  p = get_locator_set_index (a, p);
1842 
1843  /* overwrite */
1844  if (p && p[0] != (u32) ~ 0)
1845  {
1846  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1847  if (!ls)
1848  {
1849  clib_warning ("locator-set %d to be overwritten doesn't exist!",
1850  p[0]);
1851  return -1;
1852  }
1853 
1854  /* clean locator to locator-set vectors and remove locators if
1855  * they're not part of another locator-set */
1856  clean_locator_to_locator_set (lcm, p[0]);
1857 
1858  /* remove locator indices from locator set */
1859  vec_free (ls->locator_indices);
1860 
1861  ls_index = p[0];
1862 
1863  if (ls_result)
1864  ls_result[0] = p[0];
1865  }
1866  /* new locator-set */
1867  else
1868  {
1869  pool_get (lcm->locator_set_pool, ls);
1870  memset (ls, 0, sizeof (*ls));
1871  ls_index = ls - lcm->locator_set_pool;
1872 
1873  if (a->local)
1874  {
1875  ls->name = vec_dup (a->name);
1876 
1877  if (!lcm->locator_set_index_by_name)
1879  /* size */
1880  0,
1881  sizeof
1882  (ls->name
1883  [0]),
1884  sizeof
1885  (uword));
1887  ls_index);
1888 
1889  /* mark as local locator-set */
1890  vec_add1 (lcm->local_locator_set_indexes, ls_index);
1891  }
1892  ls->local = a->local;
1893  if (ls_result)
1894  ls_result[0] = ls_index;
1895  }
1896 
1897  ret = vnet_lisp_add_del_locator (a, ls, NULL);
1898  if (0 != ret)
1899  {
1900  return ret;
1901  }
1902  }
1903  else
1904  {
1905  p = get_locator_set_index (a, p);
1906  if (!p)
1907  {
1908  clib_warning ("locator-set %v doesn't exists", a->name);
1909  return -1;
1910  }
1911 
1912  ls = pool_elt_at_index (lcm->locator_set_pool, p[0]);
1913  if (!ls)
1914  {
1915  clib_warning ("locator-set with index %d doesn't exists", p[0]);
1916  return -1;
1917  }
1918 
1919  if (lcm->mreq_itr_rlocs == p[0])
1920  {
1921  clib_warning ("Can't delete the locator-set used to constrain "
1922  "the itr-rlocs in map-requests!");
1923  return -1;
1924  }
1925 
1926  if (vec_len (lcm->locator_set_to_eids) != 0)
1927  {
1928  eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]);
1929  if (vec_len (eid_indexes[0]) != 0)
1930  {
1931  clib_warning
1932  ("Can't delete a locator that supports a mapping!");
1933  return -1;
1934  }
1935  }
1936 
1937  /* clean locator to locator-sets data */
1938  clean_locator_to_locator_set (lcm, p[0]);
1939 
1940  if (ls->local)
1941  {
1942  u32 it, lsi;
1943 
1945  {
1946  lsi = vec_elt (lcm->local_locator_set_indexes, it);
1947  if (lsi == p[0])
1948  {
1950  break;
1951  }
1952  }
1954  }
1955  vec_free (ls->name);
1956  vec_free (ls->locator_indices);
1957  pool_put (lcm->locator_set_pool, ls);
1958  }
1959  return 0;
1960 }
1961 
1962 int
1964 {
1966 
1967  lcm->rloc_probing = is_enable;
1968  return 0;
1969 }
1970 
1971 int
1973 {
1975 
1976  lcm->map_registering = is_enable;
1977  return 0;
1978 }
1979 
1980 clib_error_t *
1982 {
1983  u32 vni, dp_table;
1984  clib_error_t *error = 0;
1987 
1988  a->is_en = is_enable;
1989  error = vnet_lisp_gpe_enable_disable (a);
1990  if (error)
1991  {
1992  return clib_error_return (0, "failed to %s data-plane!",
1993  a->is_en ? "enable" : "disable");
1994  }
1995 
1996  if (is_enable)
1997  {
1998  /* enable all l2 and l3 ifaces */
1999 
2000  /* *INDENT-OFF* */
2001  hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({
2002  dp_add_del_iface(lcm, vni, 0, 1);
2003  }));
2004  hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({
2005  dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1);
2006  }));
2007  /* *INDENT-ON* */
2008  }
2009  else
2010  {
2011  /* clear interface table */
2013  pool_free (lcm->fwd_entry_pool);
2014  }
2015 
2016  /* update global flag */
2017  lcm->is_enabled = is_enable;
2018 
2019  return 0;
2020 }
2021 
2022 u8
2024 {
2026  return lcm->is_enabled;
2027 }
2028 
2029 int
2031 {
2033  u32 i;
2034  lisp_msmr_t _mr, *mr = &_mr;
2035 
2036  if (vnet_lisp_enable_disable_status () == 0)
2037  {
2038  clib_warning ("LISP is disabled!");
2039  return VNET_API_ERROR_LISP_DISABLED;
2040  }
2041 
2042  if (a->is_add)
2043  {
2044 
2045  if (get_map_resolver (&a->address))
2046  {
2047  clib_warning ("map-resolver %U already exists!", format_ip_address,
2048  &a->address);
2049  return -1;
2050  }
2051 
2052  memset (mr, 0, sizeof (*mr));
2053  ip_address_copy (&mr->address, &a->address);
2054  vec_add1 (lcm->map_resolvers, *mr);
2055 
2056  if (vec_len (lcm->map_resolvers) == 1)
2057  lcm->do_map_resolver_election = 1;
2058  }
2059  else
2060  {
2061  for (i = 0; i < vec_len (lcm->map_resolvers); i++)
2062  {
2063  mr = vec_elt_at_index (lcm->map_resolvers, i);
2064  if (!ip_address_cmp (&mr->address, &a->address))
2065  {
2066  if (!ip_address_cmp (&mr->address, &lcm->active_map_resolver))
2067  lcm->do_map_resolver_election = 1;
2068 
2069  vec_del1 (lcm->map_resolvers, i);
2070  break;
2071  }
2072  }
2073  }
2074  return 0;
2075 }
2076 
2077 int
2079 {
2081  uword *p = 0;
2082 
2083  if (vnet_lisp_enable_disable_status () == 0)
2084  {
2085  clib_warning ("LISP is disabled!");
2086  return VNET_API_ERROR_LISP_DISABLED;
2087  }
2088 
2089  if (a->is_add)
2090  {
2092  if (!p)
2093  {
2094  clib_warning ("locator-set %v doesn't exist", a->locator_set_name);
2095  return VNET_API_ERROR_INVALID_ARGUMENT;
2096  }
2097 
2098  lcm->mreq_itr_rlocs = p[0];
2099  }
2100  else
2101  {
2102  lcm->mreq_itr_rlocs = ~0;
2103  }
2104 
2105  return 0;
2106 }
2107 
2108 /* Statistics (not really errors) */
2109 #define foreach_lisp_cp_lookup_error \
2110 _(DROP, "drop") \
2111 _(MAP_REQUESTS_SENT, "map-request sent") \
2112 _(ARP_REPLY_TX, "ARP replies sent")
2113 
2115 #define _(sym,string) string,
2117 #undef _
2118 };
2119 
2120 typedef enum
2121 {
2122 #define _(sym,str) LISP_CP_LOOKUP_ERROR_##sym,
2124 #undef _
2127 
2128 typedef enum
2129 {
2134 
2135 typedef struct
2136 {
2138  ip_address_t map_resolver_ip;
2140 
2141 u8 *
2142 format_lisp_cp_lookup_trace (u8 * s, va_list * args)
2143 {
2144  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
2145  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
2146  lisp_cp_lookup_trace_t *t = va_arg (*args, lisp_cp_lookup_trace_t *);
2147 
2148  s = format (s, "LISP-CP-LOOKUP: map-resolver: %U destination eid %U",
2150  &t->dst_eid);
2151  return s;
2152 }
2153 
2154 int
2155 get_mr_and_local_iface_ip (lisp_cp_main_t * lcm, ip_address_t * mr_ip,
2156  ip_address_t * sloc)
2157 {
2158  lisp_msmr_t *mrit;
2159  ip_address_t *a;
2160 
2161  if (vec_len (lcm->map_resolvers) == 0)
2162  {
2163  clib_warning ("No map-resolver configured");
2164  return 0;
2165  }
2166 
2167  /* find the first mr ip we have a route to and the ip of the
2168  * iface that has a route to it */
2169  vec_foreach (mrit, lcm->map_resolvers)
2170  {
2171  a = &mrit->address;
2172  if (0 != ip_fib_get_first_egress_ip_for_dst (lcm, a, sloc))
2173  {
2174  ip_address_copy (mr_ip, a);
2175 
2176  /* also update globals */
2177  return 1;
2178  }
2179  }
2180 
2181  clib_warning ("Can't find map-resolver and local interface ip!");
2182  return 0;
2183 }
2184 
2185 static gid_address_t *
2187 {
2188  void *addr;
2189  u32 i;
2190  locator_t *loc;
2191  u32 *loc_indexp;
2192  ip_interface_address_t *ia = 0;
2193  gid_address_t gid_data, *gid = &gid_data;
2194  gid_address_t *rlocs = 0;
2195  ip_prefix_t *ippref = &gid_address_ippref (gid);
2196  ip_address_t *rloc = &ip_prefix_addr (ippref);
2197 
2198  memset (gid, 0, sizeof (gid[0]));
2200  for (i = 0; i < vec_len (loc_set->locator_indices); i++)
2201  {
2202  loc_indexp = vec_elt_at_index (loc_set->locator_indices, i);
2203  loc = pool_elt_at_index (lcm->locator_pool, loc_indexp[0]);
2204 
2205  /* Add ipv4 locators first TODO sort them */
2206 
2207  /* *INDENT-OFF* */
2209  loc->sw_if_index, 1 /* unnumbered */,
2210  ({
2211  addr = ip_interface_address_get_address (&lcm->im4->lookup_main, ia);
2212  ip_address_set (rloc, addr, IP4);
2213  ip_prefix_len (ippref) = 32;
2214  ip_prefix_normalize (ippref);
2215  vec_add1 (rlocs, gid[0]);
2216  }));
2217 
2218  /* Add ipv6 locators */
2220  loc->sw_if_index, 1 /* unnumbered */,
2221  ({
2222  addr = ip_interface_address_get_address (&lcm->im6->lookup_main, ia);
2223  ip_address_set (rloc, addr, IP6);
2224  ip_prefix_len (ippref) = 128;
2225  ip_prefix_normalize (ippref);
2226  vec_add1 (rlocs, gid[0]);
2227  }));
2228  /* *INDENT-ON* */
2229 
2230  }
2231  return rlocs;
2232 }
2233 
2234 static vlib_buffer_t *
2236  ip_address_t * sloc, ip_address_t * rloc,
2237  gid_address_t * itr_rlocs, u64 * nonce_res, u32 * bi_res)
2238 {
2239  vlib_buffer_t *b;
2240  u32 bi;
2241  vlib_main_t *vm = lcm->vlib_main;
2242 
2243  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2244  {
2245  clib_warning ("Can't allocate buffer for Map-Request!");
2246  return 0;
2247  }
2248 
2249  b = vlib_get_buffer (vm, bi);
2250 
2251  /* leave some space for the encap headers */
2253 
2254  /* put lisp msg */
2255  lisp_msg_put_mreq (lcm, b, NULL, deid, itr_rlocs, 0 /* smr invoked */ ,
2256  1 /* rloc probe */ , nonce_res);
2257 
2258  /* push outer ip header */
2260  rloc);
2261 
2262  bi_res[0] = bi;
2263 
2264  return b;
2265 }
2266 
2267 static vlib_buffer_t *
2269  gid_address_t * seid, gid_address_t * deid,
2270  locator_set_t * loc_set, ip_address_t * mr_ip,
2271  ip_address_t * sloc, u8 is_smr_invoked,
2272  u64 * nonce_res, u32 * bi_res)
2273 {
2274  vlib_buffer_t *b;
2275  u32 bi;
2276  gid_address_t *rlocs = 0;
2277  vlib_main_t *vm = lcm->vlib_main;
2278 
2279  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2280  {
2281  clib_warning ("Can't allocate buffer for Map-Request!");
2282  return 0;
2283  }
2284 
2285  b = vlib_get_buffer (vm, bi);
2286 
2287  /* leave some space for the encap headers */
2289 
2290  /* get rlocs */
2291  rlocs = build_itr_rloc_list (lcm, loc_set);
2292 
2293  if (MR_MODE_SRC_DST == lcm->map_request_mode
2294  && GID_ADDR_SRC_DST != gid_address_type (deid))
2295  {
2296  gid_address_t sd;
2297  memset (&sd, 0, sizeof (sd));
2298  build_src_dst (&sd, seid, deid);
2299  lisp_msg_put_mreq (lcm, b, seid, &sd, rlocs, is_smr_invoked,
2300  0 /* rloc probe */ , nonce_res);
2301  }
2302  else
2303  {
2304  /* put lisp msg */
2305  lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked,
2306  0 /* rloc probe */ , nonce_res);
2307  }
2308 
2309  /* push ecm: udp-ip-lisp */
2311 
2312  /* push outer ip header */
2314  mr_ip);
2315 
2316  bi_res[0] = bi;
2317 
2318  vec_free (rlocs);
2319  return b;
2320 }
2321 
2322 static void
2324 {
2326  r->retries_num = 0;
2327 }
2328 
2329 static int
2331 {
2332  lisp_msmr_t *mr;
2333 
2334  vec_foreach (mr, lcm->map_resolvers)
2335  {
2336  if (!mr->is_down)
2337  {
2339  lcm->do_map_resolver_election = 0;
2340  return 1;
2341  }
2342  }
2343  return 0;
2344 }
2345 
2346 static void
2348 {
2349  mapping_t *map;
2350  vec_foreach (map, maps) vec_free (map->locators);
2351 
2352  vec_free (maps);
2353 }
2354 
2355 static void
2356 add_locators (lisp_cp_main_t * lcm, mapping_t * m, u32 locator_set_index,
2357  ip_address_t * probed_loc)
2358 {
2359  u32 *li;
2360  locator_t *loc, new;
2361  ip_interface_address_t *ia = 0;
2362  void *addr;
2363  ip_address_t *new_ip = &gid_address_ip (&new.address);
2364 
2365  m->locators = 0;
2367  locator_set_index);
2368  vec_foreach (li, ls->locator_indices)
2369  {
2370  loc = pool_elt_at_index (lcm->locator_pool, li[0]);
2371  new = loc[0];
2372  if (loc->local)
2373  {
2374  /* *INDENT-OFF* */
2376  loc->sw_if_index, 1 /* unnumbered */,
2377  ({
2378  addr = ip_interface_address_get_address (&lcm->im4->lookup_main,
2379  ia);
2380  ip_address_set (new_ip, addr, IP4);
2381  }));
2382 
2383  /* Add ipv6 locators */
2385  loc->sw_if_index, 1 /* unnumbered */,
2386  ({
2387  addr = ip_interface_address_get_address (&lcm->im6->lookup_main,
2388  ia);
2389  ip_address_set (new_ip, addr, IP6);
2390  }));
2391  /* *INDENT-ON* */
2392 
2393  if (probed_loc && ip_address_cmp (probed_loc, new_ip) == 0)
2394  new.probed = 1;
2395  }
2396  vec_add1 (m->locators, new);
2397  }
2398 }
2399 
2400 static mapping_t *
2402 {
2403  mapping_t *recs = 0, rec, *m;
2404 
2405  /* *INDENT-OFF* */
2406  pool_foreach(m, lcm->mapping_pool,
2407  {
2408  /* for now build only local mappings */
2409  if (!m->local)
2410  continue;
2411 
2412  rec = m[0];
2413  add_locators (lcm, &rec, m->locator_set_index, NULL);
2414  vec_add1 (recs, rec);
2415  });
2416  /* *INDENT-ON* */
2417 
2418  return recs;
2419 }
2420 
2421 static int
2423  lisp_key_type_t key_id, u8 * key,
2424  u16 auth_data_len, u32 msg_len)
2425 {
2426  MREG_KEY_ID (map_reg_hdr) = clib_host_to_net_u16 (key_id);
2427  MREG_AUTH_DATA_LEN (map_reg_hdr) = clib_host_to_net_u16 (auth_data_len);
2428 
2429  unsigned char *result = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
2430  (unsigned char *) map_reg_hdr, msg_len, NULL,
2431  NULL);
2432  clib_memcpy (MREG_DATA (map_reg_hdr), result, auth_data_len);
2433 
2434  return 0;
2435 }
2436 
2437 static vlib_buffer_t *
2438 build_map_register (lisp_cp_main_t * lcm, ip_address_t * sloc,
2439  ip_address_t * ms_ip, u64 * nonce_res, u8 want_map_notif,
2440  mapping_t * records, lisp_key_type_t key_id, u8 * key,
2441  u32 * bi_res)
2442 {
2443  void *map_reg_hdr;
2444  vlib_buffer_t *b;
2445  u32 bi, auth_data_len = 0, msg_len = 0;
2446  vlib_main_t *vm = lcm->vlib_main;
2447 
2448  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
2449  {
2450  clib_warning ("Can't allocate buffer for Map-Register!");
2451  return 0;
2452  }
2453 
2454  b = vlib_get_buffer (vm, bi);
2455 
2456  /* leave some space for the encap headers */
2458 
2459  auth_data_len = auth_data_len_by_key_id (key_id);
2460  map_reg_hdr = lisp_msg_put_map_register (b, records, want_map_notif,
2461  auth_data_len, nonce_res,
2462  &msg_len);
2463 
2464  update_map_register_auth_data (map_reg_hdr, key_id, key, auth_data_len,
2465  msg_len);
2466 
2467  /* push outer ip header */
2469  ms_ip);
2470 
2471  bi_res[0] = bi;
2472  return b;
2473 }
2474 
2475 static int
2476 get_egress_map_resolver_ip (lisp_cp_main_t * lcm, ip_address_t * ip)
2477 {
2478  lisp_msmr_t *mr;
2479  while (lcm->do_map_resolver_election
2481  &lcm->active_map_resolver,
2482  ip)))
2483  {
2484  if (0 == elect_map_resolver (lcm))
2485  /* all map resolvers are down */
2486  {
2487  /* restart MR checking by marking all of them up */
2488  vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0;
2489  return -1;
2490  }
2491  }
2492  return 0;
2493 }
2494 
2495 /* CP output statistics */
2496 #define foreach_lisp_cp_output_error \
2497 _(MAP_REGISTERS_SENT, "map-registers sent") \
2498 _(RLOC_PROBES_SENT, "rloc-probes sent")
2499 
2501 #define _(sym,string) string,
2503 #undef _
2504 };
2505 
2506 typedef enum
2507 {
2508 #define _(sym,str) LISP_CP_OUTPUT_ERROR_##sym,
2510 #undef _
2513 
2514 static uword
2516  vlib_frame_t * from_frame)
2517 {
2518  return 0;
2519 }
2520 
2521 /* dummy node used only for statistics */
2522 /* *INDENT-OFF* */
2524  .function = lisp_cp_output,
2525  .name = "lisp-cp-output",
2526  .vector_size = sizeof (u32),
2527  .format_trace = format_lisp_cp_input_trace,
2528  .type = VLIB_NODE_TYPE_INTERNAL,
2529 
2530  .n_errors = LISP_CP_OUTPUT_N_ERROR,
2531  .error_strings = lisp_cp_output_error_strings,
2532 
2533  .n_next_nodes = LISP_CP_INPUT_N_NEXT,
2534 
2535  .next_nodes = {
2536  [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
2537  },
2538 };
2539 /* *INDENT-ON* */
2540 
2541 static int
2543  u32 local_locator_set_index, ip_address_t * sloc,
2544  ip_address_t * rloc)
2545 {
2546  locator_set_t *ls;
2547  u32 bi;
2548  vlib_buffer_t *b;
2549  vlib_frame_t *f;
2550  u64 nonce = 0;
2551  u32 next_index, *to_next;
2552  gid_address_t *itr_rlocs;
2553 
2554  ls = pool_elt_at_index (lcm->locator_set_pool, local_locator_set_index);
2555  itr_rlocs = build_itr_rloc_list (lcm, ls);
2556 
2557  b = build_map_request (lcm, deid, sloc, rloc, itr_rlocs, &nonce, &bi);
2558  vec_free (itr_rlocs);
2559  if (!b)
2560  return -1;
2561 
2562  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
2563 
2564  next_index = (ip_addr_version (rloc) == IP4) ?
2565  ip4_lookup_node.index : ip6_lookup_node.index;
2566 
2567  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
2568 
2569  /* Enqueue the packet */
2570  to_next = vlib_frame_vector_args (f);
2571  to_next[0] = bi;
2572  f->n_vectors = 1;
2573  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
2574 
2575  hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
2576  return 0;
2577 }
2578 
2579 static int
2581 {
2582  u8 lprio = 0;
2583  mapping_t *lm;
2584  fwd_entry_t *e;
2585  locator_pair_t *lp;
2586  u32 si, rloc_probes_sent = 0;
2587 
2588  /* *INDENT-OFF* */
2589  pool_foreach (e, lcm->fwd_entry_pool,
2590  {
2591  if (vec_len (e->locator_pairs) == 0)
2592  continue;
2593 
2594  si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &e->leid);
2595  if (~0 == si)
2596  {
2597  clib_warning ("internal error: cannot find local eid %U in "
2598  "map-cache!", format_gid_address, &e->leid);
2599  continue;
2600  }
2601  lm = pool_elt_at_index (lcm->mapping_pool, si);
2602 
2603  /* get the best (lowest) priority */
2604  lprio = e->locator_pairs[0].priority;
2605 
2606  /* send rloc-probe for pair(s) with the best remote locator priority */
2607  vec_foreach (lp, e->locator_pairs)
2608  {
2609  if (lp->priority != lprio)
2610  break;
2611 
2612  /* get first remote locator */
2613  send_rloc_probe (lcm, &e->reid, lm->locator_set_index, &lp->lcl_loc,
2614  &lp->rmt_loc);
2615  rloc_probes_sent++;
2616  }
2617  });
2618  /* *INDENT-ON* */
2619 
2621  LISP_CP_OUTPUT_ERROR_RLOC_PROBES_SENT,
2622  rloc_probes_sent);
2623  return 0;
2624 }
2625 
2626 static int
2627 send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif)
2628 {
2629  u32 bi, map_registers_sent = 0;
2630  vlib_buffer_t *b;
2631  ip_address_t sloc;
2632  vlib_frame_t *f;
2633  u64 nonce = 0;
2634  u32 next_index, *to_next;
2635  ip_address_t *ms = 0;
2636  mapping_t *records, *r, *group, *k;
2637 
2638  // TODO: support multiple map servers and do election
2639  if (0 == vec_len (lcm->map_servers))
2640  return -1;
2641 
2642  ms = &lcm->map_servers[0].address;
2643 
2644  if (0 == ip_fib_get_first_egress_ip_for_dst (lcm, ms, &sloc))
2645  {
2646  clib_warning ("no eligible interface address found for %U!",
2647  format_ip_address, &lcm->map_servers[0]);
2648  return -1;
2649  }
2650 
2651  records = build_map_register_record_list (lcm);
2652  if (!records)
2653  return -1;
2654 
2655  vec_foreach (r, records)
2656  {
2657  u8 *key = r->key;
2658  u8 key_id = r->key_id;
2659 
2660  if (!key)
2661  continue; /* no secret key -> map-register cannot be sent */
2662 
2663  group = 0;
2664  vec_add1 (group, r[0]);
2665 
2666  /* group mappings that share common key */
2667  for (k = r + 1; k < vec_end (records); k++)
2668  {
2669  if (k->key_id != r->key_id)
2670  continue;
2671 
2672  if (vec_is_equal (k->key, r->key))
2673  {
2674  vec_add1 (group, k[0]);
2675  k->key = 0; /* don't process this mapping again */
2676  }
2677  }
2678 
2679  b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, group,
2680  key_id, key, &bi);
2681  vec_free (group);
2682  if (!b)
2683  continue;
2684 
2685  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
2686 
2687  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
2688  ip4_lookup_node.index : ip6_lookup_node.index;
2689 
2690  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
2691 
2692  /* Enqueue the packet */
2693  to_next = vlib_frame_vector_args (f);
2694  to_next[0] = bi;
2695  f->n_vectors = 1;
2696  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
2697  map_registers_sent++;
2698 
2699  hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
2700  }
2701  free_map_register_records (records);
2702 
2704  LISP_CP_OUTPUT_ERROR_MAP_REGISTERS_SENT,
2705  map_registers_sent);
2706 
2707  return 0;
2708 }
2709 
2710 #define send_encapsulated_map_request(lcm, seid, deid, smr) \
2711  _send_encapsulated_map_request(lcm, seid, deid, smr, 0)
2712 
2713 #define resend_encapsulated_map_request(lcm, seid, deid, smr) \
2714  _send_encapsulated_map_request(lcm, seid, deid, smr, 1)
2715 
2716 static int
2717 _send_encapsulated_map_request (lisp_cp_main_t * lcm,
2718  gid_address_t * seid, gid_address_t * deid,
2719  u8 is_smr_invoked, u8 is_resend)
2720 {
2721  u32 next_index, bi = 0, *to_next, map_index;
2722  vlib_buffer_t *b;
2723  vlib_frame_t *f;
2724  u64 nonce = 0;
2725  locator_set_t *loc_set;
2726  mapping_t *map;
2727  pending_map_request_t *pmr, *duplicate_pmr = 0;
2728  ip_address_t sloc;
2729  u32 ls_index;
2730 
2731  /* if there is already a pending request remember it */
2732 
2733  /* *INDENT-OFF* */
2735  ({
2736  if (!gid_address_cmp (&pmr->src, seid)
2737  && !gid_address_cmp (&pmr->dst, deid))
2738  {
2739  duplicate_pmr = pmr;
2740  break;
2741  }
2742  }));
2743  /* *INDENT-ON* */
2744 
2745  if (!is_resend && duplicate_pmr)
2746  {
2747  /* don't send the request if there is a pending map request already */
2748  return 0;
2749  }
2750 
2751  /* get locator-set for seid */
2752  if (!lcm->lisp_pitr && gid_address_type (deid) != GID_ADDR_NSH)
2753  {
2754  map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
2755  if (map_index == ~0)
2756  {
2757  clib_warning ("No local mapping found in eid-table for %U!",
2758  format_gid_address, seid);
2759  return -1;
2760  }
2761 
2762  map = pool_elt_at_index (lcm->mapping_pool, map_index);
2763 
2764  if (!map->local)
2765  {
2766  clib_warning
2767  ("Mapping found for src eid %U is not marked as local!",
2768  format_gid_address, seid);
2769  return -1;
2770  }
2771  ls_index = map->locator_set_index;
2772  }
2773  else
2774  {
2775  if (lcm->lisp_pitr)
2776  {
2777  map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
2778  ls_index = map->locator_set_index;
2779  }
2780  else
2781  {
2782  if (lcm->nsh_map_index == (u32) ~ 0)
2783  {
2784  clib_warning ("No locator-set defined for NSH!");
2785  return -1;
2786  }
2787  else
2788  {
2789  map = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index);
2790  ls_index = map->locator_set_index;
2791  }
2792  }
2793  }
2794 
2795  /* overwrite locator set if map-request itr-rlocs configured */
2796  if (~0 != lcm->mreq_itr_rlocs)
2797  {
2798  ls_index = lcm->mreq_itr_rlocs;
2799  }
2800 
2801  loc_set = pool_elt_at_index (lcm->locator_set_pool, ls_index);
2802 
2803  if (get_egress_map_resolver_ip (lcm, &sloc) < 0)
2804  {
2805  if (duplicate_pmr)
2806  duplicate_pmr->to_be_removed = 1;
2807  return -1;
2808  }
2809 
2810  /* build the encapsulated map request */
2811  b = build_encapsulated_map_request (lcm, seid, deid, loc_set,
2812  &lcm->active_map_resolver,
2813  &sloc, is_smr_invoked, &nonce, &bi);
2814 
2815  if (!b)
2816  return -1;
2817 
2818  /* set fib index to default and lookup node */
2819  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
2820  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
2821  ip4_lookup_node.index : ip6_lookup_node.index;
2822 
2823  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
2824 
2825  /* Enqueue the packet */
2826  to_next = vlib_frame_vector_args (f);
2827  to_next[0] = bi;
2828  f->n_vectors = 1;
2829  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
2830 
2831  if (duplicate_pmr)
2832  /* if there is a pending request already update it */
2833  {
2834  if (clib_fifo_elts (duplicate_pmr->nonces) >= PENDING_MREQ_QUEUE_LEN)
2835  {
2836  /* remove the oldest nonce */
2837  u64 CLIB_UNUSED (tmp), *nonce_del;
2838  nonce_del = clib_fifo_head (duplicate_pmr->nonces);
2839  hash_unset (lcm->pending_map_requests_by_nonce, nonce_del[0]);
2840  clib_fifo_sub1 (duplicate_pmr->nonces, tmp);
2841  }
2842 
2843  clib_fifo_add1 (duplicate_pmr->nonces, nonce);
2844  hash_set (lcm->pending_map_requests_by_nonce, nonce,
2845  duplicate_pmr - lcm->pending_map_requests_pool);
2846  }
2847  else
2848  {
2849  /* add map-request to pending requests table */
2850  pool_get (lcm->pending_map_requests_pool, pmr);
2851  memset (pmr, 0, sizeof (*pmr));
2852  gid_address_copy (&pmr->src, seid);
2853  gid_address_copy (&pmr->dst, deid);
2854  clib_fifo_add1 (pmr->nonces, nonce);
2855  pmr->is_smr_invoked = is_smr_invoked;
2857  hash_set (lcm->pending_map_requests_by_nonce, nonce,
2858  pmr - lcm->pending_map_requests_pool);
2859  }
2860 
2861  return 0;
2862 }
2863 
2864 static void
2865 get_src_and_dst_ip (void *hdr, ip_address_t * src, ip_address_t * dst)
2866 {
2867  ip4_header_t *ip4 = hdr;
2868  ip6_header_t *ip6;
2869 
2870  if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
2871  {
2872  ip_address_set (src, &ip4->src_address, IP4);
2873  ip_address_set (dst, &ip4->dst_address, IP4);
2874  }
2875  else
2876  {
2877  ip6 = hdr;
2878  ip_address_set (src, &ip6->src_address, IP6);
2879  ip_address_set (dst, &ip6->dst_address, IP6);
2880  }
2881 }
2882 
2883 static u32
2885  u8 version)
2886 {
2887  uword *vnip;
2888  u32 vni = ~0, table_id = ~0;
2889 
2890  table_id = fib_table_get_table_id_for_sw_if_index ((version ==
2891  IP4 ? FIB_PROTOCOL_IP4 :
2893  vnet_buffer
2894  (b)->sw_if_index
2895  [VLIB_RX]);
2896 
2897  vnip = hash_get (lcm->vni_by_table_id, table_id);
2898  if (vnip)
2899  vni = vnip[0];
2900  else
2901  clib_warning ("vrf %d is not mapped to any vni!", table_id);
2902 
2903  return vni;
2904 }
2905 
2908 {
2909  u32 sw_if_index0;
2910 
2911  l2input_main_t *l2im = &l2input_main;
2912  l2_input_config_t *config;
2913  l2_bridge_domain_t *bd_config;
2914 
2915  sw_if_index0 = vnet_buffer (b)->sw_if_index[VLIB_RX];
2916  config = vec_elt_at_index (l2im->configs, sw_if_index0);
2917  bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
2918 
2919  return bd_config->bd_id;
2920 }
2921 
2924 {
2925  uword *vnip;
2926  u32 vni = ~0;
2928 
2929  vnip = hash_get (lcm->vni_by_bd_id, bd);
2930  if (vnip)
2931  vni = vnip[0];
2932  else
2933  clib_warning ("bridge domain %d is not mapped to any vni!", bd);
2934 
2935  return vni;
2936 }
2937 
2938 void
2940  gid_address_t * src, gid_address_t * dst,
2941  u16 type)
2942 {
2943  ethernet_header_t *eh;
2944  u32 vni = 0;
2945 
2946  memset (src, 0, sizeof (*src));
2947  memset (dst, 0, sizeof (*dst));
2948 
2951 
2952  if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
2953  {
2954  ip4_header_t *ip;
2955  u8 version, preflen;
2956 
2959 
2960  ip = vlib_buffer_get_current (b);
2961  get_src_and_dst_ip (ip, &gid_address_ip (src), &gid_address_ip (dst));
2962 
2963  version = gid_address_ip_version (src);
2964  preflen = ip_address_max_len (version);
2965  gid_address_ippref_len (src) = preflen;
2966  gid_address_ippref_len (dst) = preflen;
2967 
2968  vni = lisp_get_vni_from_buffer_ip (lcm, b, version);
2969  gid_address_vni (dst) = vni;
2970  gid_address_vni (src) = vni;
2971  }
2972  else if (LISP_AFI_MAC == type)
2973  {
2975 
2976  eh = vlib_buffer_get_current (b);
2977 
2978  if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_ARP)
2979  {
2980  ah = (ethernet_arp_header_t *) (((u8 *) eh) + sizeof (*eh));
2981  if (clib_net_to_host_u16 (ah->opcode)
2982  != ETHERNET_ARP_OPCODE_request)
2983  return;
2984 
2988  &ah->ip4_over_ethernet[1].ip4, 4);
2989  }
2990  else
2991  {
2994  mac_copy (&gid_address_mac (src), eh->src_address);
2995  mac_copy (&gid_address_mac (dst), eh->dst_address);
2996 
2997  /* get vni */
2998  vni = lisp_get_vni_from_buffer_eth (lcm, b);
2999 
3000  gid_address_vni (dst) = vni;
3001  gid_address_vni (src) = vni;
3002  }
3003  }
3004  else if (LISP_AFI_LCAF == type)
3005  {
3006  lisp_nsh_hdr_t *nh;
3007  eh = vlib_buffer_get_current (b);
3008 
3009  if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_NSH)
3010  {
3011  nh = (lisp_nsh_hdr_t *) (((u8 *) eh) + sizeof (*eh));
3012  u32 spi = clib_net_to_host_u32 (nh->spi_si << 8);
3013  u8 si = (u8) clib_net_to_host_u32 (nh->spi_si);
3014  gid_address_nsh_spi (dst) = spi;
3015  gid_address_nsh_si (dst) = si;
3016 
3018  }
3019  }
3020 }
3021 
3022 static uword
3024  vlib_node_runtime_t * node,
3025  vlib_frame_t * from_frame, int overlay)
3026 {
3027  u32 *from, *to_next, di, si;
3029  u32 pkts_mapped = 0, next_index;
3030  uword n_left_from, n_left_to_next;
3031  vnet_main_t *vnm = vnet_get_main ();
3032 
3033  from = vlib_frame_vector_args (from_frame);
3034  n_left_from = from_frame->n_vectors;
3035  next_index = node->cached_next_index;
3036 
3037  while (n_left_from > 0)
3038  {
3039  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
3040 
3041  while (n_left_from > 0 && n_left_to_next > 0)
3042  {
3043  u32 pi0, sw_if_index0, next0;
3044  u64 mac0;
3045  vlib_buffer_t *b0;
3046  gid_address_t src, dst;
3047  ethernet_arp_header_t *arp0;
3048  ethernet_header_t *eth0;
3049  vnet_hw_interface_t *hw_if0;
3050 
3051  pi0 = from[0];
3052  from += 1;
3053  n_left_from -= 1;
3054  to_next[0] = pi0;
3055  to_next += 1;
3056  n_left_to_next -= 1;
3057 
3058  b0 = vlib_get_buffer (vm, pi0);
3059 
3060  /* src/dst eid pair */
3061  get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay);
3062 
3063  if (gid_address_type (&dst) == GID_ADDR_ARP)
3064  {
3065  mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
3066  if (GID_LOOKUP_MISS_L2 != mac0)
3067  {
3068  /* send ARP reply */
3069 
3070  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
3071  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
3072 
3073  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
3074 
3075  eth0 = vlib_buffer_get_current (b0);
3076  arp0 = (ethernet_arp_header_t *) (((u8 *) eth0)
3077  + sizeof (*eth0));
3078  arp0->opcode =
3079  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
3080  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
3081  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
3082  (u8 *) & mac0, 6);
3083  clib_memcpy (&arp0->ip4_over_ethernet[0].ip4,
3084  &gid_address_arp_ip4 (&dst), 4);
3085 
3086  /* Hardware must be ethernet-like. */
3087  ASSERT (vec_len (hw_if0->hw_address) == 6);
3088 
3089  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
3090  clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
3091 
3092  b0->error = node->errors[LISP_CP_LOOKUP_ERROR_ARP_REPLY_TX];
3094  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
3095  to_next,
3096  n_left_to_next, pi0,
3097  next0);
3098  continue;
3099  }
3100  goto done;
3101  }
3102 
3103  /* if we have remote mapping for destination already in map-chache
3104  add forwarding tunnel directly. If not send a map-request */
3106  &src);
3107  if (~0 != di)
3108  {
3109  mapping_t *m = vec_elt_at_index (lcm->mapping_pool, di);
3110  /* send a map-request also in case of negative mapping entry
3111  with corresponding action */
3112  if (m->action == LISP_SEND_MAP_REQUEST)
3113  {
3114  /* send map-request */
3115  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
3116  0 /* is_resend */ );
3117  pkts_mapped++;
3118  }
3119  else
3120  {
3121  if (GID_ADDR_NSH != gid_address_type (&dst))
3122  {
3124  &src);
3125  }
3126  else
3127  si = lcm->nsh_map_index;
3128 
3129  if (~0 != si)
3130  {
3131  dp_add_fwd_entry_from_mt (si, di);
3132  }
3133  }
3134  }
3135  else
3136  {
3137  /* send map-request */
3138  queue_map_request (&src, &dst, 0 /* smr_invoked */ ,
3139  0 /* is_resend */ );
3140  pkts_mapped++;
3141  }
3142 
3143  done:
3144  b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
3146  {
3147  lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
3148  sizeof (*tr));
3149 
3150  memset (tr, 0, sizeof (*tr));
3151  gid_address_copy (&tr->dst_eid, &dst);
3153  &lcm->active_map_resolver);
3154  }
3155  gid_address_free (&dst);
3156  gid_address_free (&src);
3157  next0 = LISP_CP_LOOKUP_NEXT_DROP;
3158  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
3159  to_next,
3160  n_left_to_next, pi0, next0);
3161  }
3162 
3163  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3164  }
3166  LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
3167  pkts_mapped);
3168  return from_frame->n_vectors;
3169 }
3170 
3171 static uword
3173  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
3174 {
3175  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP));
3176 }
3177 
3178 static uword
3180  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
3181 {
3182  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_IP6));
3183 }
3184 
3185 static uword
3187  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
3188 {
3189  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_MAC));
3190 }
3191 
3192 static uword
3194  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
3195 {
3196  /* TODO decide if NSH should be propagated as LCAF or not */
3197  return (lisp_cp_lookup_inline (vm, node, from_frame, LISP_AFI_LCAF));
3198 }
3199 
3200 /* *INDENT-OFF* */
3202  .function = lisp_cp_lookup_ip4,
3203  .name = "lisp-cp-lookup-ip4",
3204  .vector_size = sizeof (u32),
3205  .format_trace = format_lisp_cp_lookup_trace,
3206  .type = VLIB_NODE_TYPE_INTERNAL,
3207 
3208  .n_errors = LISP_CP_LOOKUP_N_ERROR,
3209  .error_strings = lisp_cp_lookup_error_strings,
3210 
3211  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
3212 
3213  .next_nodes = {
3214  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
3215  [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
3216  },
3217 };
3218 /* *INDENT-ON* */
3219 
3220 /* *INDENT-OFF* */
3222  .function = lisp_cp_lookup_ip6,
3223  .name = "lisp-cp-lookup-ip6",
3224  .vector_size = sizeof (u32),
3225  .format_trace = format_lisp_cp_lookup_trace,
3226  .type = VLIB_NODE_TYPE_INTERNAL,
3227 
3228  .n_errors = LISP_CP_LOOKUP_N_ERROR,
3229  .error_strings = lisp_cp_lookup_error_strings,
3230 
3231  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
3232 
3233  .next_nodes = {
3234  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
3235  [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
3236  },
3237 };
3238 /* *INDENT-ON* */
3239 
3240 /* *INDENT-OFF* */
3242  .function = lisp_cp_lookup_l2,
3243  .name = "lisp-cp-lookup-l2",
3244  .vector_size = sizeof (u32),
3245  .format_trace = format_lisp_cp_lookup_trace,
3246  .type = VLIB_NODE_TYPE_INTERNAL,
3247 
3248  .n_errors = LISP_CP_LOOKUP_N_ERROR,
3249  .error_strings = lisp_cp_lookup_error_strings,
3250 
3251  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
3252 
3253  .next_nodes = {
3254  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
3255  [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
3256  },
3257 };
3258 /* *INDENT-ON* */
3259 
3260 /* *INDENT-OFF* */
3262  .function = lisp_cp_lookup_nsh,
3263  .name = "lisp-cp-lookup-nsh",
3264  .vector_size = sizeof (u32),
3265  .format_trace = format_lisp_cp_lookup_trace,
3266  .type = VLIB_NODE_TYPE_INTERNAL,
3267 
3268  .n_errors = LISP_CP_LOOKUP_N_ERROR,
3269  .error_strings = lisp_cp_lookup_error_strings,
3270 
3271  .n_next_nodes = LISP_CP_LOOKUP_N_NEXT,
3272 
3273  .next_nodes = {
3274  [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
3275  [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
3276  },
3277 };
3278 /* *INDENT-ON* */
3279 
3280 /* lisp_cp_input statistics */
3281 #define foreach_lisp_cp_input_error \
3282 _(DROP, "drop") \
3283 _(RLOC_PROBE_REQ_RECEIVED, "rloc-probe requests received") \
3284 _(RLOC_PROBE_REP_RECEIVED, "rloc-probe replies received") \
3285 _(MAP_NOTIFIES_RECEIVED, "map-notifies received") \
3286 _(MAP_REPLIES_RECEIVED, "map-replies received")
3287 
3289 #define _(sym,string) string,
3291 #undef _
3292 };
3293 
3294 typedef enum
3295 {
3296 #define _(sym,str) LISP_CP_INPUT_ERROR_##sym,
3298 #undef _
3301 
3302 typedef struct
3303 {
3307 
3308 u8 *
3309 format_lisp_cp_input_trace (u8 * s, va_list * args)
3310 {
3311  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
3312  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
3314  va_arg (*args, lisp_cp_input_trace_t *);
3315 
3316  s = format (s, "LISP-CP-INPUT: TODO");
3317  return s;
3318 }
3319 
3320 static void
3322 {
3323  mapping_t *m;
3324  vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args;
3325  memset (adj_args, 0, sizeof (adj_args[0]));
3326 
3327  m = pool_elt_at_index (lcm->mapping_pool, mi);
3328 
3329  gid_address_copy (&adj_args->reid, &m->eid);
3330  adj_args->is_add = 0;
3331  if (vnet_lisp_add_del_adjacency (adj_args))
3332  clib_warning ("failed to del adjacency!");
3333 
3334  vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ ,
3335  0 /* is_static */ , 0);
3336  mapping_delete_timer (lcm, mi);
3337 }
3338 
3339 static void
3341  f64 expiration_time)
3342 {
3343  mapping_t *m;
3344  u64 now = clib_cpu_time_now ();
3345  u64 cpu_cps = lcm->vlib_main->clib_time.clocks_per_second;
3346  u64 exp_clock_time = now + expiration_time * cpu_cps;
3347 
3348  m = pool_elt_at_index (lcm->mapping_pool, mi);
3349 
3350  m->timer_set = 1;
3351  timing_wheel_insert (&lcm->wheel, exp_clock_time, mi);
3352 }
3353 
3354 static void
3356 {
3358  mapping_t *m;
3359  vec_foreach (m, a->mappings)
3360  {
3361  vec_free (m->locators);
3362  gid_address_free (&m->eid);
3363  }
3365 }
3366 
3367 void *
3369 {
3370  mapping_t *m;
3372  u32 dst_map_index = 0;
3373  pending_map_request_t *pmr;
3374  u64 *noncep;
3375  uword *pmr_index;
3376 
3377  if (a->is_rloc_probe)
3378  goto done;
3379 
3380  /* Check pending requests table and nonce */
3381  pmr_index = hash_get (lcm->pending_map_requests_by_nonce, a->nonce);
3382  if (!pmr_index)
3383  {
3384  clib_warning ("No pending map-request entry with nonce %lu!", a->nonce);
3385  goto done;
3386  }
3387  pmr = pool_elt_at_index (lcm->pending_map_requests_pool, pmr_index[0]);
3388 
3389  vec_foreach (m, a->mappings)
3390  {
3391  /* insert/update mappings cache */
3393  m->authoritative, m->ttl,
3394  1, 0 /* is_static */ , &dst_map_index);
3395 
3396  if (dst_map_index == (u32) ~ 0)
3397  continue;
3398 
3399  /* try to program forwarding only if mapping saved or updated */
3400  vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args;
3401  memset (adj_args, 0, sizeof (adj_args[0]));
3402 
3403  gid_address_copy (&adj_args->leid, &pmr->src);
3404  gid_address_copy (&adj_args->reid, &m->eid);
3405  adj_args->is_add = 1;
3406  if (vnet_lisp_add_del_adjacency (adj_args))
3407  clib_warning ("failed to add adjacency!");
3408 
3409  if ((u32) ~ 0 != m->ttl)
3410  mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60);
3411  }
3412 
3413  /* remove pending map request entry */
3414 
3415  /* *INDENT-OFF* */
3416  clib_fifo_foreach (noncep, pmr->nonces, ({
3417  hash_unset(lcm->pending_map_requests_by_nonce, noncep[0]);
3418  }));
3419  /* *INDENT-ON* */
3420 
3421  clib_fifo_free (pmr->nonces);
3422  pool_put (lcm->pending_map_requests_pool, pmr);
3423 
3424 done:
3425  a->is_free = 1;
3426  return 0;
3427 }
3428 
3429 static int
3431  lisp_key_type_t key_id, u8 * key)
3432 {
3433  u8 *auth_data = 0;
3434  u16 auth_data_len;
3435  int result;
3436 
3437  auth_data_len = auth_data_len_by_key_id (key_id);
3438  if ((u16) ~ 0 == auth_data_len)
3439  {
3440  clib_warning ("invalid length for key_id %d!", key_id);
3441  return 0;
3442  }
3443 
3444  /* save auth data */
3445  vec_validate (auth_data, auth_data_len - 1);
3446  clib_memcpy (auth_data, MNOTIFY_DATA (h), auth_data_len);
3447 
3448  /* clear auth data */
3449  memset (MNOTIFY_DATA (h), 0, auth_data_len);
3450 
3451  /* get hash of the message */
3452  unsigned char *code = HMAC (get_encrypt_fcn (key_id), key, vec_len (key),
3453  (unsigned char *) h, msg_len, NULL, NULL);
3454 
3455  result = memcmp (code, auth_data, auth_data_len);
3456 
3457  vec_free (auth_data);
3458 
3459  return !result;
3460 }
3461 
3462 static void
3464 {
3466  uword *pmr_index;
3467 
3468  pmr_index = hash_get (lcm->map_register_messages_by_nonce, a->nonce);
3469  if (!pmr_index)
3470  {
3471  clib_warning ("No pending map-register entry with nonce %lu!",
3472  a->nonce);
3473  return;
3474  }
3475 
3476  a->is_free = 1;
3478 }
3479 
3480 static mapping_t *
3482 {
3483  u32 mi;
3484 
3486  if (~0 == mi)
3487  {
3488  clib_warning ("eid %U not found in map-cache!", unformat_gid_address,
3489  e);
3490  return 0;
3491  }
3492  return pool_elt_at_index (lcm->mapping_pool, mi);
3493 }
3494 
3495 /**
3496  * When map-notify is received it is necessary that all EIDs in the record
3497  * list share common key. The key is then used to verify authentication
3498  * data in map-notify message.
3499  */
3500 static int
3502  u32 key_id, u8 ** key_out)
3503 {
3504  u32 i, len = vec_len (maps);
3505  mapping_t *m;
3506 
3507  /* get key of the first mapping */
3508  m = get_mapping (lcm, &maps[0].eid);
3509  if (!m || !m->key)
3510  return -1;
3511 
3512  key_out[0] = m->key;
3513 
3514  for (i = 1; i < len; i++)
3515  {
3516  m = get_mapping (lcm, &maps[i].eid);
3517  if (!m || !m->key)
3518  return -1;
3519 
3520  if (key_id != m->key_id || vec_cmp (m->key, key_out[0]))
3521  {
3522  clib_warning ("keys does not match! %v, %v", key_out[0], m->key);
3523  return -1;
3524  }
3525  }
3526  return 0;
3527 }
3528 
3529 static int
3531 {
3532  locator_t *locators = 0;
3533  u32 i, len;
3534  gid_address_t deid;
3535  mapping_t m;
3536  locator_t *loc;
3537 
3538  memset (&m, 0, sizeof (m));
3539 
3540  /* parse record eid */
3541  for (i = 0; i < count; i++)
3542  {
3543  locators = 0;
3544  len = lisp_msg_parse_mapping_record (b, &deid, &locators, NULL);
3545  if (len == ~0)
3546  {
3547  clib_warning ("Failed to parse mapping record!");
3548  vec_foreach (loc, locators) locator_free (loc);
3549  vec_free (locators);
3550  return -1;
3551  }
3552 
3553  m.locators = locators;
3554  gid_address_copy (&m.eid, &deid);
3555  vec_add1 (a->mappings, m);
3556  }
3557 
3558  return 0;
3559 }
3560 
3561 static map_records_arg_t *
3563 {
3565  map_records_arg_t *rec;
3566 
3567  /* Cleanup first */
3568  /* *INDENT-OFF* */
3570  if (rec->is_free)
3571  map_records_arg_free (rec);
3572  }));
3573  /* *INDENT-ON* */
3574 
3576  return rec;
3577 }
3578 
3579 static map_records_arg_t *
3581 {
3582  int rc = 0;
3583  map_notify_hdr_t *mnotif_hdr;
3584  lisp_key_type_t key_id;
3586  u8 *key = 0;
3587  gid_address_t deid;
3588  u16 auth_data_len = 0;
3589  u8 record_count;
3591 
3592  a = map_record_args_get ();
3593  memset (a, 0, sizeof (*a));
3594  mnotif_hdr = vlib_buffer_get_current (b);
3595  vlib_buffer_pull (b, sizeof (*mnotif_hdr));
3596  memset (&deid, 0, sizeof (deid));
3597 
3598  a->nonce = MNOTIFY_NONCE (mnotif_hdr);
3599  key_id = clib_net_to_host_u16 (MNOTIFY_KEY_ID (mnotif_hdr));
3600  auth_data_len = auth_data_len_by_key_id (key_id);
3601 
3602  /* advance buffer by authentication data */
3603  vlib_buffer_pull (b, auth_data_len);
3604 
3605  record_count = MNOTIFY_REC_COUNT (mnotif_hdr);
3606  rc = parse_map_records (b, a, record_count);
3607  if (rc != 0)
3608  {
3610  return 0;
3611  }
3612 
3613  rc = map_record_integrity_check (lcm, a->mappings, key_id, &key);
3614  if (rc != 0)
3615  {
3617  return 0;
3618  }
3619 
3620  /* verify authentication data */
3621  if (!is_auth_data_valid (mnotif_hdr, vlib_buffer_get_tail (b)
3622  - (u8 *) mnotif_hdr, key_id, key))
3623  {
3624  clib_warning ("Map-notify auth data verification failed for nonce %lu!",
3625  a->nonce);
3627  return 0;
3628  }
3629  return a;
3630 }
3631 
3632 static vlib_buffer_t *
3633 build_map_reply (lisp_cp_main_t * lcm, ip_address_t * sloc,
3634  ip_address_t * dst, u64 nonce, u8 probe_bit,
3635  mapping_t * records, u16 dst_port, u32 * bi_res)
3636 {
3637  vlib_buffer_t *b;
3638  u32 bi;
3639  vlib_main_t *vm = lcm->vlib_main;
3640 
3641  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
3642  {
3643  clib_warning ("Can't allocate buffer for Map-Register!");
3644  return 0;
3645  }
3646 
3647  b = vlib_get_buffer (vm, bi);
3648 
3649  /* leave some space for the encap headers */
3651 
3652  lisp_msg_put_map_reply (b, records, nonce, probe_bit);
3653 
3654  /* push outer ip header */
3655  pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst);
3656 
3657  bi_res[0] = bi;
3658  return b;
3659 }
3660 
3661 static int
3662 send_map_reply (lisp_cp_main_t * lcm, u32 mi, ip_address_t * dst,
3663  u8 probe_bit, u64 nonce, u16 dst_port,
3664  ip_address_t * probed_loc)
3665 {
3666  ip_address_t src;
3667  u32 bi;
3668  vlib_buffer_t *b;
3669  vlib_frame_t *f;
3670  u32 next_index, *to_next;
3671  mapping_t *records = 0, *m;
3672 
3673  m = pool_elt_at_index (lcm->mapping_pool, mi);
3674  if (!m)
3675  return -1;
3676 
3677  vec_add1 (records, m[0]);
3678  add_locators (lcm, &records[0], m->locator_set_index, probed_loc);
3679  memset (&src, 0, sizeof (src));
3680 
3681  if (!ip_fib_get_first_egress_ip_for_dst (lcm, dst, &src))
3682  {
3683  clib_warning ("can't find inteface address for %U", format_ip_address,
3684  dst);
3685  return -1;
3686  }
3687 
3688  b = build_map_reply (lcm, &src, dst, nonce, probe_bit, records, dst_port,
3689  &bi);
3690  if (!b)
3691  return -1;
3692  free_map_register_records (records);
3693 
3694  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
3695  next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ?
3696  ip4_lookup_node.index : ip6_lookup_node.index;
3697 
3698  f = vlib_get_frame_to_node (lcm->vlib_main, next_index);
3699 
3700  /* Enqueue the packet */
3701  to_next = vlib_frame_vector_args (f);
3702  to_next[0] = bi;
3703  f->n_vectors = 1;
3704  vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
3705  return 0;
3706 }
3707 
3708 static void
3710 {
3711  const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
3712  if (start < 0 && start < -sizeof (b->pre_data))
3713  {
3714  *ip_hdr = 0;
3715  return;
3716  }
3717 
3718  *ip_hdr = b->data + start;
3719  if ((u8 *) * ip_hdr > (u8 *) vlib_buffer_get_current (b))
3720  *ip_hdr = 0;
3721 }
3722 
3723 void
3725  lisp_cp_main_t * lcm, vlib_buffer_t * b)
3726 {
3727  u8 *ip_hdr = 0;
3728  ip_address_t *dst_loc = 0, probed_loc, src_loc;
3729  mapping_t m;
3730  map_request_hdr_t *mreq_hdr;
3731  gid_address_t src, dst;
3732  u64 nonce;
3733  u32 i, len = 0, rloc_probe_recv = 0;
3734  gid_address_t *itr_rlocs = 0;
3735 
3736  mreq_hdr = vlib_buffer_get_current (b);
3737  if (!MREQ_SMR (mreq_hdr) && !MREQ_RLOC_PROBE (mreq_hdr))
3738  {
3739  clib_warning
3740  ("Only SMR Map-Requests and RLOC probe supported for now!");
3741  return;
3742  }
3743 
3744  vlib_buffer_pull (b, sizeof (*mreq_hdr));
3745  nonce = MREQ_NONCE (mreq_hdr);
3746 
3747  /* parse src eid */
3748  len = lisp_msg_parse_addr (b, &src);
3749  if (len == ~0)
3750  return;
3751 
3752  len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs,
3753  MREQ_ITR_RLOC_COUNT (mreq_hdr) + 1);
3754  if (len == ~0)
3755  goto done;
3756 
3757  /* parse eid records and send SMR-invoked map-requests */
3758  for (i = 0; i < MREQ_REC_COUNT (mreq_hdr); i++)
3759  {
3760  memset (&dst, 0, sizeof (dst));
3761  len = lisp_msg_parse_eid_rec (b, &dst);
3762  if (len == ~0)
3763  {
3764  clib_warning ("Can't parse map-request EID-record");
3765  goto done;
3766  }
3767 
3768  if (MREQ_SMR (mreq_hdr))
3769  {
3770  /* send SMR-invoked map-requests */
3771  queue_map_request (&dst, &src, 1 /* invoked */ , 0 /* resend */ );
3772  }
3773  else if (MREQ_RLOC_PROBE (mreq_hdr))
3774  {
3775  find_ip_header (b, &ip_hdr);
3776  if (!ip_hdr)
3777  {
3778  clib_warning ("Cannot find the IP header!");
3779  goto done;
3780  }
3781  rloc_probe_recv++;
3782  memset (&m, 0, sizeof (m));
3783  u32 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
3784 
3785  // TODO: select best locator; for now use the first one
3786  dst_loc = &gid_address_ip (&itr_rlocs[0]);
3787 
3788  /* get src/dst IP addresses */
3789  get_src_and_dst_ip (ip_hdr, &src_loc, &probed_loc);
3790 
3791  // TODO get source port from buffer
3792  u16 src_port = LISP_CONTROL_PORT;
3793 
3794  send_map_reply (lcm, mi, dst_loc, 1 /* probe-bit */ , nonce,
3795  src_port, &probed_loc);
3796  }
3797  }
3798 
3799 done:
3801  LISP_CP_INPUT_ERROR_RLOC_PROBE_REQ_RECEIVED,
3802  rloc_probe_recv);
3803  vec_free (itr_rlocs);
3804 }
3805 
3808 {
3809  locator_t probed;
3810  gid_address_t deid;
3811  void *h;
3812  u32 i, len = 0;
3813  mapping_t m;
3814  map_reply_hdr_t *mrep_hdr;
3816 
3817  a = map_record_args_get ();
3818  memset (a, 0, sizeof (*a));
3819 
3820  locator_t *locators;
3821 
3822  mrep_hdr = vlib_buffer_get_current (b);
3823  a->nonce = MREP_NONCE (mrep_hdr);
3824  a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr);
3825  if (!vlib_buffer_has_space (b, sizeof (*mrep_hdr)))
3826  {
3827  clib_mem_free (a);
3828  return 0;
3829  }
3830  vlib_buffer_pull (b, sizeof (*mrep_hdr));
3831 
3832  for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
3833  {
3834  memset (&m, 0, sizeof (m));
3835  locators = 0;
3836  h = vlib_buffer_get_current (b);
3837 
3838  m.ttl = clib_net_to_host_u32 (MAP_REC_TTL (h));
3839  m.action = MAP_REC_ACTION (h);
3840  m.authoritative = MAP_REC_AUTH (h);
3841 
3842  len = lisp_msg_parse_mapping_record (b, &deid, &locators, &probed);
3843  if (len == ~0)
3844  {
3845  clib_warning ("Failed to parse mapping record!");
3847  return 0;
3848  }
3849 
3850  m.locators = locators;
3851  gid_address_copy (&m.eid, &deid);
3852  vec_add1 (a->mappings, m);
3853  }
3854  return a;
3855 }
3856 
3857 static void
3859 {
3860  vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (*a));
3861 }
3862 
3863 static void
3865 {
3866  vl_api_rpc_call_main_thread (process_map_notify, (u8 *) a, sizeof (a[0]));
3867 }
3868 
3869 static uword
3871  vlib_frame_t * from_frame)
3872 {
3873  u32 n_left_from, *from, *to_next_drop, rloc_probe_rep_recv = 0,
3874  map_notifies_recv = 0;
3875  lisp_msg_type_e type;
3878 
3879  from = vlib_frame_vector_args (from_frame);
3880  n_left_from = from_frame->n_vectors;
3881 
3882 
3883  while (n_left_from > 0)
3884  {
3885  u32 n_left_to_next_drop;
3886 
3888  to_next_drop, n_left_to_next_drop);
3889  while (n_left_from > 0 && n_left_to_next_drop > 0)
3890  {
3891  u32 bi0;
3892  vlib_buffer_t *b0;
3893 
3894  bi0 = from[0];
3895  from += 1;
3896  n_left_from -= 1;
3897  to_next_drop[0] = bi0;
3898  to_next_drop += 1;
3899  n_left_to_next_drop -= 1;
3900 
3901  b0 = vlib_get_buffer (vm, bi0);
3902 
3903  type = lisp_msg_type (vlib_buffer_get_current (b0));
3904  switch (type)
3905  {
3906  case LISP_MAP_REPLY:
3907  a = parse_map_reply (b0);
3908  if (a)
3909  {
3910  if (a->is_rloc_probe)
3911  rloc_probe_rep_recv++;
3913  }
3914  break;
3915  case LISP_MAP_REQUEST:
3916  process_map_request (vm, node, lcm, b0);
3917  break;
3918  case LISP_MAP_NOTIFY:
3919  a = parse_map_notify (b0);
3920  if (a)
3921  {
3922  map_notifies_recv++;
3924  }
3925  break;
3926  default:
3927  clib_warning ("Unsupported LISP message type %d", type);
3928  break;
3929  }
3930 
3931  b0->error = node->errors[LISP_CP_INPUT_ERROR_DROP];
3932 
3934  {
3935 
3936  }
3937  }
3938 
3940  n_left_to_next_drop);
3941  }
3943  LISP_CP_INPUT_ERROR_RLOC_PROBE_REP_RECEIVED,
3944  rloc_probe_rep_recv);
3946  LISP_CP_INPUT_ERROR_MAP_NOTIFIES_RECEIVED,
3947  map_notifies_recv);
3948  return from_frame->n_vectors;
3949 }
3950 
3951 /* *INDENT-OFF* */
3953  .function = lisp_cp_input,
3954  .name = "lisp-cp-input",
3955  .vector_size = sizeof (u32),
3956  .format_trace = format_lisp_cp_input_trace,
3957  .type = VLIB_NODE_TYPE_INTERNAL,
3958 
3959  .n_errors = LISP_CP_INPUT_N_ERROR,
3960  .error_strings = lisp_cp_input_error_strings,
3961 
3962  .n_next_nodes = LISP_CP_INPUT_N_NEXT,
3963 
3964  .next_nodes = {
3965  [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
3966  },
3967 };
3968 /* *INDENT-ON* */
3969 
3970 clib_error_t *
3972 {
3974  clib_error_t *error = 0;
3976  u32 num_threads;
3977 
3978  if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
3979  return error;
3980 
3981  lcm->im4 = &ip4_main;
3982  lcm->im6 = &ip6_main;
3983  lcm->vlib_main = vm;
3984  lcm->vnet_main = vnet_get_main ();
3985  lcm->mreq_itr_rlocs = ~0;
3986  lcm->lisp_pitr = 0;
3987  lcm->flags = 0;
3988  memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver));
3989 
3991  lcm->do_map_resolver_election = 1;
3993 
3994  num_threads = 1 /* main thread */ + vtm->n_threads;
3995  vec_validate (lcm->map_records_args_pool, num_threads - 1);
3996 
3997  /* default vrf mapped to vni 0 */
3998  hash_set (lcm->table_id_by_vni, 0, 0);
3999  hash_set (lcm->vni_by_table_id, 0, 0);
4000 
4001  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
4002  lisp_cp_input_node.index, 1 /* is_ip4 */ );
4003  udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6,
4004  lisp_cp_input_node.index, 0 /* is_ip4 */ );
4005 
4006  u64 now = clib_cpu_time_now ();
4008  lcm->nsh_map_index = ~0;
4009  return 0;
4010 }
4011 
4012 static int
4014  lisp_api_stats_t * stat, lisp_stats_key_t * key,
4015  u32 stats_index)
4016 {
4017  vlib_counter_t v;
4019  lisp_gpe_fwd_entry_key_t fwd_key;
4020  const lisp_gpe_tunnel_t *lgt;
4021  fwd_entry_t *fe;
4022 
4023  memset (stat, 0, sizeof (*stat));
4024  memset (&fwd_key, 0, sizeof (fwd_key));
4025 
4027  ASSERT (fe != 0);
4028 
4029  gid_to_dp_address (&fe->reid, &stat->deid);
4030  gid_to_dp_address (&fe->leid, &stat->seid);
4031  stat->vni = gid_address_vni (&fe->reid);
4032 
4033  lgt = lisp_gpe_tunnel_get (key->tunnel_index);
4034  stat->loc_rloc = lgt->key->lcl;
4035  stat->rmt_rloc = lgt->key->rmt;
4036 
4037  vlib_get_combined_counter (cm, stats_index, &v);
4038  stat->counters = v;
4039  return 1;
4040 }
4041 
4044 {
4047  lisp_api_stats_t *stats = 0, stat;
4048  lisp_stats_key_t *key;
4049  u32 index;
4050 
4051  /* *INDENT-OFF* */
4052  hash_foreach_mem (key, index, lgm->lisp_stats_index_by_key,
4053  {
4054  if (lisp_stats_api_fill (lcm, lgm, &stat, key, index))
4055  vec_add1 (stats, stat);
4056  });
4057  /* *INDENT-ON* */
4058 
4059  return stats;
4060 }
4061 
4062 static void *
4064 {
4065  map_request_args_t *a = arg;
4067 
4068  if (a->is_resend)
4070  else
4071  send_encapsulated_map_request (lcm, &a->seid, &a->deid, a->smr_invoked);
4072 
4073  return 0;
4074 }
4075 
4076 static int
4078  u8 smr_invoked, u8 is_resend)
4079 {
4081 
4082  a.is_resend = is_resend;
4083  gid_address_copy (&a.seid, seid);
4084  gid_address_copy (&a.deid, deid);
4085  a.smr_invoked = smr_invoked;
4086 
4088  (u8 *) & a, sizeof (a));
4089  return 0;
4090 }
4091 
4092 /**
4093  * Take an action with a pending map request depending on expiration time
4094  * and re-try counters.
4095  */
4096 static void
4098 {
4100  lisp_msmr_t *mr;
4101 
4102  if (r->time_to_expire - dt < 0)
4103  /* it's time to decide what to do with this pending request */
4104  {
4105  if (r->retries_num >= NUMBER_OF_RETRIES)
4106  /* too many retries -> assume current map resolver is not available */
4107  {
4109  if (!mr)
4110  {
4111  clib_warning ("Map resolver %U not found - probably deleted "
4112  "by the user recently.", format_ip_address,
4113  &lcm->active_map_resolver);
4114  }
4115  else
4116  {
4117  clib_warning ("map resolver %U is unreachable, ignoring",
4119 
4120  /* mark current map resolver unavailable so it won't be
4121  * selected next time */
4122  mr->is_down = 1;
4123  mr->last_update = vlib_time_now (lcm->vlib_main);
4124  }
4125 
4127  elect_map_resolver (lcm);
4128 
4129  /* try to find a next eligible map resolver and re-send */
4130  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4131  1 /* resend */ );
4132  }
4133  else
4134  {
4135  /* try again */
4136  queue_map_request (&r->src, &r->dst, r->is_smr_invoked,
4137  1 /* resend */ );
4138  r->retries_num++;
4140  }
4141  }
4142  else
4143  r->time_to_expire -= dt;
4144 }
4145 
4146 static void
4148 {
4149  u64 *nonce;
4150  pending_map_request_t *pmr;
4151  u32 *to_be_removed = 0, *pmr_index;
4152 
4153  /* *INDENT-OFF* */
4155  ({
4156  if (pmr->to_be_removed)
4157  {
4158  clib_fifo_foreach (nonce, pmr->nonces, ({
4159  hash_unset (lcm->pending_map_requests_by_nonce, nonce[0]);
4160  }));
4161 
4162  vec_add1 (to_be_removed, pmr - lcm->pending_map_requests_pool);
4163  }
4164  }));
4165  /* *INDENT-ON* */
4166 
4167  vec_foreach (pmr_index, to_be_removed)
4168  pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]);
4169 
4170  vec_free (to_be_removed);
4171 }
4172 
4173 static void
4175 {
4176  static f64 time_left = RLOC_PROBING_INTERVAL;
4177 
4178  if (!lcm->is_enabled || !lcm->rloc_probing)
4179  return;
4180 
4181  time_left -= dt;
4182  if (time_left <= 0)
4183  {
4184  time_left = RLOC_PROBING_INTERVAL;
4185  send_rloc_probes (lcm);
4186  }
4187 }
4188 
4189 static void
4191 {
4192  static f64 time_left = QUICK_MAP_REGISTER_INTERVAL;
4193  static u64 mreg_sent_counter = 0;
4194 
4195  if (!lcm->is_enabled || !lcm->map_registering)
4196  return;
4197 
4198  time_left -= dt;
4199  if (time_left <= 0)
4200  {
4201  if (mreg_sent_counter >= QUICK_MAP_REGISTER_MSG_COUNT)
4202  time_left = MAP_REGISTER_INTERVAL;
4203  else
4204  {
4205  mreg_sent_counter++;
4206  time_left = QUICK_MAP_REGISTER_INTERVAL;
4207  }
4208  send_map_register (lcm, 1 /* want map notify */ );
4209  }
4210 }
4211 
4212 static uword
4215 {
4216  u32 *expired = 0;
4217  f64 period = 2.0;
4218  pending_map_request_t *pmr;
4220 
4221  while (1)
4222  {
4224 
4225  /* currently no signals are expected - just wait for clock */
4226  (void) vlib_process_get_events (vm, 0);
4227 
4228  /* *INDENT-OFF* */
4230  ({
4231  if (!pmr->to_be_removed)
4232  update_pending_request (pmr, period);
4233  }));
4234  /* *INDENT-ON* */
4235 
4237 
4238  update_map_register (lcm, period);
4239  update_rloc_probing (lcm, period);
4240 
4241  u64 now = clib_cpu_time_now ();
4242 
4243  expired = timing_wheel_advance (&lcm->wheel, now, expired, 0);
4244  if (vec_len (expired) > 0)
4245  {
4246  u32 *mi = 0;
4247  vec_foreach (mi, expired)
4248  {
4249  remove_expired_mapping (lcm, mi[0]);
4250  }
4251  _vec_len (expired) = 0;
4252  }
4253  }
4254 
4255  /* unreachable */
4256  return 0;
4257 }
4258 
4261 {
4263 
4264  if (vnet_lisp_enable_disable_status () == 0)
4265  return VNET_API_ERROR_LISP_DISABLED;
4266 
4267  if (enable)
4268  lcm->flags |= LISP_FLAG_STATS_ENABLED;
4269  else
4270  lcm->flags &= ~LISP_FLAG_STATS_ENABLED;
4271 
4272  return 0;
4273 }
4274 
4275 u8
4277 {
4279 
4280  if (vnet_lisp_enable_disable_status () == 0)
4281  return VNET_API_ERROR_LISP_DISABLED;
4282 
4283  return lcm->flags & LISP_FLAG_STATS_ENABLED;
4284 }
4285 
4286 /* *INDENT-OFF* */
4288  .function = send_map_resolver_service,
4289  .type = VLIB_NODE_TYPE_PROCESS,
4290  .name = "lisp-retry-service",
4291  .process_log2_n_stack_bytes = 16,
4292 };
4293 /* *INDENT-ON* */
4294 
4296 
4297 /*
4298  * fd.io coding-style-patch-verification: ON
4299  *
4300  * Local Variables:
4301  * eval: (c-set-style "gnu")
4302  * End:
4303  */
void lisp_gpe_tenant_l2_iface_unlock(u32 vni)
Release the lock held on the tenant&#39;s L3 interface.
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
#define MREQ_SMR(h_)
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:179
#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:169
const lisp_gpe_tunnel_t * lisp_gpe_tunnel_get(index_t lgti)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:567
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
#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:3870
#define gid_address_ip_version(_a)
Definition: lisp_types.h:261
#define gid_address_arp_bd(_a)
Definition: lisp_types.h:280
#define vec_foreach_index(var, v)
Iterate over vector indices.
map_records_arg_t ** map_records_args_pool
Per thread pool of records shared with thread0.
Definition: control.h:238
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:214
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:2627
vnet_api_error_t
Definition: api_errno.h:117
#define hash_set(h, key, value)
Definition: hash.h:254
l2_input_config_t * configs
Definition: l2_input.h:66
static u8 * vlib_buffer_get_tail(vlib_buffer_t *b)
Get pointer to the end of buffer&#39;s data.
Definition: buffer.h:260
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define clib_fifo_head(v)
Definition: fifo.h:254
#define gid_address_type(_a)
Definition: lisp_types.h:257
#define CLIB_UNUSED(x)
Definition: clib.h:79
u8 timer_set
Definition: lisp_types.h:366
vlib_node_registration_t lisp_cp_lookup_ip4_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node)
Definition: control.c:3201
map_records_arg_t * parse_map_reply(vlib_buffer_t *b)
Definition: control.c:3807
static void mapping_start_expiration_timer(lisp_cp_main_t *lcm, u32 mi, f64 expiration_time)
Definition: control.c:3340
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:699
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
void process_map_request(vlib_main_t *vm, vlib_node_runtime_t *node, lisp_cp_main_t *lcm, vlib_buffer_t *b)
Definition: control.c:3724
gid_address_t deid
Definition: control.c:47
lisp_api_l2_arp_entry_t * vnet_lisp_l2_arp_entries_get_by_bd(u32 bd)
Definition: control.c:882
#define SHA256_AUTH_DATA_LEN
Definition: lisp_types.h:23
lisp_cp_lookup_next_t
Definition: control.c:2128
ip4_address_t src_address
Definition: ip4_packet.h:164
static uword clib_fifo_elts(void *v)
Definition: fifo.h:66
ip_address_t active_map_resolver
Definition: control.h:195
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define RLOC_PROBING_INTERVAL
Definition: control.h:28
u32 bd_id
bridge domain id
Definition: lisp_gpe.h:269
lisp_msmr_t * map_resolvers
Definition: control.h:186
#define MAP_REC_TTL(h)
gid_address_t dst_eid
Definition: control.c:3304
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:171
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:162
#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:2268
locator_pair_t * locator_pairs
Definition: control.h:58
uword * table_id_by_vni
Definition: control.h:203
static void queue_map_notify_for_processing(map_records_arg_t *a)
Definition: control.c:3864
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.
clib_error_t * vnet_lisp_gpe_enable_disable(vnet_lisp_gpe_enable_disable_args_t *a)
Enable/disable LISP-GPE.
Definition: lisp_gpe.c:193
#define NULL
Definition: clib.h:55
#define foreach_lisp_cp_input_error
Definition: control.c:3281
static uword lisp_cp_lookup_nsh(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3193
u32 * local_mappings_indexes
Definition: control.h:167
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:192
u32 vnet_lisp_gpe_add_nsh_iface(lisp_gpe_main_t *lgm)
Add LISP-GPE NSH interface.
Definition: interface.c:745
locator_t * locator_pool
Definition: control.h:152
f64 clocks_per_second
Definition: time.h:53
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
dp_address_t seid
Definition: lisp_gpe.h:103
#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:118
u8 vnet_lisp_get_map_request_mode(void)
Definition: control.c:52
static int elect_map_resolver(lisp_cp_main_t *lcm)
Definition: control.c:2330
vlib_node_registration_t lisp_cp_lookup_nsh_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_nsh_node)
Definition: control.c:3261
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:141
ip_address_t loc_rloc
Definition: lisp_gpe.h:104
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
static uword lisp_cp_output(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:2515
Definition: control.h:53
static u64 clib_cpu_time_now(void)
Definition: time.h:73
int vnet_lisp_add_del_l2_arp_entry(gid_address_t *key, u8 *mac, u8 is_add)
Definition: control.c:897
Combined counter to hold both packets and byte differences.
Definition: counter.h:139
void gid_dict_foreach_l2_arp_entry(gid_dictionary_t *db, void(*cb)(BVT(clib_bihash_kv)*kvp, void *arg), void *ht)
LISP-GPE definitions.
lisp_cp_input_next_t
Definition: control.c:37
#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:174
#define hash_set_mem(h, key, value)
Definition: hash.h:274
static char * lisp_cp_input_error_strings[]
Definition: control.c:3288
ip_lookup_main_t lookup_main
Definition: ip4.h:85
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 nsh_map_index
Definition: control.h:223
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
void vnet_lisp_gpe_add_fwd_counters(vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u32 fwd_entry_index)
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:4147
void ip_address_copy(ip_address_t *dst, const ip_address_t *src)
Definition: lisp_types.c:878
ip_address_t address
Definition: control.h:78
vnet_api_error_t vnet_lisp_stats_enable_disable(u8 enable)
Definition: control.c:4260
void ip_address_set(ip_address_t *dst, const void *src, u8 version)
Definition: lisp_types.c:900
static lisp_msmr_t * get_map_server(ip_address_t *a)
Definition: control.c:617
void timing_wheel_insert(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
Definition: timing_wheel.c:294
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:419
uword * vni_by_table_id
Definition: control.h:204
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
ip6_address_t src_address
Definition: ip6_packet.h:341
u8 vnet_lisp_stats_enable_disable_state(void)
Definition: control.c:4276
#define fid_addr_mac(_a)
Definition: lisp_types.h:133
void gid_dictionary_init(gid_dictionary_t *db)
u8 vnet_lisp_map_register_state_get(void)
Definition: control.c:417
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:3662
void gid_address_from_ip(gid_address_t *g, ip_address_t *ip)
Definition: lisp_types.c:853
int vnet_lisp_set_map_request_mode(u8 mode)
Definition: control.c:1384
static int is_local_ip(lisp_cp_main_t *lcm, ip_address_t *addr)
Definition: control.c:1112
static void clean_locator_to_locator_set(lisp_cp_main_t *lcm, u32 lsi)
Definition: control.c:1567
int vnet_lisp_add_del_adjacency(vnet_lisp_add_del_adjacency_args_t *a)
Adds adjacency or removes forwarding entry associated to remote mapping.
Definition: control.c:1323
static char * lisp_cp_output_error_strings[]
Definition: control.c:2500
#define NUMBER_OF_RETRIES
Definition: control.h:23
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:479
#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:2422
lisp_msmr_t * map_servers
Definition: control.h:189
#define MREQ_NONCE(h_)
static lisp_gpe_main_t * vnet_lisp_gpe_get_main()
Definition: lisp_gpe.h:183
static void reset_pending_mr_counters(pending_map_request_t *r)
Definition: control.c:2323
u32 ** locator_to_locator_sets
Definition: control.h:158
vlib_main_t * vlib_main
Definition: control.h:243
u32 gid_dictionary_add_del(gid_dictionary_t *db, gid_address_t *key, u64 value, u8 is_add)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
ethernet_arp_ip4_over_ethernet_address_t ip4_over_ethernet[2]
Definition: arp_packet.h:136
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u32 fwd_entry_index
Definition: lisp_gpe.h:95
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:542
#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:191
u8 * key
Definition: lisp_types.h:364
gid_address_t * eids_to_be_deleted
Definition: control.c:1019
ip4_address_t dst_address
Definition: ip4_packet.h:164
ip_address_t rmt_rloc
Definition: lisp_gpe.h:105
u8 dst_address[6]
Definition: packet.h:53
static BVT(clib_bihash)
Definition: adj_nbr.c:26
vlib_combined_counter_main_t counters
Definition: lisp_gpe.h:164
static int dp_add_fwd_entry_from_mt(u32 si, u32 di)
Definition: control.c:573
LISP-GPE fwd entry key.
u8 is_add
Definition: lisp_gpe.h:233
int i32
Definition: types.h:81
#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:274
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
void vnet_lisp_gpe_del_fwd_counters(vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u32 fwd_entry_index)
Aggregrate type for a prefix.
Definition: fib_types.h:160
u32 * fwd_entry_by_mapping_index
Definition: control.h:171
#define clib_error_return(e, args...)
Definition: error.h:99
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:144
static mapping_t * get_mapping(lisp_cp_main_t *lcm, gid_address_t *e)
Definition: control.c:3481
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:936
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:300
#define vec_end(v)
End (last data address) of vector.
uword * bd_id_by_vni
Definition: control.h:207
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:257
u16 fp_len
The mask length.
Definition: fib_types.h:164
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static void * send_map_request_thread_fn(void *arg)
Definition: control.c:4063
uword * vni_by_bd_id
Definition: control.h:208
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:226
gid_address_t src
Definition: control.h:44
u32 petr_map_index
Proxy ETR map index.
Definition: control.h:217
#define ip_addr_version(_a)
Definition: lisp_types.h:56
ip6_main_t * im6
Definition: control.h:242
void gid_to_dp_address(gid_address_t *g, dp_address_t *d)
Definition: lisp_types.c:598
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:4097
clib_error_t * vnet_lisp_enable_disable(u8 is_enable)
Definition: control.c:1981
vlib_node_registration_t lisp_cp_lookup_ip6_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node)
Definition: control.c:3221
static void add_locators(lisp_cp_main_t *lcm, mapping_t *m, u32 locator_set_index, ip_address_t *probed_loc)
Definition: control.c:2356
Definition: fib_entry.h:238
void vnet_lisp_gpe_del_nsh_iface(lisp_gpe_main_t *lgm)
Del LISP-GPE NSH interface.
Definition: interface.c:785
#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:1106
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:1456
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
u8 vnet_lisp_rloc_probe_state_get(void)
Definition: control.c:424
static void queue_map_reply_for_processing(map_records_arg_t *a)
Definition: control.c:3858
#define hash_unset_mem(h, key)
Definition: hash.h:280
Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels.
lisp_cp_lookup_error_t
Definition: control.c:2120
u8 do_map_resolver_election
Definition: control.h:197
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
u32 table_id
table (vrf) id
Definition: lisp_gpe.h:266
static void * vlib_buffer_make_headroom(vlib_buffer_t *b, u8 size)
Make head room, typically for packet headers.
Definition: buffer.h:300
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:183
void gid_dict_foreach_subprefix(gid_dictionary_t *db, gid_address_t *eid, foreach_subprefix_match_cb_t cb, void *arg)
#define gid_address_mac(_a)
Definition: lisp_types.h:263
static u16 auth_data_len_by_key_id(lisp_key_type_t key_id)
Definition: control.c:59
int get_mr_and_local_iface_ip(lisp_cp_main_t *lcm, ip_address_t *mr_ip, ip_address_t *sloc)
Definition: control.c:2155
#define v
Definition: acl.c:320
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:694
#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:809
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:4287
vlib_node_registration_t lisp_cp_input_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_input_node)
Definition: control.c:3952
#define MNOTIFY_KEY_ID(h_)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define hash_free(h)
Definition: hash.h:286
void gid_address_free(gid_address_t *a)
Definition: lisp_types.c:842
vlib_node_registration_t lisp_cp_lookup_l2_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node)
Definition: control.c:3241
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define gid_address_sd_dst_type(_a)
Definition: lisp_types.h:277
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
static void cleanup(void)
Definition: client.c:90
u8 authoritative
Definition: lisp_types.h:355
lisp_api_stats_t * vnet_lisp_get_stats(void)
Definition: control.c:4043
static void remove_expired_mapping(lisp_cp_main_t *lcm, u32 mi)
Definition: control.c:3321
u32 * local_locator_set_indexes
Definition: control.h:168
#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:3501
uword unformat_gid_address(unformat_input_t *input, va_list *args)
Definition: lisp_types.c:342
gid_address_t reid
Definition: control.h:56
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
u8 * format_gid_address(u8 *s, va_list *args)
Definition: lisp_types.c:258
static uword lisp_cp_lookup_ip4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3172
ip_address_t lcl_loc
Definition: lisp_types.h:376
volatile u8 is_free
Definition: control.h:132
u8 map_request_mode
Definition: control.h:226
static u8 compare_locators(lisp_cp_main_t *lcm, u32 *old_ls_indexes, locator_t *new_locators)
Definition: control.c:993
#define foreach_lisp_cp_lookup_error
Definition: control.c:2109
vlib_node_registration_t lisp_cp_output_node
(constructor) VLIB_REGISTER_NODE (lisp_cp_output_node)
Definition: control.c:2523
u32 node_index
Node index.
Definition: node.h:441
#define MAX_LISP_MSG_ENCAP_LEN
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#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:366
ip_address_t map_resolver_ip
Definition: control.c:2138
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:437
#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:1139
#define clib_fifo_foreach(v, f, body)
Definition: fifo.h:279
static void process_map_notify(map_records_arg_t *a)
Definition: control.c:3463
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:113
u8 map_registering
Definition: control.h:229
static int queue_map_request(gid_address_t *seid, gid_address_t *deid, u8 smr_invoked, u8 is_resend)
Definition: control.c:4077
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1131
static void remove_locator_from_locator_set(locator_set_t *ls, u32 *locit, u32 ls_index, u32 loc_id)
Definition: control.c:1703
#define gid_address_ippref(_a)
Definition: lisp_types.h:258
dp_address_t deid
Definition: lisp_gpe.h:102
lisp_adjacency_t * vnet_lisp_adjacencies_get_by_vni(u32 vni)
Returns vector of adjacencies.
Definition: control.c:595
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1338
u8 is_negative
type of mapping
Definition: lisp_gpe.h:236
static int is_locator_in_locator_set(lisp_cp_main_t *lcm, locator_set_t *ls, locator_t *loc)
Definition: control.c:1627
#define pool_free(p)
Free a pool.
Definition: pool.h:290
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:316
clib_error_t * lisp_cp_init(vlib_main_t *vm)
Definition: control.c:3971
u32 vni
VNI/tenant id in HOST byte order.
Definition: lisp_gpe.h:260
u8 * format_lisp_cp_input_trace(u8 *s, va_list *args)
Definition: control.c:3309
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:3633
static uword lisp_cp_lookup_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3186
uword * pending_map_requests_by_nonce
Definition: control.h:177
static void dp_add_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:431
int vnet_lisp_add_del_mreq_itr_rlocs(vnet_lisp_add_del_mreq_itr_rloc_args_t *a)
Definition: control.c:2078
u16 n_vectors
Definition: node.h:345
vlib_counter_t counters
Definition: lisp_gpe.h:107
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
static lisp_msmr_t * get_map_resolver(ip_address_t *a)
Definition: control.c:633
static void vlib_get_combined_counter(const vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of per-thr...
Definition: counter.h:250
#define MAP_REC_ACTION(h)
int gid_address_cmp(gid_address_t *a1, gid_address_t *a2)
Definition: lisp_types.c:1624
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
#define gid_address_ippref_len(_a)
Definition: lisp_types.h:259
static map_records_arg_t * parse_map_notify(vlib_buffer_t *b)
Definition: control.c:3580
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:1026
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
u32 locator_set_index
Definition: lisp_types.h:348
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:592
void timing_wheel_delete(timing_wheel_t *w, u32 user_data)
Definition: timing_wheel.c:331
u32 locator_cmp(locator_t *l1, locator_t *l2)
Definition: lisp_types.c:1710
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1328
static void update_map_register(lisp_cp_main_t *lcm, f64 dt)
Definition: control.c:4190
int vnet_lisp_map_register_enable_disable(u8 is_enable)
Definition: control.c:1972
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:238
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:3305
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:2542
lisp_key_type_t key_id
Definition: lisp_types.h:365
#define gid_address_nsh_si(_a)
Definition: lisp_types.h:266
#define vec_is_equal(v1, v2)
Compare two vectors, not NULL-pointer tolerant.
Definition: vec.h:910
void * ip_interface_get_first_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 version)
Definition: control.c:110
enum fib_entry_flag_t_ fib_entry_flag_t
lisp_gpe_tunnel_key_t * key
RLOC pair and rloc fib_index.
#define fid_addr_ippref(_a)
Definition: lisp_types.h:130
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:2023
#define MAX_VALUE_U24
Definition: control.c:31
timing_wheel_t wheel
Definition: control.h:235
Definition: control.c:557
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:733
static uword send_map_resolver_service(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: control.c:4213
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:1012
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:255
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:122
int vnet_lisp_add_del_map_server(ip_address_t *addr, u8 is_add)
Definition: control.c:649
#define ASSERT(truth)
#define fid_addr_type(_a)
Definition: lisp_types.h:135
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:144
#define GID_LOOKUP_MISS
static int send_rloc_probes(lisp_cp_main_t *lcm)
Definition: control.c:2580
int vnet_lisp_clear_all_remote_adjacencies(void)
Definition: control.c:1272
ip6_main_t ip6_main
Definition: ip6_forward.c:2926
ip_lookup_main_t lookup_main
Definition: ip6.h:148
#define gid_address_sd_dst(_a)
Definition: lisp_types.h:275
#define MAP_REGISTER_INTERVAL
Definition: control.h:37
gid_address_t seid
Definition: control.c:46
static void get_src_and_dst_ip(void *hdr, ip_address_t *src, ip_address_t *dst)
Definition: control.c:2865
clib_error_t * lisp_gpe_init(vlib_main_t *vm)
LISP-GPE init function.
Definition: lisp_gpe.c:592
gid_dictionary_t mapping_index_by_gid
Definition: control.h:143
ip_interface_address_t * ip_interface_get_first_interface_address(ip_lookup_main_t *lm, u32 sw_if_index, u8 loop)
Definition: control.c:95
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:2884
locator_set_t * locator_set_pool
Definition: control.h:155
static void clib_mem_free(void *p)
Definition: mem.h:176
u8 is_static
Definition: lisp_types.h:358
u8 is_src_dst
Definition: lisp_gpe.h:231
static void gid_address_sd_to_flat(gid_address_t *dst, gid_address_t *src, fid_address_t *fid)
Definition: control.c:393
int vnet_lisp_rloc_probe_enable_disable(u8 is_enable)
Definition: control.c:1963
u32 ** locator_set_to_eids
Definition: control.h:164
#define LISP_CONTROL_PORT
static u64 mac_to_u64(u8 *m)
Definition: load_balance.c:901
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:920
gid_address_t rmt_eid
remote eid
Definition: lisp_gpe.h:245
u64 gid_dictionary_lookup(gid_dictionary_t *db, gid_address_t *key)
static void add_l2_arp_entry(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: control.c:868
#define foreach_lisp_cp_output_error
Definition: control.c:2496
#define clib_fifo_free(f)
Definition: fifo.h:257
Definition: control.h:90
fwd_entry_t * fwd_entry_pool
Definition: control.h:174
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:180
int vnet_lisp_add_del_locator_set(vnet_lisp_add_del_locator_set_args_t *a, u32 *ls_result)
Definition: control.c:1823
#define gid_address_ip(_a)
Definition: lisp_types.h:260
Definition: defs.h:47
negative_fwd_actions_e action
action for negative mappings
Definition: lisp_gpe.h:239
#define clib_fifo_add1(f, e)
Definition: fifo.h:192
static u32 lisp_get_bd_from_buffer_eth(vlib_buffer_t *b)
Definition: control.c:2907
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:88
static u8 vlib_buffer_has_space(vlib_buffer_t *b, word l)
Check if there is enough space in buffer to advance.
Definition: buffer.h:215
#define gid_address_vni(_a)
Definition: lisp_types.h:267
#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:2923
#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:2438
static uword * get_locator_set_index(vnet_lisp_add_del_locator_set_args_t *a, uword *p)
Definition: control.c:1606
void locator_free(locator_t *l)
Definition: lisp_types.c:1728
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:1066
#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:2114
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:219
#define GID_LOOKUP_MISS_L2
static void dp_del_fwd_entry(lisp_cp_main_t *lcm, u32 src_map_index, u32 dst_map_index)
Definition: control.c:263
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
#define gid_address_nsh_spi(_a)
Definition: lisp_types.h:265
u32 * vnet_lisp_l2_arp_bds_get(void)
Definition: control.c:851
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:1719
locator_pair_t * locator_pairs
vector of locator pairs
Definition: lisp_gpe.h:248
static mapping_t * lisp_get_petr_mapping(lisp_cp_main_t *lcm)
Definition: control.h:368
mapping_t * mapping_pool
Definition: control.h:146
static int get_egress_map_resolver_ip(lisp_cp_main_t *lcm, ip_address_t *ip)
Definition: control.c:2476
u8 ip_address_max_len(u8 version)
Definition: lisp_types.c:541
uword * locator_set_index_by_name
Definition: control.h:161
int vnet_lisp_nsh_set_locator_set(u8 *locator_set_name, u8 is_add)
Definition: control.c:1405
static map_records_arg_t * map_record_args_get()
Definition: control.c:3562
static gid_address_t * build_itr_rloc_list(lisp_cp_main_t *lcm, locator_set_t *loc_set)
Definition: control.c:2186
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:1487
u32 di
Definition: control.c:560
A collection of combined counters.
Definition: counter.h:180
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:2235
gid_address_t eid
Definition: lisp_types.h:343
gid_address_t address
Definition: lisp_types.h:317
#define hash_get_mem(h, key)
Definition: hash.h:268
void mac_copy(void *dst, void *src)
Definition: lisp_types.c:1043
static void add_l2_arp_bd(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: control.c:843
u32 lisp_msg_parse_eid_rec(vlib_buffer_t *b, gid_address_t *eid)
#define MREG_DATA(h_)
#define vnet_buffer(b)
Definition: buffer.h:304
gid_address_t dst
Definition: control.h:45
static void map_records_arg_free(map_records_arg_t *a)
Definition: control.c:3355
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
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, u16 type)
Definition: control.c:2939
int vnet_lisp_add_del_map_resolver(vnet_lisp_add_del_map_resolver_args_t *a)
Definition: control.c:2030
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void find_ip_header(vlib_buffer_t *b, u8 **ip_hdr)
Definition: control.c:3709
ip_address_t rmt_loc
Definition: lisp_types.h:377
u8 data[0]
Packet data.
Definition: buffer.h:152
#define vec_foreach(var, vec)
Vector iterator.
static void * vlib_buffer_pull(vlib_buffer_t *b, u8 size)
Retrieve bytes from buffer head.
Definition: buffer.h:313
uword * map_register_messages_by_nonce
Definition: control.h:183
static void free_map_register_records(mapping_t *maps)
Definition: control.c:2347
static void update_rloc_probing(lisp_cp_main_t *lcm, f64 dt)
Definition: control.c:4174
lisp_cp_main_t lisp_control_main
Definition: control.c:33
vhost_vring_addr_t addr
Definition: vhost-user.h:82
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:488
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
#define gid_address_arp_ip4(_a)
Definition: lisp_types.h:279
void * process_map_reply(map_records_arg_t *a)
Definition: control.c:3368
gid_address_t dst_eid
Definition: control.c:2137
static int parse_map_records(vlib_buffer_t *b, map_records_arg_t *a, u8 count)
Definition: control.c:3530
u8 ip_version_and_header_length
Definition: ip4_packet.h:132
uword * lisp_stats_index_by_key
Definition: lisp_gpe.h:163
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:172
#define MREP_NONCE(h_)
mapping_t * mappings
Definition: control.h:131
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:418
u32 flags
Definition: vhost-user.h:76
Definition: lisp_types.h:38
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
u32 si
Definition: control.c:559
static void update_fwd_entries_by_locator_set(lisp_cp_main_t *lcm, u8 is_local, u32 ls_index, u8 remove_only)
Definition: control.c:1683
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:245
static const EVP_MD * get_encrypt_fcn(lisp_key_type_t key_id)
Definition: control.c:75
static void * dp_add_fwd_entry_thread_fn(void *arg)
Definition: control.c:564
void build_src_dst(gid_address_t *sd, gid_address_t *src, gid_address_t *dst)
Definition: lisp_types.c:1735
static uword lisp_cp_lookup_ip6(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: control.c:3179
int vnet_lisp_use_petr(ip_address_t *ip, u8 is_add)
Configure Proxy-ETR.
Definition: control.c:1508
static void update_adjacencies_by_map_index(lisp_cp_main_t *lcm, u8 is_local, u32 mapping_index, u8 remove_only)
Definition: control.c:1651
gid_address_t lcl_eid
local eid
Definition: lisp_gpe.h:242
u32 mreq_itr_rlocs
Definition: control.h:200
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:337
#define send_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:2710
vnet_main_t * vnet_main
Definition: control.h:244
#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:3430
A LISP GPE Tunnel.
static mapping_t * build_map_register_record_list(lisp_cp_main_t *lcm)
Definition: control.c:2401
u8 * format_lisp_cp_lookup_trace(u8 *s, va_list *args)
Definition: control.c:2142
ip4_main_t * im4
Definition: control.h:241
gid_address_t leid
Definition: control.h:55
Definition: defs.h:46
lisp_msg_type_e
#define ip_prefix_addr(_a)
Definition: lisp_types.h:71
ip6_address_t dst_address
Definition: ip6_packet.h:341
#define resend_encapsulated_map_request(lcm, seid, deid, smr)
Definition: control.c:2713
lisp_cp_output_error_t
Definition: control.c:2506
#define PENDING_MREQ_EXPIRATION_TIME
Definition: control.h:24
static int lisp_stats_api_fill(lisp_cp_main_t *lcm, lisp_gpe_main_t *lgm, lisp_api_stats_t *stat, lisp_stats_key_t *key, u32 stats_index)
Definition: control.c:4013
locator_t * locators
Definition: lisp_types.h:349
lisp_cp_input_error_t
Definition: control.c:3294
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:3023
int ip_address_cmp(const ip_address_t *ip1, const ip_address_t *ip2)
Definition: lisp_types.c:861
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:252