FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
ip_neighbor.c
Go to the documentation of this file.
1 /*
2  * src/vnet/ip/ip_neighboor.c: ip neighbor generic handling
3  *
4  * Copyright (c) 2018 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vppinfra/llist.h>
19 
24 
25 #include <vnet/ip/ip6_ll_table.h>
26 #include <vnet/fib/fib_table.h>
27 #include <vnet/adj/adj_mcast.h>
28 
29 /** Pool for All IP neighbors */
31 
32 /** protocol specific lists of time sorted neighbors */
34 
35 typedef struct ip_neighbor_elt_t_
36 {
40 
41 /** Pool of linked list elemeents */
43 
44 typedef struct ip_neighbor_db_t_
45 {
46  /** per interface hash */
48  /** per-protocol limit - max number of neighbors*/
50  /** max age of a neighbor before it's forcibly evicted */
52  /** when the limit is reached and new neighbors are created, should
53  * we recycle an old one */
55  /** per-protocol number of elements */
57  /** per-protocol number of elements per-fib-index*/
60 
62 
63 /* DBs of neighbours one per AF */
64 /* *INDENT-OFF* */
65 static ip_neighbor_db_t ip_neighbor_db[IP46_N_TYPES] = {
66  [IP46_TYPE_IP4] = {
67  .ipndb_limit = 50000,
68  /* Default to not aging and not recycling */
69  .ipndb_age = 0,
70  .ipndb_recycle = false,
71  },
72  [IP46_TYPE_IP6] = {
73  .ipndb_limit = 50000,
74  /* Default to not aging and not recycling */
75  .ipndb_age = 0,
76  .ipndb_recycle = false,
77  }
78 };
79 /* *INDENT-ON* */
80 
81 #define IP_NEIGHBOR_DBG(...) \
82  vlib_log_debug (ipn_logger, __VA_ARGS__);
83 
84 #define IP_NEIGHBOR_INFO(...) \
85  vlib_log_notice (ipn_logger, __VA_ARGS__);
86 
89 {
90  if (pool_is_free_index (ip_neighbor_pool, ipni))
91  return (NULL);
92 
93  return (pool_elt_at_index (ip_neighbor_pool, ipni));
94 }
95 
96 static index_t
98 {
99  return (ipn - ip_neighbor_pool);
100 }
101 
102 static bool
104 {
105  return (ipn->ipn_flags & IP_NEIGHBOR_FLAG_DYNAMIC);
106 }
107 
108 const ip46_address_t *
110 {
111  return (&ipn->ipn_key->ipnk_ip);
112 }
113 
114 const mac_address_t *
116 {
117  return (&ipn->ipn_mac);
118 }
119 
120 const u32
122 {
123  return (ipn->ipn_key->ipnk_sw_if_index);
124 }
125 
126 static void
128 {
129  /* new neighbours, are added to the head of the list, since the
130  * list is time sorted, newest first */
131  ip_neighbor_elt_t *elt;
132 
133  if (~0 != ipn->ipn_elt)
134  {
135  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
136 
137  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
138  }
139 }
140 
141 static void
143 {
144  /* new neighbours, are added to the head of the list, since the
145  * list is time sorted, newest first */
146  ip_neighbor_elt_t *elt, *head;
147 
149  ipn->ipn_n_probes = 0;
150 
151  if (ip_neighbor_is_dynamic (ipn))
152  {
153  if (~0 == ipn->ipn_elt)
154  /* first time insertion */
155  pool_get_zero (ip_neighbor_elt_pool, elt);
156  else
157  {
158  /* already inserted - extract first */
159  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
160 
161  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
162  }
163  head = pool_elt_at_index (ip_neighbor_elt_pool,
165  ipn_key->ipnk_type]);
166 
167  elt->ipne_index = ip_neighbor_get_index (ipn);
168  clib_llist_add (ip_neighbor_elt_pool, ipne_anchor, elt, head);
169  ipn->ipn_elt = elt - ip_neighbor_elt_pool;
170  }
171 }
172 
173 static void
175 {
176  vec_validate (ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash,
177  ipn->ipn_key->ipnk_sw_if_index);
178 
179  if (!ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash
180  [ipn->ipn_key->ipnk_sw_if_index])
181  ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash[ipn->
182  ipn_key->ipnk_sw_if_index]
183  = hash_create_mem (0, sizeof (ip_neighbor_key_t), sizeof (index_t));
184 
185  hash_set_mem (ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash
186  [ipn->ipn_key->ipnk_sw_if_index], ipn->ipn_key,
187  ip_neighbor_get_index (ipn));
188 
189  ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_n_elts++;
190 }
191 
192 static void
194 {
195  vec_validate (ip_neighbor_db[key->ipnk_type].ipndb_hash,
196  key->ipnk_sw_if_index);
197 
198  hash_unset_mem (ip_neighbor_db[key->ipnk_type].ipndb_hash
199  [key->ipnk_sw_if_index], key);
200 
201  ip_neighbor_db[key->ipnk_type].ipndb_n_elts--;
202 }
203 
204 static ip_neighbor_t *
206 {
207  uword *p;
208 
209  if (key->ipnk_sw_if_index >=
210  vec_len (ip_neighbor_db[key->ipnk_type].ipndb_hash))
211  return NULL;
212 
213  p =
214  hash_get_mem (ip_neighbor_db[key->ipnk_type].ipndb_hash
215  [key->ipnk_sw_if_index], key);
216 
217  if (p)
218  return ip_neighbor_get (p[0]);
219 
220  return (NULL);
221 }
222 
223 static u8
225 {
226  return (type == IP46_TYPE_IP4 ? 32 : 128);
227 }
228 
229 static void
231 {
232  if (ipn->ipn_key->ipnk_type == IP46_TYPE_IP6 &&
234  {
235  ip6_ll_prefix_t pfx = {
236  .ilp_addr = ipn->ipn_key->ipnk_ip.ip6,
237  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
238  };
239  ipn->ipn_fib_entry_index =
241  }
242  else
243  {
244  fib_protocol_t fproto;
245 
246  fproto = fib_proto_from_ip46 (ipn->ipn_key->ipnk_type);
247 
248  fib_prefix_t pfx = {
250  .fp_proto = fproto,
251  .fp_addr = ipn->ipn_key->ipnk_ip,
252  };
253 
254  ipn->ipn_fib_entry_index =
255  fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
257  fib_proto_to_dpo (fproto),
258  &pfx.fp_addr,
261 
262  vec_validate (ip_neighbor_db
264  fib_index);
265 
266  ip_neighbor_db[ipn->ipn_key->
267  ipnk_type].ipndb_n_elts_per_fib[fib_index]++;
268 
269  if (1 ==
270  ip_neighbor_db[ipn->ipn_key->
271  ipnk_type].ipndb_n_elts_per_fib[fib_index])
272  fib_table_lock (fib_index, fproto, FIB_SOURCE_ADJ);
273  }
274 }
275 
276 static void
278 {
280  {
281  if (ipn->ipn_key->ipnk_type == IP46_TYPE_IP6 &&
283  {
284  ip6_ll_prefix_t pfx = {
285  .ilp_addr = ipn->ipn_key->ipnk_ip.ip6,
286  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
287  };
289  }
290  else
291  {
292  fib_protocol_t fproto;
293 
294  fproto = fib_proto_from_ip46 (ipn->ipn_key->ipnk_type);
295 
296  fib_prefix_t pfx = {
298  .fp_proto = fproto,
299  .fp_addr = ipn->ipn_key->ipnk_ip,
300  };
301 
302  fib_table_entry_path_remove (fib_index,
303  &pfx,
305  fib_proto_to_dpo (fproto),
306  &pfx.fp_addr,
308  ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
309 
310  ip_neighbor_db[ipn->ipn_key->
311  ipnk_type].ipndb_n_elts_per_fib[fib_index]--;
312 
313  if (0 ==
314  ip_neighbor_db[ipn->ipn_key->
315  ipnk_type].ipndb_n_elts_per_fib[fib_index])
316  fib_table_unlock (fib_index, fproto, FIB_SOURCE_ADJ);
317  }
318  }
319 }
320 
321 static void
323 {
326  ipn->
327  ipn_key->ipnk_sw_if_index,
328  adj_get_link_type (ai),
329  ipn->ipn_mac.bytes));
330 }
331 
332 static void
334 {
335  ip_adjacency_t *adj = adj_get (ai);
336 
340  adj->
341  rewrite_header.sw_if_index,
344 }
345 
346 static adj_walk_rc_t
348 {
349  ip_neighbor_t *ipn = ctx;
350 
351  ip_neighbor_mk_complete (ai, ipn);
352 
353  return (ADJ_WALK_RC_CONTINUE);
354 }
355 
356 static adj_walk_rc_t
358 {
360 
361  return (ADJ_WALK_RC_CONTINUE);
362 }
363 
364 static void
366 {
367  IP_NEIGHBOR_DBG ("free: %U", format_ip_neighbor,
368  ip_neighbor_get_index (ipn));
369 
372  &ipn->ipn_key->ipnk_ip,
375  (ipn,
378  ipn->ipn_key->ipnk_sw_if_index));
379 
382  clib_mem_free (ipn->ipn_key);
383 
384  pool_put (ip_neighbor_pool, ipn);
385 }
386 
387 static bool
389 {
390  if (!ip_neighbor_db[type].ipndb_recycle)
391  return false;
392 
393  /* pluck the oldest entry, which is the one from the end of the list */
394  ip_neighbor_elt_t *elt, *head;
395 
396  head =
397  pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[type]);
398 
399  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
400  return (false);
401 
402  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
404 
405  return (true);
406 }
407 
408 static ip_neighbor_t *
411 {
412  ip_neighbor_t *ipn;
413 
414  if (ip_neighbor_db[key->ipnk_type].ipndb_limit &&
415  (ip_neighbor_db[key->ipnk_type].ipndb_n_elts >=
416  ip_neighbor_db[key->ipnk_type].ipndb_limit))
417  {
419  return (NULL);
420  }
421 
422  pool_get_zero (ip_neighbor_pool, ipn);
423 
424  ipn->ipn_key = clib_mem_alloc (sizeof (*ipn->ipn_key));
425  clib_memcpy (ipn->ipn_key, key, sizeof (*ipn->ipn_key));
426 
428  ipn->ipn_flags = flags;
429  ipn->ipn_elt = ~0;
430 
431  mac_address_copy (&ipn->ipn_mac, mac);
432 
433  ip_neighbor_db_add (ipn);
434 
435  /* create the adj-fib. the entry in the FIB table for the peer's interface */
440  ipn->ipn_key->ipnk_sw_if_index));
441 
442  return (ipn);
443 }
444 
445 int
446 ip_neighbor_add (const ip46_address_t * ip,
448  const mac_address_t * mac,
451 {
452  fib_protocol_t fproto;
453  ip_neighbor_t *ipn;
454 
455  /* main thread only */
456  ASSERT (0 == vlib_get_thread_index ());
457 
458  fproto = fib_proto_from_ip46 (type);
459 
460  const ip_neighbor_key_t key = {
461  .ipnk_ip = *ip,
462  .ipnk_sw_if_index = sw_if_index,
463  .ipnk_type = type,
464  };
465 
466  ipn = ip_neighbor_db_find (&key);
467 
468  if (ipn)
469  {
470  IP_NEIGHBOR_DBG ("update: %U, %U",
472  sw_if_index, format_ip46_address, ip, type,
474  mac);
475 
476  /* Refuse to over-write static neighbor entry. */
477  if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
478  (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
479  {
480  /* if MAC address match, still check to send event */
481  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
482  goto check_customers;
483  return -2;
484  }
485 
486  /*
487  * prevent a DoS attack from the data-plane that
488  * spams us with no-op updates to the MAC address
489  */
490  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
491  {
492  ip_neighbor_refresh (ipn);
493  goto check_customers;
494  }
495 
496  mac_address_copy (&ipn->ipn_mac, mac);
497 
498  /* A dynamic entry can become static, but not vice-versa.
499  * i.e. since if it was programmed by the CP then it must
500  * be removed by the CP */
501  if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
502  !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
503  {
507  }
508  }
509  else
510  {
511  IP_NEIGHBOR_INFO ("add: %U, %U",
513  sw_if_index, format_ip46_address, ip, type,
515  mac);
516 
517  ipn = ip_neighbor_alloc (&key, mac, flags);
518 
519  if (NULL == ipn)
520  return VNET_API_ERROR_LIMIT_EXCEEDED;
521  }
522 
523  /* Update time stamp and flags. */
524  ip_neighbor_refresh (ipn);
525 
527  fproto, &ipn->ipn_key->ipnk_ip,
529 
530 check_customers:
531  /* Customer(s) requesting event for this address? */
533 
534  if (stats_index)
535  *stats_index = adj_nbr_find (fproto,
536  fib_proto_to_link (fproto),
537  &ipn->ipn_key->ipnk_ip,
538  ipn->ipn_key->ipnk_sw_if_index);
539  return 0;
540 }
541 
542 int
543 ip_neighbor_del (const ip46_address_t * ip, ip46_type_t type, u32 sw_if_index)
544 {
545  ip_neighbor_t *ipn;
546 
547  /* main thread only */
548  ASSERT (0 == vlib_get_thread_index ());
549 
550  IP_NEIGHBOR_INFO ("delete: %U, %U",
552  sw_if_index, format_ip46_address, ip, type);
553 
554  const ip_neighbor_key_t key = {
555  .ipnk_ip = *ip,
556  .ipnk_sw_if_index = sw_if_index,
557  .ipnk_type = type,
558  };
559 
560  ipn = ip_neighbor_db_find (&key);
561 
562  if (NULL == ipn)
563  return (VNET_API_ERROR_NO_SUCH_ENTRY);
564 
565  ip_neighbor_free (ipn);
566 
567  return (0);
568 }
569 
570 void
572 {
573  ip_neighbor_t *ipn;
574  ip_adjacency_t *adj;
575 
576  adj = adj_get (ai);
577 
579  .ipnk_ip = adj->sub_type.nbr.next_hop,
580  .ipnk_type = fib_proto_to_ip46 (adj->ia_nh_proto),
581  .ipnk_sw_if_index = adj->rewrite_header.sw_if_index,
582  };
583  ipn = ip_neighbor_db_find (&key);
584 
585  switch (adj->lookup_next_index)
586  {
587  case IP_LOOKUP_NEXT_ARP:
588  if (NULL != ipn)
589  {
590  adj_nbr_walk_nh (adj->rewrite_header.sw_if_index,
591  adj->ia_nh_proto,
592  &ipn->ipn_key->ipnk_ip,
594  }
595  else
596  {
597  /*
598  * no matching ARP entry.
599  * construct the rewrite required to for an ARP packet, and stick
600  * that in the adj's pipe to smoke.
601  */
603  (ai,
606  (vnm,
607  adj->rewrite_header.sw_if_index,
610 
611  /*
612  * since the FIB has added this adj for a route, it makes sense it
613  * may want to forward traffic sometime soon. Let's send a
614  * speculative ARP. just one. If we were to do periodically that
615  * wouldn't be bad either, but that's more code than i'm prepared to
616  * write at this time for relatively little reward.
617  */
618  /*
619  * adj_nbr_update_rewrite may actually call fib_walk_sync.
620  * fib_walk_sync may allocate a new adjacency and potentially cause
621  * a realloc for adj_pool. When that happens, adj pointer is no
622  * longer valid here.x We refresh adj pointer accordingly.
623  */
624  adj = adj_get (ai);
625  ip_neighbor_probe (adj);
626  }
627  break;
631  case IP_LOOKUP_NEXT_DROP:
632  case IP_LOOKUP_NEXT_PUNT:
638  case IP_LOOKUP_N_NEXT:
639  ASSERT (0);
640  break;
641  }
642 }
643 
644 void
646 {
647  ip_neighbor_add (&l->ip, l->type, &l->mac, l->sw_if_index,
649 }
650 
651 static clib_error_t *
653  unformat_input_t * input, vlib_cli_command_t * cmd)
654 {
655  ip46_address_t ip = ip46_address_initializer;
657  vnet_main_t *vnm = vnet_get_main ();
659  u32 sw_if_index = ~0;
660  int is_add = 1;
661  int count = 1;
662 
663  flags = IP_NEIGHBOR_FLAG_DYNAMIC;
664 
666  {
667  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
668  if (unformat (input, "%U %U %U",
669  unformat_vnet_sw_interface, vnm, &sw_if_index,
671  unformat_mac_address_t, &mac))
672  ;
673  else if (unformat (input, "delete") || unformat (input, "del"))
674  is_add = 0;
675  else if (unformat (input, "static"))
676  {
677  flags |= IP_NEIGHBOR_FLAG_STATIC;
678  flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
679  }
680  else if (unformat (input, "no-fib-entry"))
682  else if (unformat (input, "count %d", &count))
683  ;
684  else
685  break;
686  }
687 
688  if (sw_if_index == ~0 ||
690  return clib_error_return (0,
691  "specify interface, IP address and MAC: `%U'",
692  format_unformat_error, input);
693 
694  while (count)
695  {
696  if (is_add)
697  ip_neighbor_add (&ip, ip46_address_get_type (&ip), &mac, sw_if_index,
698  flags, NULL);
699  else
700  ip_neighbor_del (&ip, ip46_address_get_type (&ip), sw_if_index);
701 
703  mac_address_increment (&mac);
704 
705  --count;
706  }
707 
708  return NULL;
709 }
710 
711 /* *INDENT-OFF* */
712 /*?
713  * Add or delete IPv4 ARP cache entries.
714  *
715  * @note 'set ip neighbor' options (e.g. delete, static, 'fib-id <id>',
716  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
717  * any order and combination.
718  *
719  * @cliexpar
720  * @parblock
721  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
722  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
723  * @cliexcmd{set ip neighbor GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
724  * @cliexcmd{set ip neighbor delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
725  *
726  * To add or delete an IPv4 ARP cache entry to or from a specific fib
727  * table:
728  * @cliexcmd{set ip neighbor fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
729  * @cliexcmd{set ip neighbor fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
730  *
731  * Add or delete IPv4 static ARP cache entries as follows:
732  * @cliexcmd{set ip neighbor static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
733  * @cliexcmd{set ip neighbor static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
734  *
735  * For testing / debugging purposes, the 'set ip neighbor' command can add or
736  * delete multiple entries. Supply the 'count N' parameter:
737  * @cliexcmd{set ip neighbor count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
738  * @endparblock
739  ?*/
740 VLIB_CLI_COMMAND (ip_neighbor_command, static) = {
741  .path = "set ip neighbor",
742  .short_help =
743  "set ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
744  .function = ip_neighbor_cmd,
745 };
746 VLIB_CLI_COMMAND (ip_neighbor_command2, static) = {
747  .path = "ip neighbor",
748  .short_help =
749  "ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
750  .function = ip_neighbor_cmd,
751 };
752 /* *INDENT-ON* */
753 
754 static int
755 ip_neighbor_sort (void *a1, void *a2)
756 {
757  index_t *ipni1 = a1, *ipni2 = a2;
758  ip_neighbor_t *ipn1, *ipn2;
759  int cmp;
760 
761  ipn1 = ip_neighbor_get (*ipni1);
762  ipn2 = ip_neighbor_get (*ipni2);
763 
765  ipn1->ipn_key->ipnk_sw_if_index,
766  ipn2->ipn_key->ipnk_sw_if_index);
767  if (!cmp)
768  cmp = ip46_address_cmp (&ipn1->ipn_key->ipnk_ip, &ipn2->ipn_key->ipnk_ip);
769  return cmp;
770 }
771 
772 static index_t *
774 {
775  index_t *ipnis = NULL;
776  ip_neighbor_t *ipn;
777 
778  /* *INDENT-OFF* */
779  pool_foreach (ipn, ip_neighbor_pool,
780  ({
781  if (sw_if_index != ~0 &&
782  ipn->ipn_key->ipnk_sw_if_index != sw_if_index &&
783  (IP46_TYPE_ANY == type ||
784  (ipn->ipn_key->ipnk_type == type)))
785  continue;
786  vec_add1 (ipnis, ip_neighbor_get_index(ipn));
787  }));
788 
789  /* *INDENT-ON* */
790 
791  if (ipnis)
793  return ipnis;
794 }
795 
796 static clib_error_t *
798  unformat_input_t * input,
800 {
801  ip_neighbor_elt_t *elt, *head;
802 
803  head = pool_elt_at_index (ip_neighbor_elt_pool,
804  ip_neighbor_list_head[type]);
805 
806 
807  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
808  "Flags", "Ethernet", "Interface");
809 
810  /* *INDENT-OFF*/
811  /* the list is time sorted, newest first, so start from the back
812  * and work forwards. Stop when we get to one that is alive */
813  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
814  ipne_anchor, head, elt,
815  ({
817  }));
818  /* *INDENT-ON*/
819 
820  return (NULL);
821 }
822 
823 static clib_error_t *
825  unformat_input_t * input,
827 {
828  index_t *ipni, *ipnis = NULL;
830 
831  /* Filter entries by interface if given. */
832  sw_if_index = ~0;
834  &sw_if_index);
835 
836  ipnis = ip_neighbor_entries (sw_if_index, type);
837 
838  if (ipnis)
839  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
840  "Flags", "Ethernet", "Interface");
841 
842  vec_foreach (ipni, ipnis)
843  {
844  vlib_cli_output (vm, "%U", format_ip_neighbor, *ipni);
845  }
846  vec_free (ipnis);
847 
848  return (NULL);
849 }
850 
851 static clib_error_t *
853  unformat_input_t * input, vlib_cli_command_t * cmd)
854 {
855  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_ANY));
856 }
857 
858 static clib_error_t *
860  unformat_input_t * input, vlib_cli_command_t * cmd)
861 {
862  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_IP6));
863 }
864 
865 static clib_error_t *
867  unformat_input_t * input, vlib_cli_command_t * cmd)
868 {
869  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_IP4));
870 }
871 
872 static clib_error_t *
874  unformat_input_t * input, vlib_cli_command_t * cmd)
875 {
876  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP6));
877 }
878 
879 static clib_error_t *
881  unformat_input_t * input, vlib_cli_command_t * cmd)
882 {
883  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP4));
884 }
885 
886 /*?
887  * Display all the IP neighbor entries.
888  *
889  * @cliexpar
890  * Example of how to display the IPv4 ARP table:
891  * @cliexstart{show ip neighbor}
892  * Time FIB IP4 Flags Ethernet Interface
893  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
894  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
895  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
896  * Proxy arps enabled for:
897  * Fib_index 0 6.0.0.1 - 6.0.0.11
898  * @cliexend
899  ?*/
900 /* *INDENT-OFF* */
901 VLIB_CLI_COMMAND (show_ip_neighbors_cmd_node, static) = {
902  .path = "show ip neighbors",
903  .function = ip_neighbor_show,
904  .short_help = "show ip neighbors [interface]",
905 };
906 VLIB_CLI_COMMAND (show_ip4_neighbors_cmd_node, static) = {
907  .path = "show ip4 neighbors",
908  .function = ip4_neighbor_show,
909  .short_help = "show ip4 neighbors [interface]",
910 };
911 VLIB_CLI_COMMAND (show_ip6_neighbors_cmd_node, static) = {
912  .path = "show ip6 neighbors",
913  .function = ip6_neighbor_show,
914  .short_help = "show ip6 neighbors [interface]",
915 };
916 VLIB_CLI_COMMAND (show_ip_neighbor_cmd_node, static) = {
917  .path = "show ip neighbor",
918  .function = ip_neighbor_show,
919  .short_help = "show ip neighbor [interface]",
920 };
921 VLIB_CLI_COMMAND (show_ip4_neighbor_cmd_node, static) = {
922  .path = "show ip4 neighbor",
923  .function = ip4_neighbor_show,
924  .short_help = "show ip4 neighbor [interface]",
925 };
926 VLIB_CLI_COMMAND (show_ip6_neighbor_cmd_node, static) = {
927  .path = "show ip6 neighbor",
928  .function = ip6_neighbor_show,
929  .short_help = "show ip6 neighbor [interface]",
930 };
931 VLIB_CLI_COMMAND (show_ip4_neighbor_sorted_cmd_node, static) = {
932  .path = "show ip4 neighbor-sorted",
933  .function = ip4_neighbor_show_sorted,
934  .short_help = "show ip4 neighbor-sorted",
935 };
936 VLIB_CLI_COMMAND (show_ip6_neighbor_sorted_cmd_node, static) = {
937  .path = "show ip6 neighbor-sorted",
938  .function = ip6_neighbor_show_sorted,
939  .short_help = "show ip6 neighbor-sorted",
940 };
941 /* *INDENT-ON* */
942 
943 static ip_neighbor_vft_t ip_nbr_vfts[IP46_N_TYPES];
944 
945 void
947 {
948  ip_nbr_vfts[type] = *vft;
949 }
950 
951 void
952 ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * dst)
953 {
955  adj->rewrite_header.sw_if_index))
956  return;
957 
958  switch (adj->ia_nh_proto)
959  {
960  case FIB_PROTOCOL_IP6:
961  ip6_neighbor_probe_dst (adj, &dst->ip6);
962  break;
963  case FIB_PROTOCOL_IP4:
964  ip4_neighbor_probe_dst (adj, &dst->ip4);
965  break;
966  case FIB_PROTOCOL_MPLS:
967  ASSERT (0);
968  break;
969  }
970 }
971 
972 void
974 {
975  ip_neighbor_probe_dst (adj, &adj->sub_type.nbr.next_hop);
976 }
977 
978 void
981  const ip46_address_t * addr, u32 sw_if_index)
982 {
983  vnet_main_t *vnm = vnet_get_main ();
984 
985  if (type == IP46_TYPE_IP4 || type == IP46_TYPE_BOTH)
986  ip4_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip4 : NULL);
987  if (type == IP46_TYPE_IP6 || type == IP46_TYPE_BOTH)
988  ip6_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip6 : NULL);
989 }
990 
991 void
994 {
996  index_t ipni;
997 
998  if (~0 == sw_if_index)
999  {
1000  uword **hash;
1001 
1002  vec_foreach (hash, ip_neighbor_db[type].ipndb_hash)
1003  {
1004  /* *INDENT-OFF* */
1005  hash_foreach (key, ipni, *hash,
1006  ({
1007  cb (ipni, ctx);
1008  }));
1009  /* *INDENT-ON* */
1010  }
1011  }
1012  else
1013  {
1014  uword *hash;
1015 
1016  if (vec_len (ip_neighbor_db[type].ipndb_hash) <= sw_if_index)
1017  return;
1018  hash = ip_neighbor_db[type].ipndb_hash[sw_if_index];
1019 
1020  /* *INDENT-OFF* */
1021  hash_foreach (key, ipni, hash,
1022  ({
1023  cb (ipni, ctx);
1024  }));
1025  /* *INDENT-ON* */
1026  }
1027 }
1028 
1029 int
1031  const ip4_address_t * start,
1032  const ip4_address_t * end)
1033 {
1034  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_add)
1035  {
1036  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_add
1037  (fib_index, start, end));
1038  }
1039 
1040  return (-1);
1041 }
1042 
1043 int
1045  const ip4_address_t * start,
1046  const ip4_address_t * end)
1047 {
1048  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del)
1049  {
1050  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del
1051  (fib_index, start, end));
1052  }
1053  return -1;
1054 }
1055 
1056 int
1058 {
1059  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable)
1060  {
1061  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable (sw_if_index));
1062  }
1063  return -1;
1064 }
1065 
1066 int
1068 {
1069  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable)
1070  {
1071  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable (sw_if_index));
1072  }
1073  return -1;
1074 }
1075 
1076 int
1078 {
1079  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add)
1080  {
1081  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add (sw_if_index, addr));
1082  }
1083  return -1;
1084 }
1085 
1086 int
1088 {
1089  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del)
1090  {
1091  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del (sw_if_index, addr));
1092  }
1093  return -1;
1094 }
1095 
1096 static void
1098  u32 sw_if_index, uword opaque)
1099 {
1100  ip_neighbor_t *ipn;
1101  adj_index_t ai;
1102 
1103  IP_NEIGHBOR_DBG ("mac-change: %U",
1105  sw_if_index);
1106 
1107  /* *INDENT-OFF* */
1108  pool_foreach (ipn, ip_neighbor_pool,
1109  ({
1110  if (ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1113  &ipn->ipn_key->ipnk_ip,
1115  ipn);
1116  }));
1117  /* *INDENT-ON* */
1118 
1119  ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
1120 
1121  if (ADJ_INDEX_INVALID != ai)
1123 }
1124 
1125 void
1127 {
1128  index_t *ipnis = NULL, *ipni;
1129  ip_neighbor_t *ipn;
1130 
1131  IP_NEIGHBOR_DBG ("populate: %U %U",
1133  sw_if_index, format_ip46_type, type);
1134 
1135  /* *INDENT-OFF* */
1136  pool_foreach (ipn, ip_neighbor_pool,
1137  ({
1138  if (ipn->ipn_key->ipnk_type == type &&
1139  ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1140  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1141  }));
1142  /* *INDENT-ON* */
1143 
1144  vec_foreach (ipni, ipnis)
1145  {
1146  ipn = ip_neighbor_get (*ipni);
1147 
1150  &ipn->ipn_key->ipnk_ip,
1152  }
1153  vec_free (ipnis);
1154 }
1155 
1156 void
1158 {
1159  index_t *ipnis = NULL, *ipni;
1160  ip_neighbor_t *ipn;
1161 
1162  IP_NEIGHBOR_DBG ("flush: %U %U",
1164  sw_if_index, format_ip46_type, type);
1165 
1166  /* *INDENT-OFF* */
1167  pool_foreach (ipn, ip_neighbor_pool,
1168  ({
1169  if (ipn->ipn_key->ipnk_type == type &&
1170  ipn->ipn_key->ipnk_sw_if_index == sw_if_index &&
1171  ip_neighbor_is_dynamic (ipn))
1172  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1173  }));
1174  /* *INDENT-ON* */
1175 
1176  vec_foreach (ipni, ipnis) ip_neighbor_free (ip_neighbor_get (*ipni));
1177  vec_free (ipnis);
1178 }
1179 
1180 /*
1181  * Remove any arp entries associated with the specified interface
1182  */
1183 static clib_error_t *
1186 {
1187  ip46_type_t type;
1188 
1189  IP_NEIGHBOR_DBG ("interface-admin: %U %s",
1191  sw_if_index,
1192  (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ? "up" : "down"));
1193 
1194  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1195  {
1196  FOREACH_IP46_TYPE (type) ip_neighbor_populate (type, sw_if_index);
1197  }
1198  else
1199  {
1200  /* admin down, flush all neighbours */
1201  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, sw_if_index);
1202  }
1203 
1204  return (NULL);
1205 }
1206 
1208 
1209 /*
1210  * Remove any arp entries associated with the specified interface
1211  */
1212 static clib_error_t *
1214  u32 sw_if_index, u32 is_add)
1215 {
1216  IP_NEIGHBOR_DBG ("interface-change: %U %s",
1218  sw_if_index, (is_add ? "add" : "del"));
1219 
1220  if (!is_add && sw_if_index != ~0)
1221  {
1222  ip46_type_t type;
1223 
1224  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, sw_if_index);
1225  }
1226 
1227  return (NULL);
1228 }
1229 
1231 
1233 {
1235  ip46_address_t addr;
1239 
1240 static walk_rc_t
1242 {
1244  ip_neighbor_t *ipn;
1245 
1246  ipn = ip_neighbor_get (ipni);
1247 
1248  ASSERT (ipn->ipn_key->ipnk_type == ctx->type);
1249 
1250  if (IP46_TYPE_IP4 == ctx->type)
1251  {
1253  &ipn->ipn_key->ipnk_ip.ip4,
1254  &ctx->addr.ip4,
1255  ctx->length) &&
1256  ip_neighbor_is_dynamic (ipn))
1257  {
1258  vec_add1 (ctx->ipnis, ip_neighbor_get_index (ipn));
1259  }
1260  }
1261  return (WALK_CONTINUE);
1262 }
1263 
1264 
1265 /*
1266  * callback when an interface address is added or deleted
1267  */
1268 static void
1270  uword opaque,
1271  u32 sw_if_index,
1273  u32 address_length,
1274  u32 if_address_index, u32 is_del)
1275 {
1276  /*
1277  * Flush the ARP cache of all entries covered by the address
1278  * that is being removed.
1279  */
1280  IP_NEIGHBOR_DBG ("addr-%d: %U, %U/%d",
1281  (is_del ? "del" : "add"),
1283  sw_if_index, format_ip4_address, address, address_length);
1284 
1285  if (is_del)
1286  {
1288  .addr.ip4 = *address,
1289  .type = IP46_TYPE_IP4,
1290  .length = address_length,
1291  };
1292  index_t *ipni;
1293 
1294  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1295  ip_neighbor_walk_covered, &ctx);
1296 
1297  vec_foreach (ipni, ctx.ipnis)
1299 
1300  vec_free (ctx.ipnis);
1301  }
1302 }
1303 
1304 /*
1305  * callback when an interface address is added or deleted
1306  */
1307 static void
1309  uword opaque,
1310  u32 sw_if_index,
1312  u32 address_length,
1313  u32 if_address_index, u32 is_del)
1314 {
1315  /*
1316  * Flush the ARP cache of all entries covered by the address
1317  * that is being removed.
1318  */
1319  IP_NEIGHBOR_DBG ("addr-change: %U, %U/%d %s",
1321  sw_if_index, format_ip6_address, address, address_length,
1322  (is_del ? "del" : "add"));
1323 
1324  if (is_del)
1325  {
1327  .addr.ip6 = *address,
1328  .type = IP46_TYPE_IP6,
1329  .length = address_length,
1330  };
1331  index_t *ipni;
1332 
1333  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1334  ip_neighbor_walk_covered, &ctx);
1335 
1336  vec_foreach (ipni, ctx.ipnis)
1338 
1339  vec_free (ctx.ipnis);
1340  }
1341 }
1342 
1344 {
1348 
1349 static walk_rc_t
1351 {
1353  ip_neighbor_t *ipn;
1354 
1355  ipn = ip_neighbor_get (ipni);
1358 
1359  return (WALK_CONTINUE);
1360 }
1361 
1362 static void
1364  uword opaque,
1365  u32 sw_if_index,
1366  u32 new_fib_index, u32 old_fib_index)
1367 {
1369  .old_fib_index = old_fib_index,
1370  .new_fib_index = new_fib_index,
1371  };
1372 
1373  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1375 }
1376 
1377 static void
1379  uword opaque,
1380  u32 sw_if_index,
1381  u32 new_fib_index, u32 old_fib_index)
1382 {
1384  .old_fib_index = old_fib_index,
1385  .new_fib_index = new_fib_index,
1386  };
1387 
1388  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1390 }
1391 
1393 {
1398 
1399 #define IP_NEIGHBOR_PROCESS_SLEEP_LONG (0)
1400 
1403 {
1404  ip_neighbor_t *ipn;
1405  f64 ttl;
1406 
1407  ipn = ip_neighbor_get (ipni);
1408  ttl = now - ipn->ipn_time_last_updated;
1410 
1411  if (ttl > ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age)
1412  {
1413  IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
1414  format_ip_neighbor, ipni, now,
1415  ipn->ipn_time_last_updated,
1416  ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age);
1417  if (ipn->ipn_n_probes > 2)
1418  {
1419  /* 3 strikes and yea-re out */
1420  IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
1421  return (IP_NEIGHBOR_AGE_DEAD);
1422  }
1423  else
1424  {
1425  adj_index_t ai;
1426 
1429 
1430  if (ADJ_INDEX_INVALID != ai)
1432 
1433  ipn->ipn_n_probes++;
1434  *wait = 1;
1435  }
1436  }
1437  else
1438  {
1439  *wait = ttl;
1440  return (IP_NEIGHBOR_AGE_ALIVE);
1441  }
1442 
1443  return (IP_NEIGHBOR_AGE_PROBE);
1444 }
1445 
1447 {
1450 
1451 static uword
1453  vlib_node_runtime_t * rt,
1455 {
1456  uword event_type, *event_data = NULL;
1457  f64 timeout;
1458 
1459  /* Set the timeout to an effectively infinite value when the process starts */
1461 
1462  while (1)
1463  {
1464  f64 now;
1465 
1466  if (!timeout)
1468  else
1470 
1471  event_type = vlib_process_get_events (vm, &event_data);
1472  vec_reset_length (event_data);
1473 
1474  now = vlib_time_now (vm);
1475 
1476  switch (event_type)
1477  {
1478  case ~0:
1479  {
1480  /* timer expired */
1481  ip_neighbor_elt_t *elt, *head;
1482  f64 wait;
1483 
1484  timeout = 1e5;
1485  head = pool_elt_at_index (ip_neighbor_elt_pool,
1486  ip_neighbor_list_head[type]);
1487 
1488  /* *INDENT-OFF*/
1489  /* the list is time sorted, newest first, so start from the back
1490  * and work forwards. Stop when we get to one that is alive */
1491  restart:
1492  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
1493  ipne_anchor, head, elt,
1494  ({
1496 
1497  res = ip_neighbour_age_out(elt->ipne_index, now, &wait);
1498 
1499  if (IP_NEIGHBOR_AGE_ALIVE == res) {
1500  /* the oldest neighbor has not yet expired, go back to sleep */
1501  break;
1502  }
1503  else if (IP_NEIGHBOR_AGE_DEAD == res) {
1504  /* the oldest neighbor is dead, pop it, then restart the walk
1505  * again from the back */
1507  goto restart;
1508  }
1509 
1510  timeout = clib_min (wait, timeout);
1511  }));
1512  /* *INDENT-ON* */
1513  break;
1514  }
1516  {
1517 
1518  if (!ip_neighbor_db[type].ipndb_age)
1519  {
1520  /* aging has been disabled */
1521  timeout = 0;
1522  break;
1523  }
1524  ip_neighbor_elt_t *elt, *head;
1525 
1526  head = pool_elt_at_index (ip_neighbor_elt_pool,
1527  ip_neighbor_list_head[type]);
1528  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
1529 
1530  /* poke the oldset neighbour for aging, which returns how long we sleep for */
1531  if (IP_NEIGHBOR_AGE_PROBE ==
1532  ip_neighbour_age_out (elt->ipne_index, now, &timeout))
1533  /* we probed for the oldest entry, sleep for a short time to get to the next */
1534  timeout = 0.01;
1535  break;
1536  }
1537  }
1538  }
1539  return 0;
1540 }
1541 
1542 static uword
1545 {
1546  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP4));
1547 }
1548 
1549 static uword
1552 {
1553  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP6));
1554 }
1555 
1556 /* *INDENT-OFF* */
1558  .function = ip4_neighbor_age_process,
1559  .type = VLIB_NODE_TYPE_PROCESS,
1560  .name = "ip4-neighbor-age-process",
1561 };
1563  .function = ip6_neighbor_age_process,
1564  .type = VLIB_NODE_TYPE_PROCESS,
1565  .name = "ip6-neighbor-age-process",
1566 };
1567 /* *INDENT-ON* */
1568 
1569 int
1570 ip_neighbor_config (ip46_type_t type, u32 limit, u32 age, bool recycle)
1571 {
1572  ip_neighbor_db[type].ipndb_limit = limit;
1573  ip_neighbor_db[type].ipndb_recycle = recycle;
1574  ip_neighbor_db[type].ipndb_age = age;
1575 
1577  (IP46_TYPE_IP4 == type ?
1581 
1582  return (0);
1583 }
1584 
1585 static clib_error_t *
1587  unformat_input_t * input, vlib_cli_command_t * cmd)
1588 {
1589  ip46_type_t type;
1590 
1591  /* *INDENT-OFF* */
1592  FOREACH_IP46_TYPE(type) {
1593  vlib_cli_output (vm, "%U:", format_ip46_type, type);
1594  vlib_cli_output (vm, " limit:%d, age:%d, recycle:%d",
1595  ip_neighbor_db[type].ipndb_limit,
1596  ip_neighbor_db[type].ipndb_age,
1597  ip_neighbor_db[type].ipndb_recycle);
1598  }
1599 
1600  /* *INDENT-ON* */
1601  return (NULL);
1602 }
1603 
1604 /* *INDENT-OFF* */
1605 VLIB_CLI_COMMAND (show_ip_neighbor_cfg_cmd_node, static) = {
1606  .path = "show ip neighbor-config",
1607  .function = ip_neighbor_config_show,
1608  .short_help = "show ip neighbor-config",
1609 };
1610 /* *INDENT-ON* */
1611 
1612 static clib_error_t *
1614 {
1615  {
1618  };
1620  }
1621  {
1624  };
1626  }
1627  {
1630  };
1632  }
1633  {
1636  };
1638  }
1639  {
1641  .function = ip_neighbor_ethernet_change_mac,
1642  .function_opaque = 0,
1643  };
1645  }
1646 
1647  ipn_logger = vlib_log_register_class ("ip", "neighbor");
1648 
1649  ip46_type_t type;
1650 
1651  FOREACH_IP46_TYPE (type)
1653  clib_llist_make_head (ip_neighbor_elt_pool, ipne_anchor);
1654 
1655  return (NULL);
1656 }
1657 
1658 /* *INDENT-OFF* */
1660 {
1661  .runs_after = VLIB_INITS("ip_main_init"),
1662 };
1663 /* *INDENT-ON* */
1664 
1665 /*
1666  * fd.io coding-style-patch-verification: ON
1667  *
1668  * Local Variables:
1669  * eval: (c-set-style "gnu")
1670  * End:
1671  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:176
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
u8 count
Definition: dhcp.api:208
ethernet_address_change_ctx_t * address_change_callbacks
Functions to call when interface hw address changes.
Definition: ethernet.h:316
static walk_rc_t ip_neighbor_walk_table_bind(index_t ipni, void *arg)
Definition: ip_neighbor.c:1350
static index_t ip_neighbor_get_index(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:97
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:549
void mac_address_increment(mac_address_t *mac)
Definition: mac_address.c:65
void adj_nbr_walk_nh(u32 sw_if_index, fib_protocol_t adj_nh_proto, const ip46_address_t *nh, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given next-hop.
Definition: adj_nbr.c:668
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:223
const mac_address_t * ip_neighbor_get_mac(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:115
void ip_neighbor_flush(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:1157
#define clib_llist_is_empty(LP, name, H)
Check is list is empty.
Definition: llist.h:121
#define clib_min(x, y)
Definition: clib.h:295
static void ip_neighbor_add_del_interface_address_v4(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_del)
Definition: ip_neighbor.c:1269
ip4_table_bind_function_t * function
Definition: ip4.h:92
f64 ipn_time_last_updated
Aging related data.
struct ip_neighbor_db_t_ ip_neighbor_db_t
ip_neighbor_elt_t * ip_neighbor_elt_pool
Pool of linked list elemeents.
Definition: ip_neighbor.c:42
static void ip_neighbor_adj_fib_add(ip_neighbor_t *ipn, u32 fib_index)
Definition: ip_neighbor.c:230
static ip_neighbor_t * ip_neighbor_pool
Pool for All IP neighbors.
Definition: ip_neighbor.c:30
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:139
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:673
vl_api_mac_address_t mac
Definition: l2.api:491
void ip46_address_increment(ip46_type_t type, ip46_address_t *ip)
Definition: ip46_address.c:61
void ip_neighbor_probe_dst(const ip_adjacency_t *adj, const ip46_address_t *dst)
Definition: ip_neighbor.c:952
An indication that the rewrite is incomplete, i.e.
Definition: adj_nbr.h:90
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:593
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:240
ip46_type_t fib_proto_to_ip46(fib_protocol_t fproto)
Convert from fib_protocol to ip46_type.
Definition: fib_types.c:310
ip46_address_t ipnk_ip
static clib_error_t * ip6_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:859
const ip46_address_t * ip_neighbor_get_ip(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:109
int ip_neighbor_add(const ip46_address_t *ip, ip46_type_t type, const mac_address_t *mac, u32 sw_if_index, ip_neighbor_flags_t flags, u32 *stats_index)
Definition: ip_neighbor.c:446
Multicast Adjacency.
Definition: adj.h:82
static vlib_node_registration_t ip6_neighbor_age_process_node
(constructor) VLIB_REGISTER_NODE (ip6_neighbor_age_process_node)
Definition: ip_neighbor.c:1562
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:475
#define NULL
Definition: clib.h:58
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
Broadcasr Adjacency.
Definition: adj.h:85
static clib_error_t * ip_neighbor_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:652
IP unicast adjacency.
Definition: adj.h:221
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:989
static void ip_neighbor_add_del_interface_address_v6(ip6_main_t *im, uword opaque, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 if_address_index, u32 is_del)
Definition: ip_neighbor.c:1308
#define IP_NEIGHBOR_DBG(...)
Definition: ip_neighbor.c:81
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1208
static void ip_neighbor_table_bind_v4(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: ip_neighbor.c:1363
static ip_neighbor_age_state_t ip_neighbour_age_out(index_t ipni, f64 now, f64 *wait)
Definition: ip_neighbor.c:1402
int ip_neighbor_config(ip46_type_t type, u32 limit, u32 age, bool recycle)
Definition: ip_neighbor.c:1570
u32 * ipndb_n_elts_per_fib
per-protocol number of elements per-fib-index
Definition: ip_neighbor.c:58
static_always_inline void mac_address_copy(mac_address_t *dst, const mac_address_t *src)
Definition: mac_address.h:128
adj_index_t adj_glean_get(fib_protocol_t proto, u32 sw_if_index)
Get an existing glean.
Definition: adj_glean.c:122
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define hash_set_mem(h, key, value)
Definition: hash.h:275
static uword ip4_destination_matches_route(const ip4_main_t *im, const ip4_address_t *key, const ip4_address_t *dest, uword dest_length)
Definition: ip4.h:194
static_always_inline int mac_address_is_zero(const mac_address_t *mac)
Definition: mac_address.h:106
unformat_function_t unformat_vnet_sw_interface
static clib_error_t * ip4_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:866
static ip46_type_t ip46_address_get_type(const ip46_address_t *ip)
Definition: ip46_address.h:148
static void ip_neighbor_list_remove(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:127
void ip4_neighbor_probe_dst(const ip_adjacency_t *adj, const ip4_address_t *dst)
Definition: ip4_neighbor.c:44
static vlib_node_registration_t ip4_neighbor_age_process_node
(constructor) VLIB_REGISTER_NODE (ip4_neighbor_age_process_node)
Definition: ip_neighbor.c:1557
static clib_error_t * ip_neighbor_interface_admin_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip_neighbor.c:1184
Definition: fib_entry.h:114
vhost_vring_addr_t addr
Definition: vhost_user.h:147
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u32 ipndb_n_elts
per-protocol number of elements
Definition: ip_neighbor.c:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
static void ip_neighbor_mk_complete(adj_index_t ai, ip_neighbor_t *ipn)
Definition: ip_neighbor.c:322
int ip_neighbor_del(const ip46_address_t *ip, ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:543
#define clib_memcpy(d, s, n)
Definition: string.h:180
Adjacency to punt this packet.
Definition: adj.h:55
enum walk_rc_t_ walk_rc_t
Walk return code.
static void ip_neighbor_adj_fib_remove(ip_neighbor_t *ipn, u32 fib_index)
Definition: ip_neighbor.c:277
#define clib_llist_add(LP, name, E, H)
Add entry after head.
Definition: llist.h:172
void adj_glean_update_rewrite(adj_index_t adj_index)
adj_glean_update_rewrite
Definition: adj_glean.c:104
int ip4_neighbor_proxy_add(u32 fib_index, const ip4_address_t *start, const ip4_address_t *end)
The set of function that vnet requires from the IP neighbour module.
Definition: ip_neighbor.c:1030
ethernet_main_t ethernet_main
Definition: init.c:45
format_function_t format_ip4_address
Definition: format.h:73
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:431
u32 vlib_log_class_t
Definition: vlib.h:51
#define clib_llist_make_head(LP, name)
Initialize llist head.
Definition: llist.h:106
void ip_neighbor_probe(const ip_adjacency_t *adj)
Definition: ip_neighbor.c:973
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
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:516
static void ip_neighbor_db_remove(const ip_neighbor_key_t *key)
Definition: ip_neighbor.c:193
static int ip46_address_cmp(const ip46_address_t *ip46_1, const ip46_address_t *ip46_2)
Definition: ip46_address.h:80
void ip_neighbor_publish(index_t ipni)
int ip4_neighbor_proxy_delete(u32 fib_index, const ip4_address_t *start, const ip4_address_t *end)
Definition: ip_neighbor.c:1044
index_t ip_neighbor_list_head[IP46_N_TYPES]
protocol specific lists of time sorted neighbors
Definition: ip_neighbor.c:33
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
struct ip_neighbor_table_bind_ctx_t_ ip_neighbor_table_bind_ctx_t
struct ip_adjacency_t_::@119::@120 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
A representation of an IP neighbour/peer.
static bool ip_neighbor_force_reuse(ip46_type_t type)
Definition: ip_neighbor.c:388
Aggregate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
union ip_adjacency_t_::@119 sub_type
unsigned int u32
Definition: types.h:88
static uword ip4_neighbor_age_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: ip_neighbor.c:1543
void ip_neighbor_populate(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:1126
u16 fp_len
The mask length.
Definition: fib_types.h:207
u8 * format_ip_neighbor(u8 *s, va_list *va)
walk_rc_t(* ip_neighbor_walk_cb_t)(index_t ipni, void *ctx)
Definition: ip_neighbor.h:44
void ip6_neighbor_advertise(vlib_main_t *vm, vnet_main_t *vnm, u32 sw_if_index, const ip6_address_t *addr)
Definition: ip6_neighbor.c:36
vl_api_fib_path_type_t type
Definition: fib_types.api:123
fib_protocol_t fib_proto_from_ip46(ip46_type_t iproto)
Convert from ip46_type to fib_protocol.
Definition: fib_types.c:326
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
#define hash_unset_mem(h, key)
Definition: hash.h:291
clib_llist_anchor_t ipne_anchor
Definition: ip_neighbor.c:37
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
ip_neighbor_process_event_t_
Definition: ip_neighbor.c:1446
static clib_error_t * ip6_neighbor_show_sorted(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:873
static u8 ip46_address_is_zero(const ip46_address_t *ip46)
Definition: ip46_address.h:87
long ctx[MAX_CONNS]
Definition: main.c:144
u32 ipndb_age
max age of a neighbor before it&#39;s forcibly evicted
Definition: ip_neighbor.c:51
void ip_neighbor_register(ip46_type_t type, const ip_neighbor_vft_t *vft)
Definition: ip_neighbor.c:946
struct _unformat_input_t unformat_input_t
static clib_error_t * ip_neighbor_show_i(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, ip46_type_t type)
Definition: ip_neighbor.c:824
#define IP_NEIGHBOR_INFO(...)
Definition: ip_neighbor.c:84
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
ip6_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip6.h:219
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
ip6_main_t ip6_main
Definition: ip6_forward.c:2703
static index_t * ip_neighbor_entries(u32 sw_if_index, ip46_type_t type)
Definition: ip_neighbor.c:773
Adjacency source.
Definition: fib_source.h:102
mac_address_t ipn_mac
The learned MAC address of the neighbour.
static uword ip6_neighbor_age_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: ip_neighbor.c:1550
vl_api_address_t dst
Definition: gre.api:61
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1291
vlib_main_t * vm
Definition: in2out_ed.c:1810
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:216
uword unformat_mac_address_t(unformat_input_t *input, va_list *args)
Definition: mac_address.c:37
#define IP_NEIGHBOR_PROCESS_SLEEP_LONG
Definition: ip_neighbor.c:1399
format_function_t format_ip46_address
Definition: ip46_address.h:50
static clib_error_t * ip_neighbor_config_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:1586
u32 ipndb_limit
per-protocol limit - max number of neighbors
Definition: ip_neighbor.c:49
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
static int ip_neighbor_sort(void *a1, void *a2)
Definition: ip_neighbor.c:755
Adjacency to drop this packet.
Definition: adj.h:53
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
static clib_error_t * ip_neighbor_init(vlib_main_t *vm)
Definition: ip_neighbor.c:1613
u32 flags
Definition: vhost_user.h:141
struct ip_neighbor_walk_covered_ctx_t_ ip_neighbor_walk_covered_ctx_t
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:218
static void ip_neighbor_table_bind_v6(ip6_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: ip_neighbor.c:1378
format_function_t format_ip6_address
Definition: format.h:91
fib_node_index_t ipn_fib_entry_index
The index of the adj fib created for this neighbour.
static void ip_neighbor_ethernet_change_mac(ethernet_main_t *em, u32 sw_if_index, uword opaque)
Definition: ip_neighbor.c:1097
static adj_walk_rc_t ip_neighbor_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:347
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
void ip_neighbor_walk(ip46_type_t type, u32 sw_if_index, ip_neighbor_walk_cb_t cb, void *ctx)
Definition: ip_neighbor.c:992
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:73
Multicast Midchain Adjacency.
Definition: adj.h:89
u8 ttl
Definition: fib_types.api:26
static uword ip_neighbor_age_loop(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f, ip46_type_t type)
Definition: ip_neighbor.c:1452
static ip_neighbor_t * ip_neighbor_db_find(const ip_neighbor_key_t *key)
Definition: ip_neighbor.c:205
Virtual function Table for neighbor protocol implementations to register.
Definition: ip_neighbor.h:102
void ip4_neighbor_advertise(vlib_main_t *vm, vnet_main_t *vnm, u32 sw_if_index, const ip4_address_t *addr)
Definition: ip4_neighbor.c:59
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:284
struct ip_neighbor_elt_t_ ip_neighbor_elt_t
static walk_rc_t ip_neighbor_walk_covered(index_t ipni, void *arg)
Definition: ip_neighbor.c:1241
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
#define IP46_N_TYPES
Definition: ip46_address.h:30
ip6_address_t ilp_addr
the IP6 address
Definition: ip6_ll_types.h:34
u8 * format_ip_neighbor_flags(u8 *s, va_list *args)
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1310
static void ip_neighbor_db_add(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:174
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
This packets follow a mid-chain adjacency.
Definition: adj.h:76
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:105
static adj_walk_rc_t ip_neighbor_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:357
u32 stats_index
Definition: ip.api:143
#define ASSERT(truth)
static u8 ip46_type_pfx_len(ip46_type_t type)
Definition: ip_neighbor.c:224
manual_print typedef address
Definition: ip_types.api:84
const mac_address_t ZERO_MAC_ADDRESS
Definition: mac_address.c:19
#define FOREACH_IP46_TYPE(_type)
Definition: ip46_address.h:32
void ip_neighbor_learn(const ip_neighbor_learn_t *l)
Definition: ip_neighbor.c:645
IPv4 main type.
Definition: ip4.h:105
int ip6_neighbor_proxy_add(u32 sw_if_index, const ip6_address_t *addr)
Definition: ip_neighbor.c:1077
static void clib_mem_free(void *p)
Definition: mem.h:226
Aggregate type for a prefix in the IPv6 Link-local table.
Definition: ip6_ll_types.h:24
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:260
int ip4_neighbor_proxy_disable(u32 sw_if_index)
Definition: ip_neighbor.c:1067
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:250
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:722
ip_neighbor_key_t * ipn_key
The idempotent key.
static void * clib_mem_alloc(uword size)
Definition: mem.h:153
unformat_function_t unformat_ip46_address
Definition: format.h:63
enum ip_neighbor_age_state_t_ ip_neighbor_age_state_t
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static void ip_neighbor_free(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:365
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
int ip4_neighbor_proxy_enable(u32 sw_if_index)
Definition: ip_neighbor.c:1057
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:146
typedef key
Definition: ipsec_types.api:83
This packets needs to go to ICMP error.
Definition: adj.h:79
This packet is for one of our own IP addresses.
Definition: adj.h:58
fib_protocol_t ia_nh_proto
The protocol of the neighbor/peer.
Definition: adj.h:249
static void ip_neighbor_refresh(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:142
vl_api_address_t ip
Definition: l2.api:490
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
static clib_error_t * ip_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:852
void ip_neighbor_advertise(vlib_main_t *vm, ip46_type_t type, const ip46_address_t *addr, u32 sw_if_index)
Definition: ip_neighbor.c:979
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:983
ip6_table_bind_function_t * function
Definition: ip6.h:115
void ip6_ll_table_entry_delete(const ip6_ll_prefix_t *ilp)
Delete a IP6 link-local entry.
Definition: ip6_ll_table.c:139
void ip6_neighbor_probe_dst(const ip_adjacency_t *adj, const ip6_address_t *dst)
Definition: ip6_neighbor.c:21
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:83
static ip_neighbor_t * ip_neighbor_alloc(const ip_neighbor_key_t *key, const mac_address_t *mac, ip_neighbor_flags_t flags)
Definition: ip_neighbor.c:409
ip_neighbor_flags_t ipn_flags
Falgs for this object.
#define hash_get_mem(h, key)
Definition: hash.h:269
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1079
bool ipndb_recycle
when the limit is reached and new neighbors are created, should we recycle an old one ...
Definition: ip_neighbor.c:54
static clib_error_t * ip4_neighbor_show_sorted(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:880
static clib_error_t * ip_neighbor_show_sorted_i(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, ip46_type_t type)
Definition: ip_neighbor.c:797
u8 * format_mac_address_t(u8 *s, va_list *args)
Definition: mac_address.c:27
ip_neighbor_t * ip_neighbor_get(index_t ipni)
Definition: ip_neighbor.c:88
#define vec_foreach(var, vec)
Vector iterator.
f64 end
end of the time range
Definition: mactime.api:44
static clib_error_t * ip_neighbor_delete_sw_interface(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: ip_neighbor.c:1213
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:294
#define clib_llist_remove(LP, name, E)
Remove entry from list.
Definition: llist.h:193
int ip6_neighbor_proxy_del(u32 sw_if_index, const ip6_address_t *addr)
Definition: ip_neighbor.c:1087
enum ip_neighbor_process_event_t_ ip_neighbor_process_event_t
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip_neighbor_delete_sw_interface)
#define clib_llist_foreach_reverse(LP, name, H, E, body)
Walk list starting at head in reverse order.
Definition: llist.h:297
static_always_inline int mac_address_cmp(const mac_address_t *a, const mac_address_t *b)
Definition: mac_address.h:134
u8 * format_ip46_type(u8 *s, va_list *args)
Definition: ip46_address.c:19
fib_node_index_t ip6_ll_table_entry_update(const ip6_ll_prefix_t *ilp, fib_route_path_flags_t flags)
Update an entry in the table.
Definition: ip6_ll_table.c:105
enum ip_neighbor_flags_t_ ip_neighbor_flags_t
void adj_nbr_update_rewrite(adj_index_t adj_index, adj_nbr_rewrite_flag_t flags, u8 *rewrite)
adj_nbr_update_rewrite
Definition: adj_nbr.c:301
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
static vlib_log_class_t ipn_logger
Definition: ip_neighbor.c:61
#define VLIB_INITS(...)
Definition: init.h:344
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ip_neighbor_interface_admin_change)
static bool ip_neighbor_is_dynamic(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:103
#define ip46_address_initializer
Definition: ip46_address.h:52
#define clib_llist_prev(LP, name, E)
Get previous pool entry.
Definition: llist.h:87
static void ip_neighbor_mk_incomplete(adj_index_t ai)
Definition: ip_neighbor.c:333
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip_neighbor_age_state_t_
Definition: ip_neighbor.c:1392
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:571
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
ip46_type_t
Definition: ip46_address.h:22
uword ** ipndb_hash
per interface hash
Definition: ip_neighbor.c:47
const u32 ip_neighbor_get_sw_if_index(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:121
adj_index_t adj_nbr_find(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Lookup neighbor adjancency.
Definition: adj_nbr.c:99