FD.io VPP  v21.01.1
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[N_AF] = {
66  [AF_IP4] = {
67  .ipndb_limit = 50000,
68  /* Default to not aging and not recycling */
69  .ipndb_age = 0,
70  .ipndb_recycle = false,
71  },
72  [AF_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 void
104 {
105  ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_STALE;
106 }
107 
108 static bool
110 {
111  return (ipn->ipn_flags & IP_NEIGHBOR_FLAG_DYNAMIC);
112 }
113 
114 const ip_address_t *
116 {
117  return (&ipn->ipn_key->ipnk_ip);
118 }
119 
122 {
123  return (ip_addr_version (&ipn->ipn_key->ipnk_ip));
124 }
125 
126 const mac_address_t *
128 {
129  return (&ipn->ipn_mac);
130 }
131 
132 const u32
134 {
135  return (ipn->ipn_key->ipnk_sw_if_index);
136 }
137 
138 static void
140 {
141  /* new neighbours, are added to the head of the list, since the
142  * list is time sorted, newest first */
143  ip_neighbor_elt_t *elt;
144 
145  if (~0 != ipn->ipn_elt)
146  {
147  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
148 
149  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
150 
151  ipn->ipn_elt = ~0;
152  }
153 }
154 
155 static void
157 {
158  /* new neighbours, are added to the head of the list, since the
159  * list is time sorted, newest first */
160  ip_neighbor_elt_t *elt, *head;
161 
162  ip_neighbor_touch (ipn);
164  ipn->ipn_n_probes = 0;
165 
166  if (ip_neighbor_is_dynamic (ipn))
167  {
168  if (~0 == ipn->ipn_elt)
169  /* first time insertion */
170  pool_get_zero (ip_neighbor_elt_pool, elt);
171  else
172  {
173  /* already inserted - extract first */
174  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
175 
176  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
177  }
178  head = pool_elt_at_index (ip_neighbor_elt_pool,
180  (ipn)]);
181 
182  elt->ipne_index = ip_neighbor_get_index (ipn);
183  clib_llist_add (ip_neighbor_elt_pool, ipne_anchor, elt, head);
184  ipn->ipn_elt = elt - ip_neighbor_elt_pool;
185  }
186 }
187 
188 static void
190 {
193 
194  af = ip_neighbor_get_af (ipn);
195  sw_if_index = ipn->ipn_key->ipnk_sw_if_index;
196 
197  vec_validate (ip_neighbor_db[af].ipndb_hash, sw_if_index);
198 
199  if (!ip_neighbor_db[af].ipndb_hash[sw_if_index])
200  ip_neighbor_db[af].ipndb_hash[sw_if_index]
201  = hash_create_mem (0, sizeof (ip_neighbor_key_t), sizeof (index_t));
202 
203  hash_set_mem (ip_neighbor_db[af].ipndb_hash[sw_if_index],
204  ipn->ipn_key, ip_neighbor_get_index (ipn));
205 
206  ip_neighbor_db[af].ipndb_n_elts++;
207 }
208 
209 static void
211 {
214 
215  af = ip_neighbor_get_af (ipn);
216  sw_if_index = ipn->ipn_key->ipnk_sw_if_index;
217 
218  vec_validate (ip_neighbor_db[af].ipndb_hash, sw_if_index);
219 
220  hash_unset_mem (ip_neighbor_db[af].ipndb_hash[sw_if_index], ipn->ipn_key);
221 
222  ip_neighbor_db[af].ipndb_n_elts--;
223 }
224 
225 static ip_neighbor_t *
227 {
229  uword *p;
230 
231  af = ip_addr_version (&key->ipnk_ip);
232 
233  if (key->ipnk_sw_if_index >= vec_len (ip_neighbor_db[af].ipndb_hash))
234  return NULL;
235 
236  p = hash_get_mem (ip_neighbor_db[af].ipndb_hash
237  [key->ipnk_sw_if_index], key);
238 
239  if (p)
240  return ip_neighbor_get (p[0]);
241 
242  return (NULL);
243 }
244 
245 static u8
247 {
248  return (type == AF_IP4 ? 32 : 128);
249 }
250 
251 static void
253 {
255 
256  af = ip_neighbor_get_af (ipn);
257 
258  if (af == AF_IP6 &&
260  (&ipn->ipn_key->ipnk_ip)))
261  {
262  ip6_ll_prefix_t pfx = {
263  .ilp_addr = ip_addr_v6 (&ipn->ipn_key->ipnk_ip),
264  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
265  };
266  ipn->ipn_fib_entry_index =
268  }
269  else
270  {
271  fib_protocol_t fproto;
272 
273  fproto = ip_address_family_to_fib_proto (af);
274 
275  fib_prefix_t pfx = {
276  .fp_len = ip_af_type_pfx_len (af),
277  .fp_proto = fproto,
278  .fp_addr = ip_addr_46 (&ipn->ipn_key->ipnk_ip),
279  };
280 
281  ipn->ipn_fib_entry_index =
282  fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
284  fib_proto_to_dpo (fproto),
285  &pfx.fp_addr,
287  ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
288 
289  vec_validate (ip_neighbor_db[af].ipndb_n_elts_per_fib, fib_index);
290 
291  ip_neighbor_db[af].ipndb_n_elts_per_fib[fib_index]++;
292 
293  if (1 == ip_neighbor_db[af].ipndb_n_elts_per_fib[fib_index])
294  fib_table_lock (fib_index, fproto, FIB_SOURCE_ADJ);
295  }
296 }
297 
298 static void
300 {
302 
303  af = ip_neighbor_get_af (ipn);
304 
306  {
307  if (AF_IP6 == af &&
309  (&ipn->ipn_key->ipnk_ip)))
310  {
311  ip6_ll_prefix_t pfx = {
312  .ilp_addr = ip_addr_v6 (&ipn->ipn_key->ipnk_ip),
313  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
314  };
316  }
317  else
318  {
319  fib_protocol_t fproto;
320 
321  fproto = ip_address_family_to_fib_proto (af);
322 
323  fib_prefix_t pfx = {
324  .fp_len = ip_af_type_pfx_len (af),
325  .fp_proto = fproto,
326  .fp_addr = ip_addr_46 (&ipn->ipn_key->ipnk_ip),
327  };
328 
329  fib_table_entry_path_remove (fib_index,
330  &pfx,
332  fib_proto_to_dpo (fproto),
333  &pfx.fp_addr,
335  ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
336 
337  ip_neighbor_db[af].ipndb_n_elts_per_fib[fib_index]--;
338 
339  if (0 == ip_neighbor_db[af].ipndb_n_elts_per_fib[fib_index])
340  fib_table_unlock (fib_index, fproto, FIB_SOURCE_ADJ);
341  }
342  }
343 }
344 
345 static void
347 {
350  ipn->
351  ipn_key->ipnk_sw_if_index,
352  adj_get_link_type (ai),
353  ipn->ipn_mac.bytes));
354 }
355 
356 static void
358 {
359  ip_adjacency_t *adj = adj_get (ai);
360 
364  adj->
365  rewrite_header.sw_if_index,
368 }
369 
370 static adj_walk_rc_t
372 {
373  ip_neighbor_t *ipn = ctx;
374 
375  ip_neighbor_mk_complete (ai, ipn);
376 
377  return (ADJ_WALK_RC_CONTINUE);
378 }
379 
380 static adj_walk_rc_t
382 {
384 
385  return (ADJ_WALK_RC_CONTINUE);
386 }
387 
388 static void
390 {
392 
393  af = ip_neighbor_get_af (ipn);
394 
395  IP_NEIGHBOR_DBG ("free: %U", format_ip_neighbor,
396  ip_neighbor_get_index (ipn));
397 
400 
403  &ip_addr_46 (&ipn->ipn_key->ipnk_ip),
406  (ipn,
409 
411  ip_neighbor_db_remove (ipn);
412  clib_mem_free (ipn->ipn_key);
413 
414  pool_put (ip_neighbor_pool, ipn);
415 }
416 
417 static bool
419 {
420  if (!ip_neighbor_db[af].ipndb_recycle)
421  return false;
422 
423  /* pluck the oldest entry, which is the one from the end of the list */
424  ip_neighbor_elt_t *elt, *head;
425 
426  head = pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[af]);
427 
428  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
429  return (false);
430 
431  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
433 
434  return (true);
435 }
436 
437 static ip_neighbor_t *
440 {
442  ip_neighbor_t *ipn;
443 
444  af = ip_addr_version (&key->ipnk_ip);
445 
446  if (ip_neighbor_db[af].ipndb_limit &&
447  (ip_neighbor_db[af].ipndb_n_elts >= ip_neighbor_db[af].ipndb_limit))
448  {
449  if (!ip_neighbor_force_reuse (af))
450  return (NULL);
451  }
452 
453  pool_get_zero (ip_neighbor_pool, ipn);
454 
455  ipn->ipn_key = clib_mem_alloc (sizeof (*ipn->ipn_key));
456  clib_memcpy (ipn->ipn_key, key, sizeof (*ipn->ipn_key));
457 
459  ipn->ipn_flags = flags;
460  ipn->ipn_elt = ~0;
461 
462  mac_address_copy (&ipn->ipn_mac, mac);
463 
464  ip_neighbor_db_add (ipn);
465 
466  /* create the adj-fib. the entry in the FIB table for the peer's interface */
467  if (!(ipn->ipn_flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY))
471 
472  return (ipn);
473 }
474 
475 int
477  const mac_address_t * mac,
480 {
481  fib_protocol_t fproto;
482  ip_neighbor_t *ipn;
483 
484  /* main thread only */
485  ASSERT (0 == vlib_get_thread_index ());
486 
488 
489  const ip_neighbor_key_t key = {
490  .ipnk_ip = *ip,
491  .ipnk_sw_if_index = sw_if_index,
492  };
493 
494  ipn = ip_neighbor_db_find (&key);
495 
496  if (ipn)
497  {
498  IP_NEIGHBOR_DBG ("update: %U, %U",
500  sw_if_index, format_ip_address, ip,
502  mac);
503 
504  ip_neighbor_touch (ipn);
505 
506  /* Refuse to over-write static neighbor entry. */
507  if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
508  (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
509  {
510  /* if MAC address match, still check to send event */
511  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
512  goto check_customers;
513  return -2;
514  }
515 
516  /* A dynamic entry can become static, but not vice-versa.
517  * i.e. since if it was programmed by the CP then it must
518  * be removed by the CP */
519  if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
520  !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
521  {
523  ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STATIC;
524  ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
525  }
526 
527  /*
528  * prevent a DoS attack from the data-plane that
529  * spams us with no-op updates to the MAC address
530  */
531  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
532  {
533  ip_neighbor_refresh (ipn);
534  goto check_customers;
535  }
536 
537  mac_address_copy (&ipn->ipn_mac, mac);
538  }
539  else
540  {
541  IP_NEIGHBOR_INFO ("add: %U, %U",
543  sw_if_index, format_ip_address, ip,
545  mac);
546 
547  ipn = ip_neighbor_alloc (&key, mac, flags);
548 
549  if (NULL == ipn)
550  return VNET_API_ERROR_LIMIT_EXCEEDED;
551  }
552 
553  /* Update time stamp and flags. */
554  ip_neighbor_refresh (ipn);
555 
557  fproto, &ip_addr_46 (&ipn->ipn_key->ipnk_ip),
559 
560 check_customers:
561  /* Customer(s) requesting event for this address? */
563 
564  if (stats_index)
565  *stats_index = adj_nbr_find (fproto,
566  fib_proto_to_link (fproto),
567  &ip_addr_46 (&ipn->ipn_key->ipnk_ip),
568  ipn->ipn_key->ipnk_sw_if_index);
569  return 0;
570 }
571 
572 int
574 {
575  ip_neighbor_t *ipn;
576 
577  /* main thread only */
578  ASSERT (0 == vlib_get_thread_index ());
579 
580  IP_NEIGHBOR_INFO ("delete: %U, %U",
582  sw_if_index, format_ip_address, ip);
583 
584  const ip_neighbor_key_t key = {
585  .ipnk_ip = *ip,
586  .ipnk_sw_if_index = sw_if_index,
587  };
588 
589  ipn = ip_neighbor_db_find (&key);
590 
591  if (NULL == ipn)
592  return (VNET_API_ERROR_NO_SUCH_ENTRY);
593 
594  ip_neighbor_destroy (ipn);
595 
596  return (0);
597 }
598 
600 {
603 
604 static walk_rc_t
606 {
608 
609  vec_add1 (ctx->ipn_del, ipni);
610 
611  return (WALK_CONTINUE);
612 }
613 
614 void
616 {
617  IP_NEIGHBOR_INFO ("delete-all: %U, %U",
620  sw_if_index);
621 
623  .ipn_del = NULL,
624  };
625  index_t *ipni;
626 
627  ip_neighbor_walk (af, sw_if_index, ip_neighbor_del_all_walk_cb, &ctx);
628 
629  vec_foreach (ipni,
631  vec_free (ctx.ipn_del);
632 }
633 
634 void
636 {
637  ip_neighbor_t *ipn;
638  ip_adjacency_t *adj;
639 
640  adj = adj_get (ai);
641 
643  .ipnk_sw_if_index = adj->rewrite_header.sw_if_index,
644  };
645 
646  ip_address_from_46 (&adj->sub_type.nbr.next_hop,
647  adj->ia_nh_proto, &key.ipnk_ip);
648 
649  ipn = ip_neighbor_db_find (&key);
650 
651  switch (adj->lookup_next_index)
652  {
653  case IP_LOOKUP_NEXT_ARP:
654  if (NULL != ipn)
655  {
656  adj_nbr_walk_nh (adj->rewrite_header.sw_if_index,
657  adj->ia_nh_proto,
658  &adj->sub_type.nbr.next_hop,
660  }
661  else
662  {
663  /*
664  * no matching ARP entry.
665  * construct the rewrite required to for an ARP packet, and stick
666  * that in the adj's pipe to smoke.
667  */
669  (ai,
672  (vnm,
673  adj->rewrite_header.sw_if_index,
676 
677  /*
678  * since the FIB has added this adj for a route, it makes sense it
679  * may want to forward traffic sometime soon. Let's send a
680  * speculative ARP. just one. If we were to do periodically that
681  * wouldn't be bad either, but that's more code than i'm prepared to
682  * write at this time for relatively little reward.
683  */
684  /*
685  * adj_nbr_update_rewrite may actually call fib_walk_sync.
686  * fib_walk_sync may allocate a new adjacency and potentially cause
687  * a realloc for adj_pool. When that happens, adj pointer is no
688  * longer valid here.x We refresh adj pointer accordingly.
689  */
690  adj = adj_get (ai);
691  ip_neighbor_probe (adj);
692  }
693  break;
697  case IP_LOOKUP_NEXT_DROP:
698  case IP_LOOKUP_NEXT_PUNT:
704  case IP_LOOKUP_N_NEXT:
705  ASSERT (0);
706  break;
707  }
708 }
709 
710 void
712 {
713  ip_neighbor_add (&l->ip, &l->mac, l->sw_if_index,
714  IP_NEIGHBOR_FLAG_DYNAMIC, NULL);
715 }
716 
717 static clib_error_t *
719  unformat_input_t * input, vlib_cli_command_t * cmd)
720 {
723  vnet_main_t *vnm = vnet_get_main ();
725  u32 sw_if_index = ~0;
726  int is_add = 1;
727  int count = 1;
728 
729  flags = IP_NEIGHBOR_FLAG_DYNAMIC;
730 
732  {
733  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
734  if (unformat (input, "%U %U %U",
735  unformat_vnet_sw_interface, vnm, &sw_if_index,
737  ;
738  else if (unformat (input, "delete") || unformat (input, "del"))
739  is_add = 0;
740  else if (unformat (input, "static"))
741  {
742  flags |= IP_NEIGHBOR_FLAG_STATIC;
743  flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
744  }
745  else if (unformat (input, "no-fib-entry"))
746  flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
747  else if (unformat (input, "count %d", &count))
748  ;
749  else
750  break;
751  }
752 
753  if (sw_if_index == ~0 ||
754  ip_address_is_zero (&ip) || mac_address_is_zero (&mac))
755  return clib_error_return (0,
756  "specify interface, IP address and MAC: `%U'",
757  format_unformat_error, input);
758 
759  while (count)
760  {
761  if (is_add)
762  ip_neighbor_add (&ip, &mac, sw_if_index, flags, NULL);
763  else
764  ip_neighbor_del (&ip, sw_if_index);
765 
766  ip_address_increment (&ip);
767  mac_address_increment (&mac);
768 
769  --count;
770  }
771 
772  return NULL;
773 }
774 
775 /* *INDENT-OFF* */
776 /*?
777  * Add or delete IPv4 ARP cache entries.
778  *
779  * @note 'set ip neighbor' options (e.g. delete, static, 'fib-id <id>',
780  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
781  * any order and combination.
782  *
783  * @cliexpar
784  * @parblock
785  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
786  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
787  * @cliexcmd{set ip neighbor GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
788  * @cliexcmd{set ip neighbor delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
789  *
790  * To add or delete an IPv4 ARP cache entry to or from a specific fib
791  * table:
792  * @cliexcmd{set ip neighbor fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
793  * @cliexcmd{set ip neighbor fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
794  *
795  * Add or delete IPv4 static ARP cache entries as follows:
796  * @cliexcmd{set ip neighbor static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
797  * @cliexcmd{set ip neighbor static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
798  *
799  * For testing / debugging purposes, the 'set ip neighbor' command can add or
800  * delete multiple entries. Supply the 'count N' parameter:
801  * @cliexcmd{set ip neighbor count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
802  * @endparblock
803  ?*/
804 VLIB_CLI_COMMAND (ip_neighbor_command, static) = {
805  .path = "set ip neighbor",
806  .short_help =
807  "set ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
808  .function = ip_neighbor_cmd,
809 };
810 VLIB_CLI_COMMAND (ip_neighbor_command2, static) = {
811  .path = "ip neighbor",
812  .short_help =
813  "ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
814  .function = ip_neighbor_cmd,
815 };
816 /* *INDENT-ON* */
817 
818 static int
819 ip_neighbor_sort (void *a1, void *a2)
820 {
821  index_t *ipni1 = a1, *ipni2 = a2;
822  ip_neighbor_t *ipn1, *ipn2;
823  int cmp;
824 
825  ipn1 = ip_neighbor_get (*ipni1);
826  ipn2 = ip_neighbor_get (*ipni2);
827 
829  ipn1->ipn_key->ipnk_sw_if_index,
830  ipn2->ipn_key->ipnk_sw_if_index);
831  if (!cmp)
832  cmp = ip_address_cmp (&ipn1->ipn_key->ipnk_ip, &ipn2->ipn_key->ipnk_ip);
833  return cmp;
834 }
835 
836 static index_t *
838 {
839  index_t *ipnis = NULL;
840  ip_neighbor_t *ipn;
841 
842  /* *INDENT-OFF* */
843  pool_foreach (ipn, ip_neighbor_pool)
844  {
845  if ((sw_if_index == ~0 ||
846  ipn->ipn_key->ipnk_sw_if_index == sw_if_index) &&
847  (N_AF == af ||
848  ip_neighbor_get_af(ipn) == af))
849  vec_add1 (ipnis, ip_neighbor_get_index(ipn));
850  }
851 
852  /* *INDENT-ON* */
853 
854  if (ipnis)
856  return ipnis;
857 }
858 
859 static clib_error_t *
861  unformat_input_t * input,
863 {
864  ip_neighbor_elt_t *elt, *head;
865 
866  head = pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[af]);
867 
868 
869  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
870  "Flags", "Ethernet", "Interface");
871 
872  /* *INDENT-OFF*/
873  /* the list is time sorted, newest first, so start from the back
874  * and work forwards. Stop when we get to one that is alive */
875  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
876  ipne_anchor, head, elt,
877  ({
879  }));
880  /* *INDENT-ON*/
881 
882  return (NULL);
883 }
884 
885 static clib_error_t *
887  unformat_input_t * input,
889 {
890  index_t *ipni, *ipnis = NULL;
892 
893  /* Filter entries by interface if given. */
894  sw_if_index = ~0;
896  &sw_if_index);
897 
898  ipnis = ip_neighbor_entries (sw_if_index, af);
899 
900  if (ipnis)
901  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
902  "Flags", "Ethernet", "Interface");
903 
904  vec_foreach (ipni, ipnis)
905  {
906  vlib_cli_output (vm, "%U", format_ip_neighbor, *ipni);
907  }
908  vec_free (ipnis);
909 
910  return (NULL);
911 }
912 
913 static clib_error_t *
915  unformat_input_t * input, vlib_cli_command_t * cmd)
916 {
917  return (ip_neighbor_show_i (vm, input, cmd, N_AF));
918 }
919 
920 static clib_error_t *
922  unformat_input_t * input, vlib_cli_command_t * cmd)
923 {
924  return (ip_neighbor_show_i (vm, input, cmd, AF_IP6));
925 }
926 
927 static clib_error_t *
929  unformat_input_t * input, vlib_cli_command_t * cmd)
930 {
931  return (ip_neighbor_show_i (vm, input, cmd, AF_IP4));
932 }
933 
934 static clib_error_t *
936  unformat_input_t * input, vlib_cli_command_t * cmd)
937 {
938  return (ip_neighbor_show_sorted_i (vm, input, cmd, AF_IP6));
939 }
940 
941 static clib_error_t *
943  unformat_input_t * input, vlib_cli_command_t * cmd)
944 {
945  return (ip_neighbor_show_sorted_i (vm, input, cmd, AF_IP4));
946 }
947 
948 /*?
949  * Display all the IP neighbor entries.
950  *
951  * @cliexpar
952  * Example of how to display the IPv4 ARP table:
953  * @cliexstart{show ip neighbor}
954  * Time FIB IP4 Flags Ethernet Interface
955  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
956  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
957  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
958  * Proxy arps enabled for:
959  * Fib_index 0 6.0.0.1 - 6.0.0.11
960  * @cliexend
961  ?*/
962 /* *INDENT-OFF* */
963 VLIB_CLI_COMMAND (show_ip_neighbors_cmd_node, static) = {
964  .path = "show ip neighbors",
965  .function = ip_neighbor_show,
966  .short_help = "show ip neighbors [interface]",
967 };
968 VLIB_CLI_COMMAND (show_ip4_neighbors_cmd_node, static) = {
969  .path = "show ip4 neighbors",
970  .function = ip4_neighbor_show,
971  .short_help = "show ip4 neighbors [interface]",
972 };
973 VLIB_CLI_COMMAND (show_ip6_neighbors_cmd_node, static) = {
974  .path = "show ip6 neighbors",
975  .function = ip6_neighbor_show,
976  .short_help = "show ip6 neighbors [interface]",
977 };
978 VLIB_CLI_COMMAND (show_ip_neighbor_cmd_node, static) = {
979  .path = "show ip neighbor",
980  .function = ip_neighbor_show,
981  .short_help = "show ip neighbor [interface]",
982 };
983 VLIB_CLI_COMMAND (show_ip4_neighbor_cmd_node, static) = {
984  .path = "show ip4 neighbor",
985  .function = ip4_neighbor_show,
986  .short_help = "show ip4 neighbor [interface]",
987 };
988 VLIB_CLI_COMMAND (show_ip6_neighbor_cmd_node, static) = {
989  .path = "show ip6 neighbor",
990  .function = ip6_neighbor_show,
991  .short_help = "show ip6 neighbor [interface]",
992 };
993 VLIB_CLI_COMMAND (show_ip4_neighbor_sorted_cmd_node, static) = {
994  .path = "show ip4 neighbor-sorted",
995  .function = ip4_neighbor_show_sorted,
996  .short_help = "show ip4 neighbor-sorted",
997 };
998 VLIB_CLI_COMMAND (show_ip6_neighbor_sorted_cmd_node, static) = {
999  .path = "show ip6 neighbor-sorted",
1000  .function = ip6_neighbor_show_sorted,
1001  .short_help = "show ip6 neighbor-sorted",
1002 };
1003 /* *INDENT-ON* */
1004 
1005 static ip_neighbor_vft_t ip_nbr_vfts[N_AF];
1006 
1007 void
1009 {
1010  ip_nbr_vfts[af] = *vft;
1011 }
1012 
1013 void
1015  ip_address_family_t af, const ip46_address_t * dst)
1016 {
1017  if (!vnet_sw_interface_is_admin_up (vnet_get_main (), sw_if_index))
1018  return;
1019 
1020  switch (af)
1021  {
1022  case AF_IP6:
1023  ip6_neighbor_probe_dst (sw_if_index, &dst->ip6);
1024  break;
1025  case AF_IP4:
1026  ip4_neighbor_probe_dst (sw_if_index, &dst->ip4);
1027  break;
1028  }
1029 }
1030 
1031 void
1033 {
1034  ip_neighbor_probe_dst (adj->rewrite_header.sw_if_index,
1036  &adj->sub_type.nbr.next_hop);
1037 }
1038 
1039 void
1042 {
1044  index_t ipni;
1045 
1046  if (~0 == sw_if_index)
1047  {
1048  uword **hash;
1049 
1050  vec_foreach (hash, ip_neighbor_db[af].ipndb_hash)
1051  {
1052  /* *INDENT-OFF* */
1053  hash_foreach (key, ipni, *hash,
1054  ({
1055  if (WALK_STOP == cb (ipni, ctx))
1056  break;
1057  }));
1058  /* *INDENT-ON* */
1059  }
1060  }
1061  else
1062  {
1063  uword *hash;
1064 
1065  if (vec_len (ip_neighbor_db[af].ipndb_hash) <= sw_if_index)
1066  return;
1067  hash = ip_neighbor_db[af].ipndb_hash[sw_if_index];
1068 
1069  /* *INDENT-OFF* */
1070  hash_foreach (key, ipni, hash,
1071  ({
1072  if (WALK_STOP == cb (ipni, ctx))
1073  break;
1074  }));
1075  /* *INDENT-ON* */
1076  }
1077 }
1078 
1079 int
1081  const ip4_address_t * start,
1082  const ip4_address_t * end)
1083 {
1084  if (ip_nbr_vfts[AF_IP4].inv_proxy4_add)
1085  {
1086  return (ip_nbr_vfts[AF_IP4].inv_proxy4_add (fib_index, start, end));
1087  }
1088 
1089  return (-1);
1090 }
1091 
1092 int
1094  const ip4_address_t * start,
1095  const ip4_address_t * end)
1096 {
1097  if (ip_nbr_vfts[AF_IP4].inv_proxy4_del)
1098  {
1099  return (ip_nbr_vfts[AF_IP4].inv_proxy4_del (fib_index, start, end));
1100  }
1101  return -1;
1102 }
1103 
1104 int
1106 {
1107  if (ip_nbr_vfts[AF_IP4].inv_proxy4_enable)
1108  {
1109  return (ip_nbr_vfts[AF_IP4].inv_proxy4_enable (sw_if_index));
1110  }
1111  return -1;
1112 }
1113 
1114 int
1116 {
1117  if (ip_nbr_vfts[AF_IP4].inv_proxy4_disable)
1118  {
1119  return (ip_nbr_vfts[AF_IP4].inv_proxy4_disable (sw_if_index));
1120  }
1121  return -1;
1122 }
1123 
1124 int
1125 ip6_neighbor_proxy_add (u32 sw_if_index, const ip6_address_t * addr)
1126 {
1127  if (ip_nbr_vfts[AF_IP6].inv_proxy6_add)
1128  {
1129  return (ip_nbr_vfts[AF_IP6].inv_proxy6_add (sw_if_index, addr));
1130  }
1131  return -1;
1132 }
1133 
1134 int
1135 ip6_neighbor_proxy_del (u32 sw_if_index, const ip6_address_t * addr)
1136 {
1137  if (ip_nbr_vfts[AF_IP6].inv_proxy6_del)
1138  {
1139  return (ip_nbr_vfts[AF_IP6].inv_proxy6_del (sw_if_index, addr));
1140  }
1141  return -1;
1142 }
1143 
1144 static void
1146  u32 sw_if_index, uword opaque)
1147 {
1148  ip_neighbor_t *ipn;
1149 
1150  IP_NEIGHBOR_DBG ("mac-change: %U",
1152  sw_if_index);
1153 
1154  /* *INDENT-OFF* */
1155  pool_foreach (ipn, ip_neighbor_pool)
1156  {
1157  if (ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1160  &ip_addr_46(&ipn->ipn_key->ipnk_ip),
1162  ipn);
1163  }
1164  /* *INDENT-ON* */
1165 
1166  adj_glean_update_rewrite_itf (sw_if_index);
1167 }
1168 
1169 void
1171 {
1172  index_t *ipnis = NULL, *ipni;
1173  ip_neighbor_t *ipn;
1174 
1175  IP_NEIGHBOR_DBG ("populate: %U %U",
1177  sw_if_index, format_ip_address_family, af);
1178 
1179  /* *INDENT-OFF* */
1180  pool_foreach (ipn, ip_neighbor_pool)
1181  {
1182  if (ip_neighbor_get_af(ipn) == af &&
1183  ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1184  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1185  }
1186  /* *INDENT-ON* */
1187 
1188  vec_foreach (ipni, ipnis)
1189  {
1190  ipn = ip_neighbor_get (*ipni);
1191 
1194  (ipn)),
1195  &ip_addr_46 (&ipn->ipn_key->ipnk_ip),
1197  }
1198  vec_free (ipnis);
1199 }
1200 
1201 void
1203 {
1204  index_t *ipnis = NULL, *ipni;
1205  ip_neighbor_t *ipn;
1206 
1207 
1208  IP_NEIGHBOR_DBG ("flush: %U %U",
1210  sw_if_index, format_ip_address_family, af);
1211 
1212  /* *INDENT-OFF* */
1213  pool_foreach (ipn, ip_neighbor_pool)
1214  {
1215  if (ip_neighbor_get_af(ipn) == af &&
1216  ipn->ipn_key->ipnk_sw_if_index == sw_if_index &&
1217  ip_neighbor_is_dynamic (ipn))
1218  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1219  }
1220  /* *INDENT-ON* */
1221 
1222  vec_foreach (ipni, ipnis) ip_neighbor_destroy (ip_neighbor_get (*ipni));
1223  vec_free (ipnis);
1224 }
1225 
1226 static walk_rc_t
1228 {
1229  ip_neighbor_t *ipn;
1230 
1231  ipn = ip_neighbor_get (ipni);
1232 
1233  ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STALE;
1234 
1235  return (WALK_CONTINUE);
1236 }
1237 
1238 void
1240 {
1241  ip_neighbor_walk (af, ~0, ip_neighbor_mark_one, NULL);
1242 }
1243 
1245 {
1248 
1249 static walk_rc_t
1251 {
1253  ip_neighbor_t *ipn;
1254 
1255  ipn = ip_neighbor_get (ipni);
1256 
1257  if (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STALE)
1258  {
1259  vec_add1 (ctx->ipnsc_stale, ipni);
1260  }
1261 
1262  return (WALK_CONTINUE);
1263 }
1264 
1265 void
1267 {
1269  index_t *ipni;
1270 
1271  ip_neighbor_walk (af, ~0, ip_neighbor_sweep_one, &ctx);
1272 
1273  vec_foreach (ipni, ctx.ipnsc_stale)
1274  {
1276  }
1277  vec_free (ctx.ipnsc_stale);
1278 }
1279 
1280 /*
1281  * Remove any arp entries associated with the specified interface
1282  */
1283 static clib_error_t *
1286 {
1288 
1289  IP_NEIGHBOR_DBG ("interface-admin: %U %s",
1291  sw_if_index,
1292  (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ? "up" : "down"));
1293 
1294  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1295  {
1296  FOR_EACH_IP_ADDRESS_FAMILY (af) ip_neighbor_populate (af, sw_if_index);
1297  }
1298  else
1299  {
1300  /* admin down, flush all neighbours */
1301  FOR_EACH_IP_ADDRESS_FAMILY (af) ip_neighbor_flush (af, sw_if_index);
1302  }
1303 
1304  return (NULL);
1305 }
1306 
1308 
1309 /*
1310  * Remove any arp entries associated with the specified interface
1311  */
1312 static clib_error_t *
1314  u32 sw_if_index, u32 is_add)
1315 {
1316  IP_NEIGHBOR_DBG ("interface-change: %U %s",
1318  sw_if_index, (is_add ? "add" : "del"));
1319 
1320  if (!is_add && sw_if_index != ~0)
1321  {
1323 
1324  FOR_EACH_IP_ADDRESS_FAMILY (af) ip_neighbor_flush (af, sw_if_index);
1325  }
1326 
1327  return (NULL);
1328 }
1329 
1331 
1333 {
1338 
1339 static walk_rc_t
1341 {
1343  ip_neighbor_t *ipn;
1344 
1345  ipn = ip_neighbor_get (ipni);
1346 
1347  if (AF_IP4 == ip_addr_version (&ctx->addr))
1348  {
1350  &ip_addr_v4 (&ipn->ipn_key->ipnk_ip),
1351  &ip_addr_v4 (&ctx->addr),
1352  ctx->length) &&
1353  ip_neighbor_is_dynamic (ipn))
1354  {
1355  vec_add1 (ctx->ipnis, ip_neighbor_get_index (ipn));
1356  }
1357  }
1358  else if (AF_IP6 == ip_addr_version (&ctx->addr))
1359  {
1361  &ip_addr_v6 (&ipn->ipn_key->ipnk_ip),
1362  &ip_addr_v6 (&ctx->addr),
1363  ctx->length) &&
1364  ip_neighbor_is_dynamic (ipn))
1365  {
1366  vec_add1 (ctx->ipnis, ip_neighbor_get_index (ipn));
1367  }
1368  }
1369  return (WALK_CONTINUE);
1370 }
1371 
1372 
1373 /*
1374  * callback when an interface address is added or deleted
1375  */
1376 static void
1378  uword opaque,
1379  u32 sw_if_index,
1381  u32 address_length,
1382  u32 if_address_index, u32 is_del)
1383 {
1384  /*
1385  * Flush the ARP cache of all entries covered by the address
1386  * that is being removed.
1387  */
1388  IP_NEIGHBOR_DBG ("addr-%d: %U, %U/%d",
1389  (is_del ? "del" : "add"),
1391  sw_if_index, format_ip4_address, address, address_length);
1392 
1393  if (is_del)
1394  {
1395  /* *INDENT-OFF* */
1397  .addr = {
1398  .ip.ip4 = *address,
1399  .version = AF_IP4,
1400  },
1401  .length = address_length,
1402  };
1403  /* *INDENT-ON* */
1404  index_t *ipni;
1405 
1406  ip_neighbor_walk (AF_IP4, sw_if_index, ip_neighbor_walk_covered, &ctx);
1407 
1408  vec_foreach (ipni, ctx.ipnis)
1410 
1411  vec_free (ctx.ipnis);
1412  }
1413 }
1414 
1415 /*
1416  * callback when an interface address is added or deleted
1417  */
1418 static void
1420  uword opaque,
1421  u32 sw_if_index,
1422  ip6_address_t * address,
1423  u32 address_length,
1424  u32 if_address_index, u32 is_del)
1425 {
1426  /*
1427  * Flush the ARP cache of all entries covered by the address
1428  * that is being removed.
1429  */
1430  IP_NEIGHBOR_DBG ("addr-change: %U, %U/%d %s",
1432  sw_if_index, format_ip6_address, address, address_length,
1433  (is_del ? "del" : "add"));
1434 
1435  if (is_del)
1436  {
1437  /* *INDENT-OFF* */
1439  .addr = {
1440  .ip.ip6 = *address,
1441  .version = AF_IP6,
1442  },
1443  .length = address_length,
1444  };
1445  /* *INDENT-ON* */
1446  index_t *ipni;
1447 
1448  ip_neighbor_walk (AF_IP6, sw_if_index, ip_neighbor_walk_covered, &ctx);
1449 
1450  vec_foreach (ipni, ctx.ipnis)
1452 
1453  vec_free (ctx.ipnis);
1454  }
1455 }
1456 
1458 {
1462 
1463 static walk_rc_t
1465 {
1467  ip_neighbor_t *ipn;
1468 
1469  ipn = ip_neighbor_get (ipni);
1472 
1473  return (WALK_CONTINUE);
1474 }
1475 
1476 static void
1478  uword opaque,
1479  u32 sw_if_index,
1480  u32 new_fib_index, u32 old_fib_index)
1481 {
1483  .old_fib_index = old_fib_index,
1484  .new_fib_index = new_fib_index,
1485  };
1486 
1487  ip_neighbor_walk (AF_IP4, sw_if_index, ip_neighbor_walk_table_bind, &ctx);
1488 }
1489 
1490 static void
1492  uword opaque,
1493  u32 sw_if_index,
1494  u32 new_fib_index, u32 old_fib_index)
1495 {
1497  .old_fib_index = old_fib_index,
1498  .new_fib_index = new_fib_index,
1499  };
1500 
1501  ip_neighbor_walk (AF_IP6, sw_if_index, ip_neighbor_walk_table_bind, &ctx);
1502 }
1503 
1505 {
1510 
1511 #define IP_NEIGHBOR_PROCESS_SLEEP_LONG (0)
1512 
1515 {
1517  ip_neighbor_t *ipn;
1518  u32 ipndb_age;
1519  u32 ttl;
1520 
1521  ipn = ip_neighbor_get (ipni);
1522  af = ip_neighbor_get_af (ipn);
1523  ipndb_age = ip_neighbor_db[af].ipndb_age;
1524  ttl = now - ipn->ipn_time_last_updated;
1525  *wait = ipndb_age;
1526 
1527  if (ttl > ipndb_age)
1528  {
1529  IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
1530  format_ip_neighbor, ipni, now,
1531  ipn->ipn_time_last_updated, ipndb_age);
1532  if (ipn->ipn_n_probes > 2)
1533  {
1534  /* 3 strikes and yea-re out */
1535  IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
1536  *wait = 1;
1537  return (IP_NEIGHBOR_AGE_DEAD);
1538  }
1539  else
1540  {
1542  af, &ip_addr_46 (&ipn->ipn_key->ipnk_ip));
1543 
1544  ipn->ipn_n_probes++;
1545  *wait = 1;
1546  }
1547  }
1548  else
1549  {
1550  /* here we are sure that ttl <= ipndb_age */
1551  *wait = ipndb_age - ttl + 1;
1552  return (IP_NEIGHBOR_AGE_ALIVE);
1553  }
1554 
1555  return (IP_NEIGHBOR_AGE_PROBE);
1556 }
1557 
1559 {
1562 
1563 static uword
1565  vlib_node_runtime_t * rt,
1567 {
1568  uword event_type, *event_data = NULL;
1569  f64 timeout;
1570 
1571  /* Set the timeout to an effectively infinite value when the process starts */
1573 
1574  while (1)
1575  {
1576  f64 now;
1577 
1578  if (!timeout)
1580  else
1582 
1583  event_type = vlib_process_get_events (vm, &event_data);
1584  vec_reset_length (event_data);
1585 
1586  now = vlib_time_now (vm);
1587 
1588  switch (event_type)
1589  {
1590  case ~0:
1591  {
1592  /* timer expired */
1593  ip_neighbor_elt_t *elt, *head;
1594  f64 wait;
1595 
1596  timeout = ip_neighbor_db[af].ipndb_age;
1597  head = pool_elt_at_index (ip_neighbor_elt_pool,
1598  ip_neighbor_list_head[af]);
1599 
1600  /* *INDENT-OFF*/
1601  /* the list is time sorted, newest first, so start from the back
1602  * and work forwards. Stop when we get to one that is alive */
1603  restart:
1604  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
1605  ipne_anchor, head, elt,
1606  ({
1608 
1609  res = ip_neighbour_age_out(elt->ipne_index, now, &wait);
1610 
1611  if (IP_NEIGHBOR_AGE_ALIVE == res) {
1612  /* the oldest neighbor has not yet expired, go back to sleep */
1613  timeout = clib_min (wait, timeout);
1614  break;
1615  }
1616  else if (IP_NEIGHBOR_AGE_DEAD == res) {
1617  /* the oldest neighbor is dead, pop it, then restart the walk
1618  * again from the back */
1620  goto restart;
1621  }
1622 
1623  timeout = clib_min (wait, timeout);
1624  }));
1625  /* *INDENT-ON* */
1626  break;
1627  }
1629  {
1630 
1631  if (!ip_neighbor_db[af].ipndb_age)
1632  {
1633  /* aging has been disabled */
1634  timeout = 0;
1635  break;
1636  }
1637  ip_neighbor_elt_t *elt, *head;
1638 
1639  head = pool_elt_at_index (ip_neighbor_elt_pool,
1640  ip_neighbor_list_head[af]);
1641  /* no neighbors yet */
1642  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
1643  {
1644  timeout = ip_neighbor_db[af].ipndb_age;
1645  break;
1646  }
1647 
1648  /* poke the oldset neighbour for aging, which returns how long we sleep for */
1649  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
1650  ip_neighbour_age_out (elt->ipne_index, now, &timeout);
1651  break;
1652  }
1653  }
1654  }
1655  return 0;
1656 }
1657 
1658 static uword
1661 {
1662  return (ip_neighbor_age_loop (vm, rt, f, AF_IP4));
1663 }
1664 
1665 static uword
1668 {
1669  return (ip_neighbor_age_loop (vm, rt, f, AF_IP6));
1670 }
1671 
1672 /* *INDENT-OFF* */
1674  .function = ip4_neighbor_age_process,
1675  .type = VLIB_NODE_TYPE_PROCESS,
1676  .name = "ip4-neighbor-age-process",
1677 };
1679  .function = ip6_neighbor_age_process,
1680  .type = VLIB_NODE_TYPE_PROCESS,
1681  .name = "ip6-neighbor-age-process",
1682 };
1683 /* *INDENT-ON* */
1684 
1685 int
1686 ip_neighbor_config (ip_address_family_t af, u32 limit, u32 age, bool recycle)
1687 {
1688  ip_neighbor_db[af].ipndb_limit = limit;
1689  ip_neighbor_db[af].ipndb_recycle = recycle;
1690  ip_neighbor_db[af].ipndb_age = age;
1691 
1693  (AF_IP4 == af ?
1697 
1698  return (0);
1699 }
1700 
1701 static clib_error_t *
1703  unformat_input_t * input, vlib_cli_command_t * cmd)
1704 {
1706 
1707  /* *INDENT-OFF* */
1709  vlib_cli_output (vm, "%U:", format_ip_address_family, af);
1710  vlib_cli_output (vm, " limit:%d, age:%d, recycle:%d",
1711  ip_neighbor_db[af].ipndb_limit,
1712  ip_neighbor_db[af].ipndb_age,
1713  ip_neighbor_db[af].ipndb_recycle);
1714  }
1715 
1716  /* *INDENT-ON* */
1717  return (NULL);
1718 }
1719 
1720 /* *INDENT-OFF* */
1721 VLIB_CLI_COMMAND (show_ip_neighbor_cfg_cmd_node, static) = {
1722  .path = "show ip neighbor-config",
1723  .function = ip_neighbor_config_show,
1724  .short_help = "show ip neighbor-config",
1725 };
1726 /* *INDENT-ON* */
1727 
1728 static clib_error_t *
1730 {
1731  {
1734  };
1736  }
1737  {
1740  };
1742  }
1743  {
1746  };
1748  }
1749  {
1752  };
1754  }
1755  {
1757  .function = ip_neighbor_ethernet_change_mac,
1758  .function_opaque = 0,
1759  };
1761  }
1762 
1763  ipn_logger = vlib_log_register_class ("ip", "neighbor");
1764 
1766 
1768  ip_neighbor_list_head[af] =
1769  clib_llist_make_head (ip_neighbor_elt_pool, ipne_anchor);
1770 
1771  return (NULL);
1772 }
1773 
1774 /* *INDENT-OFF* */
1776 {
1777  .runs_after = VLIB_INITS("ip_main_init"),
1778 };
1779 /* *INDENT-ON* */
1780 
1781 /*
1782  * fd.io coding-style-patch-verification: ON
1783  *
1784  * Local Variables:
1785  * eval: (c-set-style "gnu")
1786  * End:
1787  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:338
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
ethernet_address_change_ctx_t * address_change_callbacks
Functions to call when interface hw address changes.
Definition: ethernet.h:334
static walk_rc_t ip_neighbor_walk_table_bind(index_t ipni, void *arg)
Definition: ip_neighbor.c:1464
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:558
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:663
#define ip_addr_v6(_a)
Definition: ip_types.h:92
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:239
const mac_address_t * ip_neighbor_get_mac(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:127
#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:328
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:1377
ip4_table_bind_function_t * function
Definition: ip4.h:94
f64 ipn_time_last_updated
Aging related data.
struct ip_neighbor_db_t_ ip_neighbor_db_t
#define ip_addr_46(_a)
Definition: ip_types.h:90
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:252
static ip_neighbor_t * ip_neighbor_pool
Pool for All IP neighbors.
Definition: ip_neighbor.c:30
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1245
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:141
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:751
vl_api_mac_address_t mac
Definition: l2.api:502
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
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:656
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:254
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
static clib_error_t * ip6_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:921
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:1678
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:506
void ip_neighbor_probe_dst(u32 sw_if_index, ip_address_family_t af, const ip46_address_t *dst)
Definition: ip_neighbor.c:1014
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
Broadcast 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:718
IP unicast adjacency.
Definition: adj.h:235
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:998
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:1419
#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:592
ip_address_family_t ip_neighbor_get_af(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:121
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:1477
static ip_neighbor_age_state_t ip_neighbour_age_out(index_t ipni, f64 now, f64 *wait)
Definition: ip_neighbor.c:1514
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
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:188
vlib_main_t * vm
Definition: in2out_ed.c:1580
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:928
index_t ip_neighbor_list_head[N_AF]
protocol specific lists of time sorted neighbors
Definition: ip_neighbor.c:33
static void ip_neighbor_list_remove(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:139
static void ip_neighbor_db_remove(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:210
static vlib_node_registration_t ip4_neighbor_age_process_node
(constructor) VLIB_REGISTER_NODE (ip4_neighbor_age_process_node)
Definition: ip_neighbor.c:1673
void adj_glean_update_rewrite_itf(u32 sw_if_index)
Definition: adj_glean.c:190
static clib_error_t * ip_neighbor_interface_admin_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip_neighbor.c:1284
#define ip_addr_version(_a)
Definition: ip_types.h:93
int ip_neighbor_add(const ip_address_t *ip, const mac_address_t *mac, u32 sw_if_index, ip_neighbor_flags_t flags, u32 *stats_index)
Definition: ip_neighbor.c:476
Definition: fib_entry.h:114
vhost_vring_addr_t addr
Definition: vhost_user.h:111
int ip_neighbor_del(const ip_address_t *ip, u32 sw_if_index)
Definition: ip_neighbor.c:573
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:346
#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:299
#define clib_llist_add(LP, name, E, H)
Add entry after head.
Definition: llist.h:172
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:1080
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:467
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:1032
struct ip_adjacency_t_::@161::@162 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
#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:579
int ip4_neighbor_proxy_delete(u32 fib_index, const ip4_address_t *start, const ip4_address_t *end)
Definition: ip_neighbor.c:1093
static uword ip6_destination_matches_route(const ip6_main_t *im, const ip6_address_t *key, const ip6_address_t *dest, uword dest_length)
Definition: ip6.h:189
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
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
A representation of an IP neighbour/peer.
Aggregate type for a prefix.
Definition: fib_types.h:202
const ip_address_t * ip_neighbor_get_ip(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:115
#define clib_error_return(e, args...)
Definition: error.h:99
void ip_neighbor_publish(index_t ipni, ip_neighbor_event_flags_t flags)
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:1659
void ip_neighbor_del_all(ip_address_family_t af, u32 sw_if_index)
Definition: ip_neighbor.c:615
u16 fp_len
The mask length.
Definition: fib_types.h:206
void ip_neighbor_mark(ip_address_family_t af)
Definition: ip_neighbor.c:1239
u8 * format_ip_neighbor(u8 *s, va_list *va)
void ip_neighbor_sweep(ip_address_family_t af)
Definition: ip_neighbor.c:1266
walk_rc_t(* ip_neighbor_walk_cb_t)(index_t ipni, void *ctx)
Definition: ip_neighbor.h:42
vl_api_fib_path_type_t type
Definition: fib_types.api:123
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
static index_t * ip_neighbor_entries(u32 sw_if_index, ip_address_family_t af)
Definition: ip_neighbor.c:837
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
#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:1015
void ip_address_from_46(const ip46_address_t *nh, fib_protocol_t fproto, ip_address_t *ip)
Definition: ip_types.c:260
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:225
void ip4_neighbor_probe_dst(u32 sw_if_index, const ip4_address_t *dst)
Definition: ip4_neighbor.c:49
ip_neighbor_process_event_t_
Definition: ip_neighbor.c:1558
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:935
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
struct _unformat_input_t unformat_input_t
#define IP_NEIGHBOR_INFO(...)
Definition: ip_neighbor.c:84
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
bool ip_address_is_zero(const ip_address_t *ip)
Definition: ip_types.c:102
ip6_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip6.h:151
static walk_rc_t ip_neighbor_del_all_walk_cb(index_t ipni, void *arg)
Definition: ip_neighbor.c:605
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:2785
uword unformat_ip_address(unformat_input_t *input, va_list *args)
Definition: ip_types.c:41
u8 * format_ip_address_family(u8 *s, va_list *args)
Definition: ip.c:192
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:1666
vl_api_address_t dst
Definition: gre.api:55
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:1300
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:148
static walk_rc_t ip_neighbor_sweep_one(index_t ipni, void *arg)
Definition: ip_neighbor.c:1250
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:1511
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:1702
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:819
Adjacency to drop this packet.
Definition: adj.h:53
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static clib_error_t * ip_neighbor_init(vlib_main_t *vm)
Definition: ip_neighbor.c:1729
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:219
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:1491
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:1145
static adj_walk_rc_t ip_neighbor_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:371
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:75
Multicast Midchain Adjacency.
Definition: adj.h:89
u8 ttl
Definition: fib_types.api:26
struct ip_neighbor_del_all_ctx_t_ ip_neighbor_del_all_ctx_t
u8 * format_ip_address(u8 *s, va_list *args)
Definition: ip_types.c:21
static ip_neighbor_t * ip_neighbor_db_find(const ip_neighbor_key_t *key)
Definition: ip_neighbor.c:226
Virtual function Table for neighbor protocol implementations to register.
Definition: ip_neighbor.h:101
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
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:1340
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void ip6_neighbor_probe_dst(u32 sw_if_index, const ip6_address_t *dst)
Definition: ip6_neighbor.c:26
fib_protocol_t ip_address_family_to_fib_proto(ip_address_family_t af)
Definition: ip_types.c:224
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:1319
static void ip_neighbor_db_add(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:189
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
This packets follow a mid-chain adjacency.
Definition: adj.h:76
void ip_neighbor_walk(ip_address_family_t af, u32 sw_if_index, ip_neighbor_walk_cb_t cb, void *ctx)
Definition: ip_neighbor.c:1040
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:96
static uword ip_neighbor_age_loop(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f, ip_address_family_t af)
Definition: ip_neighbor.c:1564
static adj_walk_rc_t ip_neighbor_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:381
u32 stats_index
Definition: ip.api:143
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
#define ip_addr_v4(_a)
Definition: ip_types.h:91
manual_print typedef address
Definition: ip_types.api:96
const mac_address_t ZERO_MAC_ADDRESS
Definition: mac_address.c:19
struct ip_neighbor_sweep_ctx_t_ ip_neighbor_sweep_ctx_t
void ip_neighbor_learn(const ip_neighbor_learn_t *l)
Definition: ip_neighbor.c:711
IPv4 main type.
Definition: ip4.h:107
int ip6_neighbor_proxy_add(u32 sw_if_index, const ip6_address_t *addr)
Definition: ip_neighbor.c:1125
static void clib_mem_free(void *p)
Definition: mem.h:311
#define FOR_EACH_IP_ADDRESS_FAMILY(_af)
Definition: ip_types.h:33
Aggregate type for a prefix in the IPv6 Link-local table.
Definition: ip6_ll_types.h:24
int ip_address_cmp(const ip_address_t *ip1, const ip_address_t *ip2)
Definition: ip_types.c:117
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
int ip4_neighbor_proxy_disable(u32 sw_if_index)
Definition: ip_neighbor.c:1115
void ip_neighbor_flush(ip_address_family_t af, u32 sw_if_index)
Definition: ip_neighbor.c:1202
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
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:731
ip_neighbor_key_t * ipn_key
The idempotent key.
enum ip_neighbor_flags_t_ ip_neighbor_flags_t
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
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 uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
enum ip_address_family_t_ ip_address_family_t
int ip4_neighbor_proxy_enable(u32 sw_if_index)
Definition: ip_neighbor.c:1105
union ip_adjacency_t_::@161 sub_type
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:148
typedef key
Definition: ipsec_types.api:86
This packets needs to go to ICMP error.
Definition: adj.h:79
#define N_AF
Definition: ip_types.h:27
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:350
static void ip_neighbor_refresh(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:156
#define IP_ADDRESS_V6_ALL_0S
Definition: ip_types.h:87
vl_api_address_t ip
Definition: l2.api:501
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
static void ip_neighbor_touch(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:103
static void ip_neighbor_destroy(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:389
#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:337
static clib_error_t * ip_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:914
static u8 ip_af_type_pfx_len(ip_address_family_t type)
Definition: ip_neighbor.c:246
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:1055
ip6_table_bind_function_t * function
Definition: ip6.h:106
void ip6_ll_table_entry_delete(const ip6_ll_prefix_t *ilp)
Delete a IP6 link-local entry.
Definition: ip6_ll_table.c:140
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:438
static clib_error_t * ip_neighbor_show_sorted_i(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, ip_address_family_t af)
Definition: ip_neighbor.c:860
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:1105
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:942
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:1313
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:377
u8 count
Definition: dhcp.api:208
#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:1135
void ip_neighbor_populate(ip_address_family_t af, u32 sw_if_index)
Definition: ip_neighbor.c:1170
static walk_rc_t ip_neighbor_mark_one(index_t ipni, void *ctx)
Definition: ip_neighbor.c:1227
static bool ip_neighbor_force_reuse(ip_address_family_t af)
Definition: ip_neighbor.c:418
enum ip_neighbor_process_event_t_ ip_neighbor_process_event_t
static clib_error_t * ip_neighbor_show_i(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, ip_address_family_t af)
Definition: ip_neighbor.c:886
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
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:106
void ip_address_increment(ip_address_t *ip)
Definition: ip_types.c:292
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:319
static vlib_log_class_t ipn_logger
Definition: ip_neighbor.c:61
#define VLIB_INITS(...)
Definition: init.h:357
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ip_neighbor_interface_admin_change)
int ip_neighbor_config(ip_address_family_t af, u32 limit, u32 age, bool recycle)
Definition: ip_neighbor.c:1686
static bool ip_neighbor_is_dynamic(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:109
#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:357
void ip_neighbor_register(ip_address_family_t af, const ip_neighbor_vft_t *vft)
Definition: ip_neighbor.c:1008
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip_neighbor_age_state_t_
Definition: ip_neighbor.c:1504
ip_address_family_t ip_address_family_from_fib_proto(fib_protocol_t fp)
Definition: ip_types.c:238
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:635
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
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:133
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:109