FD.io VPP  v20.09-64-g4f7b92f0a
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 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 ip46_address_t *
116 {
117  return (&ipn->ipn_key->ipnk_ip);
118 }
119 
120 const mac_address_t *
122 {
123  return (&ipn->ipn_mac);
124 }
125 
126 const u32
128 {
129  return (ipn->ipn_key->ipnk_sw_if_index);
130 }
131 
132 static void
134 {
135  /* new neighbours, are added to the head of the list, since the
136  * list is time sorted, newest first */
137  ip_neighbor_elt_t *elt;
138 
139  if (~0 != ipn->ipn_elt)
140  {
141  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
142 
143  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
144 
145  ipn->ipn_elt = ~0;
146  }
147 }
148 
149 static void
151 {
152  /* new neighbours, are added to the head of the list, since the
153  * list is time sorted, newest first */
154  ip_neighbor_elt_t *elt, *head;
155 
156  ip_neighbor_touch (ipn);
158  ipn->ipn_n_probes = 0;
159 
160  if (ip_neighbor_is_dynamic (ipn))
161  {
162  if (~0 == ipn->ipn_elt)
163  /* first time insertion */
164  pool_get_zero (ip_neighbor_elt_pool, elt);
165  else
166  {
167  /* already inserted - extract first */
168  elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
169 
170  clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
171  }
172  head = pool_elt_at_index (ip_neighbor_elt_pool,
174  ipn_key->ipnk_type]);
175 
176  elt->ipne_index = ip_neighbor_get_index (ipn);
177  clib_llist_add (ip_neighbor_elt_pool, ipne_anchor, elt, head);
178  ipn->ipn_elt = elt - ip_neighbor_elt_pool;
179  }
180 }
181 
182 static void
184 {
185  vec_validate (ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash,
186  ipn->ipn_key->ipnk_sw_if_index);
187 
188  if (!ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash
189  [ipn->ipn_key->ipnk_sw_if_index])
190  ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash[ipn->
191  ipn_key->ipnk_sw_if_index]
192  = hash_create_mem (0, sizeof (ip_neighbor_key_t), sizeof (index_t));
193 
194  hash_set_mem (ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_hash
195  [ipn->ipn_key->ipnk_sw_if_index], ipn->ipn_key,
196  ip_neighbor_get_index (ipn));
197 
198  ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_n_elts++;
199 }
200 
201 static void
203 {
204  vec_validate (ip_neighbor_db[key->ipnk_type].ipndb_hash,
205  key->ipnk_sw_if_index);
206 
207  hash_unset_mem (ip_neighbor_db[key->ipnk_type].ipndb_hash
208  [key->ipnk_sw_if_index], key);
209 
210  ip_neighbor_db[key->ipnk_type].ipndb_n_elts--;
211 }
212 
213 static ip_neighbor_t *
215 {
216  uword *p;
217 
218  if (key->ipnk_sw_if_index >=
219  vec_len (ip_neighbor_db[key->ipnk_type].ipndb_hash))
220  return NULL;
221 
222  p =
223  hash_get_mem (ip_neighbor_db[key->ipnk_type].ipndb_hash
224  [key->ipnk_sw_if_index], key);
225 
226  if (p)
227  return ip_neighbor_get (p[0]);
228 
229  return (NULL);
230 }
231 
232 static u8
234 {
235  return (type == IP46_TYPE_IP4 ? 32 : 128);
236 }
237 
238 static void
240 {
241  if (ipn->ipn_key->ipnk_type == IP46_TYPE_IP6 &&
243  {
244  ip6_ll_prefix_t pfx = {
245  .ilp_addr = ipn->ipn_key->ipnk_ip.ip6,
246  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
247  };
248  ipn->ipn_fib_entry_index =
250  }
251  else
252  {
253  fib_protocol_t fproto;
254 
255  fproto = fib_proto_from_ip46 (ipn->ipn_key->ipnk_type);
256 
257  fib_prefix_t pfx = {
259  .fp_proto = fproto,
260  .fp_addr = ipn->ipn_key->ipnk_ip,
261  };
262 
263  ipn->ipn_fib_entry_index =
264  fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
266  fib_proto_to_dpo (fproto),
267  &pfx.fp_addr,
269  ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
270 
271  vec_validate (ip_neighbor_db
273  fib_index);
274 
275  ip_neighbor_db[ipn->ipn_key->
276  ipnk_type].ipndb_n_elts_per_fib[fib_index]++;
277 
278  if (1 ==
279  ip_neighbor_db[ipn->ipn_key->
280  ipnk_type].ipndb_n_elts_per_fib[fib_index])
281  fib_table_lock (fib_index, fproto, FIB_SOURCE_ADJ);
282  }
283 }
284 
285 static void
287 {
289  {
290  if (ipn->ipn_key->ipnk_type == IP46_TYPE_IP6 &&
292  {
293  ip6_ll_prefix_t pfx = {
294  .ilp_addr = ipn->ipn_key->ipnk_ip.ip6,
295  .ilp_sw_if_index = ipn->ipn_key->ipnk_sw_if_index,
296  };
298  }
299  else
300  {
301  fib_protocol_t fproto;
302 
303  fproto = fib_proto_from_ip46 (ipn->ipn_key->ipnk_type);
304 
305  fib_prefix_t pfx = {
307  .fp_proto = fproto,
308  .fp_addr = ipn->ipn_key->ipnk_ip,
309  };
310 
311  fib_table_entry_path_remove (fib_index,
312  &pfx,
314  fib_proto_to_dpo (fproto),
315  &pfx.fp_addr,
317  ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
318 
319  ip_neighbor_db[ipn->ipn_key->
320  ipnk_type].ipndb_n_elts_per_fib[fib_index]--;
321 
322  if (0 ==
323  ip_neighbor_db[ipn->ipn_key->
324  ipnk_type].ipndb_n_elts_per_fib[fib_index])
325  fib_table_unlock (fib_index, fproto, FIB_SOURCE_ADJ);
326  }
327  }
328 }
329 
330 static void
332 {
335  ipn->
336  ipn_key->ipnk_sw_if_index,
337  adj_get_link_type (ai),
338  ipn->ipn_mac.bytes));
339 }
340 
341 static void
343 {
344  ip_adjacency_t *adj = adj_get (ai);
345 
349  adj->
350  rewrite_header.sw_if_index,
353 }
354 
355 static adj_walk_rc_t
357 {
358  ip_neighbor_t *ipn = ctx;
359 
360  ip_neighbor_mk_complete (ai, ipn);
361 
362  return (ADJ_WALK_RC_CONTINUE);
363 }
364 
365 static adj_walk_rc_t
367 {
369 
370  return (ADJ_WALK_RC_CONTINUE);
371 }
372 
373 static void
375 {
376  IP_NEIGHBOR_DBG ("free: %U", format_ip_neighbor,
377  ip_neighbor_get_index (ipn));
378 
381 
384  &ipn->ipn_key->ipnk_ip,
387  (ipn,
390  ipn->ipn_key->ipnk_sw_if_index));
391 
394  clib_mem_free (ipn->ipn_key);
395 
396  pool_put (ip_neighbor_pool, ipn);
397 }
398 
399 static bool
401 {
402  if (!ip_neighbor_db[type].ipndb_recycle)
403  return false;
404 
405  /* pluck the oldest entry, which is the one from the end of the list */
406  ip_neighbor_elt_t *elt, *head;
407 
408  head =
409  pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[type]);
410 
411  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
412  return (false);
413 
414  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
416 
417  return (true);
418 }
419 
420 static ip_neighbor_t *
423 {
424  ip_neighbor_t *ipn;
425 
426  if (ip_neighbor_db[key->ipnk_type].ipndb_limit &&
427  (ip_neighbor_db[key->ipnk_type].ipndb_n_elts >=
428  ip_neighbor_db[key->ipnk_type].ipndb_limit))
429  {
431  return (NULL);
432  }
433 
434  pool_get_zero (ip_neighbor_pool, ipn);
435 
436  ipn->ipn_key = clib_mem_alloc (sizeof (*ipn->ipn_key));
437  clib_memcpy (ipn->ipn_key, key, sizeof (*ipn->ipn_key));
438 
440  ipn->ipn_flags = flags;
441  ipn->ipn_elt = ~0;
442 
443  mac_address_copy (&ipn->ipn_mac, mac);
444 
445  ip_neighbor_db_add (ipn);
446 
447  /* create the adj-fib. the entry in the FIB table for the peer's interface */
448  if (!(ipn->ipn_flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY))
452  ipn->ipn_key->ipnk_sw_if_index));
453 
454  return (ipn);
455 }
456 
457 int
458 ip_neighbor_add (const ip46_address_t * ip,
460  const mac_address_t * mac,
463 {
464  fib_protocol_t fproto;
465  ip_neighbor_t *ipn;
466 
467  /* main thread only */
468  ASSERT (0 == vlib_get_thread_index ());
469 
470  fproto = fib_proto_from_ip46 (type);
471 
472  const ip_neighbor_key_t key = {
473  .ipnk_ip = *ip,
474  .ipnk_sw_if_index = sw_if_index,
475  .ipnk_type = type,
476  };
477 
478  ipn = ip_neighbor_db_find (&key);
479 
480  if (ipn)
481  {
482  IP_NEIGHBOR_DBG ("update: %U, %U",
484  sw_if_index, format_ip46_address, ip, type,
486  mac);
487 
488  ip_neighbor_touch (ipn);
489 
490  /* Refuse to over-write static neighbor entry. */
491  if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
492  (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
493  {
494  /* if MAC address match, still check to send event */
495  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
496  goto check_customers;
497  return -2;
498  }
499 
500  /* A dynamic entry can become static, but not vice-versa.
501  * i.e. since if it was programmed by the CP then it must
502  * be removed by the CP */
503  if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
504  !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
505  {
507  ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STATIC;
508  ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
509  }
510 
511  /*
512  * prevent a DoS attack from the data-plane that
513  * spams us with no-op updates to the MAC address
514  */
515  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
516  {
517  ip_neighbor_refresh (ipn);
518  goto check_customers;
519  }
520 
521  mac_address_copy (&ipn->ipn_mac, mac);
522  }
523  else
524  {
525  IP_NEIGHBOR_INFO ("add: %U, %U",
527  sw_if_index, format_ip46_address, ip, type,
529  mac);
530 
531  ipn = ip_neighbor_alloc (&key, mac, flags);
532 
533  if (NULL == ipn)
534  return VNET_API_ERROR_LIMIT_EXCEEDED;
535  }
536 
537  /* Update time stamp and flags. */
538  ip_neighbor_refresh (ipn);
539 
541  fproto, &ipn->ipn_key->ipnk_ip,
543 
544 check_customers:
545  /* Customer(s) requesting event for this address? */
547 
548  if (stats_index)
549  *stats_index = adj_nbr_find (fproto,
550  fib_proto_to_link (fproto),
551  &ipn->ipn_key->ipnk_ip,
552  ipn->ipn_key->ipnk_sw_if_index);
553  return 0;
554 }
555 
556 int
557 ip_neighbor_del (const ip46_address_t * ip, ip46_type_t type, u32 sw_if_index)
558 {
559  ip_neighbor_t *ipn;
560 
561  /* main thread only */
562  ASSERT (0 == vlib_get_thread_index ());
563 
564  IP_NEIGHBOR_INFO ("delete: %U, %U",
566  sw_if_index, format_ip46_address, ip, type);
567 
568  const ip_neighbor_key_t key = {
569  .ipnk_ip = *ip,
570  .ipnk_sw_if_index = sw_if_index,
571  .ipnk_type = type,
572  };
573 
574  ipn = ip_neighbor_db_find (&key);
575 
576  if (NULL == ipn)
577  return (VNET_API_ERROR_NO_SUCH_ENTRY);
578 
579  ip_neighbor_destroy (ipn);
580 
581  return (0);
582 }
583 
585 {
588 
589 static walk_rc_t
591 {
593 
594  vec_add1 (ctx->ipn_del, ipni);
595 
596  return (WALK_CONTINUE);
597 }
598 
599 void
601 {
602  IP_NEIGHBOR_INFO ("delete-all: %U, %U",
603  format_ip46_type, type,
605  sw_if_index);
606 
608  .ipn_del = NULL,
609  };
610  index_t *ipni;
611 
612  ip_neighbor_walk (type, sw_if_index, ip_neighbor_del_all_walk_cb, &ctx);
613 
614  vec_foreach (ipni,
616  vec_free (ctx.ipn_del);
617 }
618 
619 void
621 {
622  ip_neighbor_t *ipn;
623  ip_adjacency_t *adj;
624 
625  adj = adj_get (ai);
626 
628  .ipnk_ip = adj->sub_type.nbr.next_hop,
629  .ipnk_type = fib_proto_to_ip46 (adj->ia_nh_proto),
630  .ipnk_sw_if_index = adj->rewrite_header.sw_if_index,
631  };
632  ipn = ip_neighbor_db_find (&key);
633 
634  switch (adj->lookup_next_index)
635  {
636  case IP_LOOKUP_NEXT_ARP:
637  if (NULL != ipn)
638  {
639  adj_nbr_walk_nh (adj->rewrite_header.sw_if_index,
640  adj->ia_nh_proto,
641  &ipn->ipn_key->ipnk_ip,
643  }
644  else
645  {
646  /*
647  * no matching ARP entry.
648  * construct the rewrite required to for an ARP packet, and stick
649  * that in the adj's pipe to smoke.
650  */
652  (ai,
655  (vnm,
656  adj->rewrite_header.sw_if_index,
659 
660  /*
661  * since the FIB has added this adj for a route, it makes sense it
662  * may want to forward traffic sometime soon. Let's send a
663  * speculative ARP. just one. If we were to do periodically that
664  * wouldn't be bad either, but that's more code than i'm prepared to
665  * write at this time for relatively little reward.
666  */
667  /*
668  * adj_nbr_update_rewrite may actually call fib_walk_sync.
669  * fib_walk_sync may allocate a new adjacency and potentially cause
670  * a realloc for adj_pool. When that happens, adj pointer is no
671  * longer valid here.x We refresh adj pointer accordingly.
672  */
673  adj = adj_get (ai);
674  ip_neighbor_probe (adj);
675  }
676  break;
680  case IP_LOOKUP_NEXT_DROP:
681  case IP_LOOKUP_NEXT_PUNT:
687  case IP_LOOKUP_N_NEXT:
688  ASSERT (0);
689  break;
690  }
691 }
692 
693 void
695 {
696  ip_neighbor_add (&l->ip, l->type, &l->mac, l->sw_if_index,
697  IP_NEIGHBOR_FLAG_DYNAMIC, NULL);
698 }
699 
700 static clib_error_t *
702  unformat_input_t * input, vlib_cli_command_t * cmd)
703 {
704  ip46_address_t ip = ip46_address_initializer;
706  vnet_main_t *vnm = vnet_get_main ();
708  u32 sw_if_index = ~0;
709  int is_add = 1;
710  int count = 1;
711 
712  flags = IP_NEIGHBOR_FLAG_DYNAMIC;
713 
715  {
716  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
717  if (unformat (input, "%U %U %U",
718  unformat_vnet_sw_interface, vnm, &sw_if_index,
720  unformat_mac_address_t, &mac))
721  ;
722  else if (unformat (input, "delete") || unformat (input, "del"))
723  is_add = 0;
724  else if (unformat (input, "static"))
725  {
726  flags |= IP_NEIGHBOR_FLAG_STATIC;
727  flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
728  }
729  else if (unformat (input, "no-fib-entry"))
730  flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
731  else if (unformat (input, "count %d", &count))
732  ;
733  else
734  break;
735  }
736 
737  if (sw_if_index == ~0 ||
739  return clib_error_return (0,
740  "specify interface, IP address and MAC: `%U'",
741  format_unformat_error, input);
742 
743  while (count)
744  {
745  if (is_add)
746  ip_neighbor_add (&ip, ip46_address_get_type (&ip), &mac, sw_if_index,
747  flags, NULL);
748  else
749  ip_neighbor_del (&ip, ip46_address_get_type (&ip), sw_if_index);
750 
752  mac_address_increment (&mac);
753 
754  --count;
755  }
756 
757  return NULL;
758 }
759 
760 /* *INDENT-OFF* */
761 /*?
762  * Add or delete IPv4 ARP cache entries.
763  *
764  * @note 'set ip neighbor' options (e.g. delete, static, 'fib-id <id>',
765  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
766  * any order and combination.
767  *
768  * @cliexpar
769  * @parblock
770  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
771  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
772  * @cliexcmd{set ip neighbor GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
773  * @cliexcmd{set ip neighbor delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
774  *
775  * To add or delete an IPv4 ARP cache entry to or from a specific fib
776  * table:
777  * @cliexcmd{set ip neighbor fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
778  * @cliexcmd{set ip neighbor fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
779  *
780  * Add or delete IPv4 static ARP cache entries as follows:
781  * @cliexcmd{set ip neighbor static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
782  * @cliexcmd{set ip neighbor static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
783  *
784  * For testing / debugging purposes, the 'set ip neighbor' command can add or
785  * delete multiple entries. Supply the 'count N' parameter:
786  * @cliexcmd{set ip neighbor count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
787  * @endparblock
788  ?*/
789 VLIB_CLI_COMMAND (ip_neighbor_command, static) = {
790  .path = "set ip neighbor",
791  .short_help =
792  "set ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
793  .function = ip_neighbor_cmd,
794 };
795 VLIB_CLI_COMMAND (ip_neighbor_command2, static) = {
796  .path = "ip neighbor",
797  .short_help =
798  "ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
799  .function = ip_neighbor_cmd,
800 };
801 /* *INDENT-ON* */
802 
803 static int
804 ip_neighbor_sort (void *a1, void *a2)
805 {
806  index_t *ipni1 = a1, *ipni2 = a2;
807  ip_neighbor_t *ipn1, *ipn2;
808  int cmp;
809 
810  ipn1 = ip_neighbor_get (*ipni1);
811  ipn2 = ip_neighbor_get (*ipni2);
812 
814  ipn1->ipn_key->ipnk_sw_if_index,
815  ipn2->ipn_key->ipnk_sw_if_index);
816  if (!cmp)
817  cmp = ip46_address_cmp (&ipn1->ipn_key->ipnk_ip, &ipn2->ipn_key->ipnk_ip);
818  return cmp;
819 }
820 
821 static index_t *
823 {
824  index_t *ipnis = NULL;
825  ip_neighbor_t *ipn;
826 
827  /* *INDENT-OFF* */
828  pool_foreach (ipn, ip_neighbor_pool,
829  ({
830  if ((sw_if_index == ~0 ||
831  ipn->ipn_key->ipnk_sw_if_index == sw_if_index) &&
832  (IP46_TYPE_ANY == type ||
833  ipn->ipn_key->ipnk_type == type))
834  vec_add1 (ipnis, ip_neighbor_get_index(ipn));
835  }));
836 
837  /* *INDENT-ON* */
838 
839  if (ipnis)
841  return ipnis;
842 }
843 
844 static clib_error_t *
846  unformat_input_t * input,
848 {
849  ip_neighbor_elt_t *elt, *head;
850 
851  head = pool_elt_at_index (ip_neighbor_elt_pool,
852  ip_neighbor_list_head[type]);
853 
854 
855  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
856  "Flags", "Ethernet", "Interface");
857 
858  /* *INDENT-OFF*/
859  /* the list is time sorted, newest first, so start from the back
860  * and work forwards. Stop when we get to one that is alive */
861  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
862  ipne_anchor, head, elt,
863  ({
865  }));
866  /* *INDENT-ON*/
867 
868  return (NULL);
869 }
870 
871 static clib_error_t *
873  unformat_input_t * input,
875 {
876  index_t *ipni, *ipnis = NULL;
878 
879  /* Filter entries by interface if given. */
880  sw_if_index = ~0;
882  &sw_if_index);
883 
884  ipnis = ip_neighbor_entries (sw_if_index, type);
885 
886  if (ipnis)
887  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
888  "Flags", "Ethernet", "Interface");
889 
890  vec_foreach (ipni, ipnis)
891  {
892  vlib_cli_output (vm, "%U", format_ip_neighbor, *ipni);
893  }
894  vec_free (ipnis);
895 
896  return (NULL);
897 }
898 
899 static clib_error_t *
901  unformat_input_t * input, vlib_cli_command_t * cmd)
902 {
903  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_ANY));
904 }
905 
906 static clib_error_t *
908  unformat_input_t * input, vlib_cli_command_t * cmd)
909 {
910  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_IP6));
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, IP46_TYPE_IP4));
918 }
919 
920 static clib_error_t *
922  unformat_input_t * input, vlib_cli_command_t * cmd)
923 {
924  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP6));
925 }
926 
927 static clib_error_t *
929  unformat_input_t * input, vlib_cli_command_t * cmd)
930 {
931  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP4));
932 }
933 
934 /*?
935  * Display all the IP neighbor entries.
936  *
937  * @cliexpar
938  * Example of how to display the IPv4 ARP table:
939  * @cliexstart{show ip neighbor}
940  * Time FIB IP4 Flags Ethernet Interface
941  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
942  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
943  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
944  * Proxy arps enabled for:
945  * Fib_index 0 6.0.0.1 - 6.0.0.11
946  * @cliexend
947  ?*/
948 /* *INDENT-OFF* */
949 VLIB_CLI_COMMAND (show_ip_neighbors_cmd_node, static) = {
950  .path = "show ip neighbors",
951  .function = ip_neighbor_show,
952  .short_help = "show ip neighbors [interface]",
953 };
954 VLIB_CLI_COMMAND (show_ip4_neighbors_cmd_node, static) = {
955  .path = "show ip4 neighbors",
956  .function = ip4_neighbor_show,
957  .short_help = "show ip4 neighbors [interface]",
958 };
959 VLIB_CLI_COMMAND (show_ip6_neighbors_cmd_node, static) = {
960  .path = "show ip6 neighbors",
961  .function = ip6_neighbor_show,
962  .short_help = "show ip6 neighbors [interface]",
963 };
964 VLIB_CLI_COMMAND (show_ip_neighbor_cmd_node, static) = {
965  .path = "show ip neighbor",
966  .function = ip_neighbor_show,
967  .short_help = "show ip neighbor [interface]",
968 };
969 VLIB_CLI_COMMAND (show_ip4_neighbor_cmd_node, static) = {
970  .path = "show ip4 neighbor",
971  .function = ip4_neighbor_show,
972  .short_help = "show ip4 neighbor [interface]",
973 };
974 VLIB_CLI_COMMAND (show_ip6_neighbor_cmd_node, static) = {
975  .path = "show ip6 neighbor",
976  .function = ip6_neighbor_show,
977  .short_help = "show ip6 neighbor [interface]",
978 };
979 VLIB_CLI_COMMAND (show_ip4_neighbor_sorted_cmd_node, static) = {
980  .path = "show ip4 neighbor-sorted",
981  .function = ip4_neighbor_show_sorted,
982  .short_help = "show ip4 neighbor-sorted",
983 };
984 VLIB_CLI_COMMAND (show_ip6_neighbor_sorted_cmd_node, static) = {
985  .path = "show ip6 neighbor-sorted",
986  .function = ip6_neighbor_show_sorted,
987  .short_help = "show ip6 neighbor-sorted",
988 };
989 /* *INDENT-ON* */
990 
991 static ip_neighbor_vft_t ip_nbr_vfts[IP46_N_TYPES];
992 
993 void
995 {
996  ip_nbr_vfts[type] = *vft;
997 }
998 
999 void
1000 ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * dst)
1001 {
1003  adj->rewrite_header.sw_if_index))
1004  return;
1005 
1006  switch (adj->ia_nh_proto)
1007  {
1008  case FIB_PROTOCOL_IP6:
1009  ip6_neighbor_probe_dst (adj, &dst->ip6);
1010  break;
1011  case FIB_PROTOCOL_IP4:
1012  ip4_neighbor_probe_dst (adj, &dst->ip4);
1013  break;
1014  case FIB_PROTOCOL_MPLS:
1015  ASSERT (0);
1016  break;
1017  }
1018 }
1019 
1020 void
1022 {
1023  ip_neighbor_probe_dst (adj, &adj->sub_type.nbr.next_hop);
1024 }
1025 
1026 void
1028  ip46_type_t type,
1029  const ip46_address_t * addr, u32 sw_if_index)
1030 {
1031  vnet_main_t *vnm = vnet_get_main ();
1032 
1033  if (type == IP46_TYPE_IP4 || type == IP46_TYPE_BOTH)
1034  ip4_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip4 : NULL);
1035  if (type == IP46_TYPE_IP6 || type == IP46_TYPE_BOTH)
1036  ip6_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip6 : NULL);
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[type].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[type].ipndb_hash) <= sw_if_index)
1066  return;
1067  hash = ip_neighbor_db[type].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[IP46_TYPE_IP4].inv_proxy4_add)
1085  {
1086  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_add
1087  (fib_index, start, end));
1088  }
1089 
1090  return (-1);
1091 }
1092 
1093 int
1095  const ip4_address_t * start,
1096  const ip4_address_t * end)
1097 {
1098  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del)
1099  {
1100  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del
1101  (fib_index, start, end));
1102  }
1103  return -1;
1104 }
1105 
1106 int
1108 {
1109  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable)
1110  {
1111  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable (sw_if_index));
1112  }
1113  return -1;
1114 }
1115 
1116 int
1118 {
1119  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable)
1120  {
1121  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable (sw_if_index));
1122  }
1123  return -1;
1124 }
1125 
1126 int
1127 ip6_neighbor_proxy_add (u32 sw_if_index, const ip6_address_t * addr)
1128 {
1129  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add)
1130  {
1131  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add (sw_if_index, addr));
1132  }
1133  return -1;
1134 }
1135 
1136 int
1137 ip6_neighbor_proxy_del (u32 sw_if_index, const ip6_address_t * addr)
1138 {
1139  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del)
1140  {
1141  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del (sw_if_index, addr));
1142  }
1143  return -1;
1144 }
1145 
1146 static void
1148  u32 sw_if_index, uword opaque)
1149 {
1150  ip_neighbor_t *ipn;
1151  adj_index_t ai;
1152 
1153  IP_NEIGHBOR_DBG ("mac-change: %U",
1155  sw_if_index);
1156 
1157  /* *INDENT-OFF* */
1158  pool_foreach (ipn, ip_neighbor_pool,
1159  ({
1160  if (ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1163  &ipn->ipn_key->ipnk_ip,
1165  ipn);
1166  }));
1167  /* *INDENT-ON* */
1168 
1169  ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
1170 
1171  if (ADJ_INDEX_INVALID != ai)
1173 }
1174 
1175 void
1177 {
1178  index_t *ipnis = NULL, *ipni;
1179  ip_neighbor_t *ipn;
1180 
1181  IP_NEIGHBOR_DBG ("populate: %U %U",
1183  sw_if_index, format_ip46_type, type);
1184 
1185  /* *INDENT-OFF* */
1186  pool_foreach (ipn, ip_neighbor_pool,
1187  ({
1188  if (ipn->ipn_key->ipnk_type == type &&
1189  ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1190  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1191  }));
1192  /* *INDENT-ON* */
1193 
1194  vec_foreach (ipni, ipnis)
1195  {
1196  ipn = ip_neighbor_get (*ipni);
1197 
1200  &ipn->ipn_key->ipnk_ip,
1202  }
1203  vec_free (ipnis);
1204 }
1205 
1206 void
1208 {
1209  index_t *ipnis = NULL, *ipni;
1210  ip_neighbor_t *ipn;
1211 
1212  IP_NEIGHBOR_DBG ("flush: %U %U",
1214  sw_if_index, format_ip46_type, type);
1215 
1216  /* *INDENT-OFF* */
1217  pool_foreach (ipn, ip_neighbor_pool,
1218  ({
1219  if (ipn->ipn_key->ipnk_type == type &&
1220  ipn->ipn_key->ipnk_sw_if_index == sw_if_index &&
1221  ip_neighbor_is_dynamic (ipn))
1222  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1223  }));
1224  /* *INDENT-ON* */
1225 
1226  vec_foreach (ipni, ipnis) ip_neighbor_destroy (ip_neighbor_get (*ipni));
1227  vec_free (ipnis);
1228 }
1229 
1230 static walk_rc_t
1232 {
1233  ip_neighbor_t *ipn;
1234 
1235  ipn = ip_neighbor_get (ipni);
1236 
1237  ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STALE;
1238 
1239  return (WALK_CONTINUE);
1240 }
1241 
1242 void
1244 {
1245  ip_neighbor_walk (type, ~0, ip_neighbor_mark_one, NULL);
1246 }
1247 
1249 {
1252 
1253 static walk_rc_t
1255 {
1257  ip_neighbor_t *ipn;
1258 
1259  ipn = ip_neighbor_get (ipni);
1260 
1261  if (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STALE)
1262  {
1263  vec_add1 (ctx->ipnsc_stale, ipni);
1264  }
1265 
1266  return (WALK_CONTINUE);
1267 }
1268 
1269 void
1271 {
1273  index_t *ipni;
1274 
1275  ip_neighbor_walk (type, ~0, ip_neighbor_sweep_one, &ctx);
1276 
1277  vec_foreach (ipni, ctx.ipnsc_stale)
1278  {
1280  }
1281  vec_free (ctx.ipnsc_stale);
1282 }
1283 
1284 /*
1285  * Remove any arp entries associated with the specified interface
1286  */
1287 static clib_error_t *
1290 {
1291  ip46_type_t type;
1292 
1293  IP_NEIGHBOR_DBG ("interface-admin: %U %s",
1295  sw_if_index,
1296  (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ? "up" : "down"));
1297 
1298  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1299  {
1300  FOREACH_IP46_TYPE (type) ip_neighbor_populate (type, sw_if_index);
1301  }
1302  else
1303  {
1304  /* admin down, flush all neighbours */
1305  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, sw_if_index);
1306  }
1307 
1308  return (NULL);
1309 }
1310 
1312 
1313 /*
1314  * Remove any arp entries associated with the specified interface
1315  */
1316 static clib_error_t *
1318  u32 sw_if_index, u32 is_add)
1319 {
1320  IP_NEIGHBOR_DBG ("interface-change: %U %s",
1322  sw_if_index, (is_add ? "add" : "del"));
1323 
1324  if (!is_add && sw_if_index != ~0)
1325  {
1326  ip46_type_t type;
1327 
1328  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, sw_if_index);
1329  }
1330 
1331  return (NULL);
1332 }
1333 
1335 
1337 {
1339  ip46_address_t addr;
1343 
1344 static walk_rc_t
1346 {
1348  ip_neighbor_t *ipn;
1349 
1350  ipn = ip_neighbor_get (ipni);
1351 
1352  ASSERT (ipn->ipn_key->ipnk_type == ctx->type);
1353 
1354  if (IP46_TYPE_IP4 == ctx->type)
1355  {
1357  &ipn->ipn_key->ipnk_ip.ip4,
1358  &ctx->addr.ip4,
1359  ctx->length) &&
1360  ip_neighbor_is_dynamic (ipn))
1361  {
1362  vec_add1 (ctx->ipnis, ip_neighbor_get_index (ipn));
1363  }
1364  }
1365  return (WALK_CONTINUE);
1366 }
1367 
1368 
1369 /*
1370  * callback when an interface address is added or deleted
1371  */
1372 static void
1374  uword opaque,
1375  u32 sw_if_index,
1377  u32 address_length,
1378  u32 if_address_index, u32 is_del)
1379 {
1380  /*
1381  * Flush the ARP cache of all entries covered by the address
1382  * that is being removed.
1383  */
1384  IP_NEIGHBOR_DBG ("addr-%d: %U, %U/%d",
1385  (is_del ? "del" : "add"),
1387  sw_if_index, format_ip4_address, address, address_length);
1388 
1389  if (is_del)
1390  {
1392  .addr.ip4 = *address,
1393  .type = IP46_TYPE_IP4,
1394  .length = address_length,
1395  };
1396  index_t *ipni;
1397 
1398  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1399  ip_neighbor_walk_covered, &ctx);
1400 
1401  vec_foreach (ipni, ctx.ipnis)
1403 
1404  vec_free (ctx.ipnis);
1405  }
1406 }
1407 
1408 /*
1409  * callback when an interface address is added or deleted
1410  */
1411 static void
1413  uword opaque,
1414  u32 sw_if_index,
1415  ip6_address_t * address,
1416  u32 address_length,
1417  u32 if_address_index, u32 is_del)
1418 {
1419  /*
1420  * Flush the ARP cache of all entries covered by the address
1421  * that is being removed.
1422  */
1423  IP_NEIGHBOR_DBG ("addr-change: %U, %U/%d %s",
1425  sw_if_index, format_ip6_address, address, address_length,
1426  (is_del ? "del" : "add"));
1427 
1428  if (is_del)
1429  {
1431  .addr.ip6 = *address,
1432  .type = IP46_TYPE_IP6,
1433  .length = address_length,
1434  };
1435  index_t *ipni;
1436 
1437  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1438  ip_neighbor_walk_covered, &ctx);
1439 
1440  vec_foreach (ipni, ctx.ipnis)
1442 
1443  vec_free (ctx.ipnis);
1444  }
1445 }
1446 
1448 {
1452 
1453 static walk_rc_t
1455 {
1457  ip_neighbor_t *ipn;
1458 
1459  ipn = ip_neighbor_get (ipni);
1462 
1463  return (WALK_CONTINUE);
1464 }
1465 
1466 static void
1468  uword opaque,
1469  u32 sw_if_index,
1470  u32 new_fib_index, u32 old_fib_index)
1471 {
1473  .old_fib_index = old_fib_index,
1474  .new_fib_index = new_fib_index,
1475  };
1476 
1477  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1479 }
1480 
1481 static void
1483  uword opaque,
1484  u32 sw_if_index,
1485  u32 new_fib_index, u32 old_fib_index)
1486 {
1488  .old_fib_index = old_fib_index,
1489  .new_fib_index = new_fib_index,
1490  };
1491 
1492  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1494 }
1495 
1497 {
1502 
1503 #define IP_NEIGHBOR_PROCESS_SLEEP_LONG (0)
1504 
1507 {
1508  ip_neighbor_t *ipn;
1509  u32 ipndb_age;
1510  u32 ttl;
1511 
1512  ipn = ip_neighbor_get (ipni);
1513  ipndb_age = ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age;
1514  ttl = now - ipn->ipn_time_last_updated;
1515  *wait = ipndb_age;
1516 
1517  if (ttl > ipndb_age)
1518  {
1519  IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
1520  format_ip_neighbor, ipni, now,
1521  ipn->ipn_time_last_updated, ipndb_age);
1522  if (ipn->ipn_n_probes > 2)
1523  {
1524  /* 3 strikes and yea-re out */
1525  IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
1526  *wait = 1;
1527  return (IP_NEIGHBOR_AGE_DEAD);
1528  }
1529  else
1530  {
1531  adj_index_t ai;
1532 
1535 
1536  if (ADJ_INDEX_INVALID != ai)
1538 
1539  ipn->ipn_n_probes++;
1540  *wait = 1;
1541  }
1542  }
1543  else
1544  {
1545  /* here we are sure that ttl <= ipndb_age */
1546  *wait = ipndb_age - ttl + 1;
1547  return (IP_NEIGHBOR_AGE_ALIVE);
1548  }
1549 
1550  return (IP_NEIGHBOR_AGE_PROBE);
1551 }
1552 
1554 {
1557 
1558 static uword
1560  vlib_node_runtime_t * rt,
1562 {
1563  uword event_type, *event_data = NULL;
1564  f64 timeout;
1565 
1566  /* Set the timeout to an effectively infinite value when the process starts */
1568 
1569  while (1)
1570  {
1571  f64 now;
1572 
1573  if (!timeout)
1575  else
1577 
1578  event_type = vlib_process_get_events (vm, &event_data);
1579  vec_reset_length (event_data);
1580 
1581  now = vlib_time_now (vm);
1582 
1583  switch (event_type)
1584  {
1585  case ~0:
1586  {
1587  /* timer expired */
1588  ip_neighbor_elt_t *elt, *head;
1589  f64 wait;
1590 
1591  timeout = ip_neighbor_db[type].ipndb_age;
1592  head = pool_elt_at_index (ip_neighbor_elt_pool,
1593  ip_neighbor_list_head[type]);
1594 
1595  /* *INDENT-OFF*/
1596  /* the list is time sorted, newest first, so start from the back
1597  * and work forwards. Stop when we get to one that is alive */
1598  restart:
1599  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
1600  ipne_anchor, head, elt,
1601  ({
1603 
1604  res = ip_neighbour_age_out(elt->ipne_index, now, &wait);
1605 
1606  if (IP_NEIGHBOR_AGE_ALIVE == res) {
1607  /* the oldest neighbor has not yet expired, go back to sleep */
1608  timeout = clib_min (wait, timeout);
1609  break;
1610  }
1611  else if (IP_NEIGHBOR_AGE_DEAD == res) {
1612  /* the oldest neighbor is dead, pop it, then restart the walk
1613  * again from the back */
1615  goto restart;
1616  }
1617 
1618  timeout = clib_min (wait, timeout);
1619  }));
1620  /* *INDENT-ON* */
1621  break;
1622  }
1624  {
1625 
1626  if (!ip_neighbor_db[type].ipndb_age)
1627  {
1628  /* aging has been disabled */
1629  timeout = 0;
1630  break;
1631  }
1632  ip_neighbor_elt_t *elt, *head;
1633 
1634  head = pool_elt_at_index (ip_neighbor_elt_pool,
1635  ip_neighbor_list_head[type]);
1636  /* no neighbors yet */
1637  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
1638  {
1639  timeout = ip_neighbor_db[type].ipndb_age;
1640  break;
1641  }
1642 
1643  /* poke the oldset neighbour for aging, which returns how long we sleep for */
1644  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
1645  ip_neighbour_age_out (elt->ipne_index, now, &timeout);
1646  break;
1647  }
1648  }
1649  }
1650  return 0;
1651 }
1652 
1653 static uword
1656 {
1657  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP4));
1658 }
1659 
1660 static uword
1663 {
1664  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP6));
1665 }
1666 
1667 /* *INDENT-OFF* */
1669  .function = ip4_neighbor_age_process,
1670  .type = VLIB_NODE_TYPE_PROCESS,
1671  .name = "ip4-neighbor-age-process",
1672 };
1674  .function = ip6_neighbor_age_process,
1675  .type = VLIB_NODE_TYPE_PROCESS,
1676  .name = "ip6-neighbor-age-process",
1677 };
1678 /* *INDENT-ON* */
1679 
1680 int
1681 ip_neighbor_config (ip46_type_t type, u32 limit, u32 age, bool recycle)
1682 {
1683  ip_neighbor_db[type].ipndb_limit = limit;
1684  ip_neighbor_db[type].ipndb_recycle = recycle;
1685  ip_neighbor_db[type].ipndb_age = age;
1686 
1688  (IP46_TYPE_IP4 == type ?
1692 
1693  return (0);
1694 }
1695 
1696 static clib_error_t *
1698  unformat_input_t * input, vlib_cli_command_t * cmd)
1699 {
1700  ip46_type_t type;
1701 
1702  /* *INDENT-OFF* */
1703  FOREACH_IP46_TYPE(type) {
1704  vlib_cli_output (vm, "%U:", format_ip46_type, type);
1705  vlib_cli_output (vm, " limit:%d, age:%d, recycle:%d",
1706  ip_neighbor_db[type].ipndb_limit,
1707  ip_neighbor_db[type].ipndb_age,
1708  ip_neighbor_db[type].ipndb_recycle);
1709  }
1710 
1711  /* *INDENT-ON* */
1712  return (NULL);
1713 }
1714 
1715 /* *INDENT-OFF* */
1716 VLIB_CLI_COMMAND (show_ip_neighbor_cfg_cmd_node, static) = {
1717  .path = "show ip neighbor-config",
1718  .function = ip_neighbor_config_show,
1719  .short_help = "show ip neighbor-config",
1720 };
1721 /* *INDENT-ON* */
1722 
1723 static clib_error_t *
1725 {
1726  {
1729  };
1731  }
1732  {
1735  };
1737  }
1738  {
1741  };
1743  }
1744  {
1747  };
1749  }
1750  {
1752  .function = ip_neighbor_ethernet_change_mac,
1753  .function_opaque = 0,
1754  };
1756  }
1757 
1758  ipn_logger = vlib_log_register_class ("ip", "neighbor");
1759 
1760  ip46_type_t type;
1761 
1762  FOREACH_IP46_TYPE (type)
1764  clib_llist_make_head (ip_neighbor_elt_pool, ipne_anchor);
1765 
1766  return (NULL);
1767 }
1768 
1769 /* *INDENT-OFF* */
1771 {
1772  .runs_after = VLIB_INITS("ip_main_init"),
1773 };
1774 /* *INDENT-ON* */
1775 
1776 /*
1777  * fd.io coding-style-patch-verification: ON
1778  *
1779  * Local Variables:
1780  * eval: (c-set-style "gnu")
1781  * End:
1782  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
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:323
static walk_rc_t ip_neighbor_walk_table_bind(index_t ipni, void *arg)
Definition: ip_neighbor.c:1454
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:663
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:234
const mac_address_t * ip_neighbor_get_mac(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:121
void ip_neighbor_flush(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:1207
#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:327
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:1373
ip4_table_bind_function_t * function
Definition: ip4.h:93
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:239
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:140
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:103
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:1000
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:255
ip46_type_t fib_proto_to_ip46(fib_protocol_t fproto)
Convert from fib_protocol to ip46_type.
Definition: fib_types.c:374
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:907
void ip_neighbor_del_all(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:600
const ip46_address_t * ip_neighbor_get_ip(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:115
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:458
void ip_neighbor_sweep(ip46_type_t type)
Definition: ip_neighbor.c:1270
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:1673
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:507
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:333
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:701
IP unicast adjacency.
Definition: adj.h:227
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:1412
#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
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1218
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:1467
static ip_neighbor_age_state_t ip_neighbour_age_out(index_t ipni, f64 now, f64 *wait)
Definition: ip_neighbor.c:1506
int ip_neighbor_config(ip46_type_t type, u32 limit, u32 age, bool recycle)
Definition: ip_neighbor.c:1681
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:200
vlib_main_t * vm
Definition: in2out_ed.c:1582
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:914
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:133
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:1668
static clib_error_t * ip_neighbor_interface_admin_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip_neighbor.c:1288
Definition: fib_entry.h:114
vhost_vring_addr_t addr
Definition: vhost_user.h:111
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:331
int ip_neighbor_del(const ip46_address_t *ip, ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:557
#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:286
#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: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:459
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:1021
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#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
static void ip_neighbor_db_remove(const ip_neighbor_key_t *key)
Definition: ip_neighbor.c:202
static int ip46_address_cmp(const ip46_address_t *ip46_1, const ip46_address_t *ip46_2)
Definition: ip46_address.h:80
int ip4_neighbor_proxy_delete(u32 fib_index, const ip4_address_t *start, const ip4_address_t *end)
Definition: ip_neighbor.c:1094
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
#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:400
Aggregate type for a prefix.
Definition: fib_types.h:203
#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:1654
void ip_neighbor_populate(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:1176
u16 fp_len
The mask length.
Definition: fib_types.h:207
u8 * format_ip_neighbor(u8 *s, va_list *va)
union ip_adjacency_t_::@149 sub_type
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:390
#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:534
#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_neighbor_mark(ip46_type_t type)
Definition: ip_neighbor.c:1243
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:1553
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:921
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:994
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:872
#define IP_NEIGHBOR_INFO(...)
Definition: ip_neighbor.c:84
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
ip6_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip6.h:220
static walk_rc_t ip_neighbor_del_all_walk_cb(index_t ipni, void *arg)
Definition: ip_neighbor.c:590
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:2781
static index_t * ip_neighbor_entries(u32 sw_if_index, ip46_type_t type)
Definition: ip_neighbor.c:822
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:1661
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:1291
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:217
static walk_rc_t ip_neighbor_sweep_one(index_t ipni, void *arg)
Definition: ip_neighbor.c:1254
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:1503
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:1697
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:804
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:1724
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:1482
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:1147
static adj_walk_rc_t ip_neighbor_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:356
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
void ip_neighbor_walk(ip46_type_t type, u32 sw_if_index, ip_neighbor_walk_cb_t cb, void *ctx)
Definition: ip_neighbor.c:1040
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:74
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:1559
struct ip_neighbor_del_all_ctx_t_ ip_neighbor_del_all_ctx_t
static ip_neighbor_t * ip_neighbor_db_find(const ip_neighbor_key_t *key)
Definition: ip_neighbor.c:214
Virtual function Table for neighbor protocol implementations to register.
Definition: ip_neighbor.h:105
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:299
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:1345
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:183
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
This packets follow a mid-chain adjacency.
Definition: adj.h:76
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:106
static adj_walk_rc_t ip_neighbor_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: ip_neighbor.c:366
u32 stats_index
Definition: ip.api:143
#define ASSERT(truth)
static u8 ip46_type_pfx_len(ip46_type_t type)
Definition: ip_neighbor.c:233
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
manual_print typedef address
Definition: ip_types.api:85
const mac_address_t ZERO_MAC_ADDRESS
Definition: mac_address.c:19
#define FOREACH_IP46_TYPE(_type)
Definition: ip46_address.h:32
struct ip_neighbor_sweep_ctx_t_ ip_neighbor_sweep_ctx_t
struct ip_adjacency_t_::@149::@150 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
void ip_neighbor_learn(const ip_neighbor_learn_t *l)
Definition: ip_neighbor.c:694
IPv4 main type.
Definition: ip4.h:106
int ip6_neighbor_proxy_add(u32 sw_if_index, const ip6_address_t *addr)
Definition: ip_neighbor.c:1127
static void clib_mem_free(void *p)
Definition: mem.h:215
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:324
int ip4_neighbor_proxy_disable(u32 sw_if_index)
Definition: ip_neighbor.c:1117
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:722
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:157
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 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:1107
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:147
typedef key
Definition: ipsec_types.api:85
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:342
static void ip_neighbor_refresh(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:150
vl_api_address_t ip
Definition: l2.api:501
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
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:374
#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:329
static clib_error_t * ip_neighbor_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_neighbor.c:900
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:1027
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:116
void ip6_ll_table_entry_delete(const ip6_ll_prefix_t *ilp)
Delete a IP6 link-local entry.
Definition: ip6_ll_table.c:140
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:421
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:1144
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:928
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:845
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:1317
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:358
#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:1137
static walk_rc_t ip_neighbor_mark_one(index_t ipni, void *ctx)
Definition: ip_neighbor.c:1231
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:106
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)
static bool ip_neighbor_is_dynamic(const ip_neighbor_t *ipn)
Definition: ip_neighbor.c:109
#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:342
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip_neighbor_age_state_t_
Definition: ip_neighbor.c:1496
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:620
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:127
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