FD.io VPP  v20.09-rc2-28-g3c5414029
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  &ipn->ipn_key->ipnk_ip,
384  (ipn,
387  ipn->ipn_key->ipnk_sw_if_index));
388 
391  clib_mem_free (ipn->ipn_key);
392 
393  pool_put (ip_neighbor_pool, ipn);
394 }
395 
396 static bool
398 {
399  if (!ip_neighbor_db[type].ipndb_recycle)
400  return false;
401 
402  /* pluck the oldest entry, which is the one from the end of the list */
403  ip_neighbor_elt_t *elt, *head;
404 
405  head =
406  pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[type]);
407 
408  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
409  return (false);
410 
411  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
413 
414  return (true);
415 }
416 
417 static ip_neighbor_t *
420 {
421  ip_neighbor_t *ipn;
422 
423  if (ip_neighbor_db[key->ipnk_type].ipndb_limit &&
424  (ip_neighbor_db[key->ipnk_type].ipndb_n_elts >=
425  ip_neighbor_db[key->ipnk_type].ipndb_limit))
426  {
428  return (NULL);
429  }
430 
431  pool_get_zero (ip_neighbor_pool, ipn);
432 
433  ipn->ipn_key = clib_mem_alloc (sizeof (*ipn->ipn_key));
434  clib_memcpy (ipn->ipn_key, key, sizeof (*ipn->ipn_key));
435 
437  ipn->ipn_flags = flags;
438  ipn->ipn_elt = ~0;
439 
440  mac_address_copy (&ipn->ipn_mac, mac);
441 
442  ip_neighbor_db_add (ipn);
443 
444  /* create the adj-fib. the entry in the FIB table for the peer's interface */
445  if (!(ipn->ipn_flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY))
449  ipn->ipn_key->ipnk_sw_if_index));
450 
451  return (ipn);
452 }
453 
454 int
455 ip_neighbor_add (const ip46_address_t * ip,
457  const mac_address_t * mac,
460 {
461  fib_protocol_t fproto;
462  ip_neighbor_t *ipn;
463 
464  /* main thread only */
465  ASSERT (0 == vlib_get_thread_index ());
466 
467  fproto = fib_proto_from_ip46 (type);
468 
469  const ip_neighbor_key_t key = {
470  .ipnk_ip = *ip,
471  .ipnk_sw_if_index = sw_if_index,
472  .ipnk_type = type,
473  };
474 
475  ipn = ip_neighbor_db_find (&key);
476 
477  if (ipn)
478  {
479  IP_NEIGHBOR_DBG ("update: %U, %U",
481  sw_if_index, format_ip46_address, ip, type,
483  mac);
484 
485  ip_neighbor_touch (ipn);
486 
487  /* Refuse to over-write static neighbor entry. */
488  if (!(flags & IP_NEIGHBOR_FLAG_STATIC) &&
489  (ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
490  {
491  /* if MAC address match, still check to send event */
492  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
493  goto check_customers;
494  return -2;
495  }
496 
497  /* A dynamic entry can become static, but not vice-versa.
498  * i.e. since if it was programmed by the CP then it must
499  * be removed by the CP */
500  if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
501  !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
502  {
504  ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STATIC;
505  ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
506  }
507 
508  /*
509  * prevent a DoS attack from the data-plane that
510  * spams us with no-op updates to the MAC address
511  */
512  if (0 == mac_address_cmp (&ipn->ipn_mac, mac))
513  {
514  ip_neighbor_refresh (ipn);
515  goto check_customers;
516  }
517 
518  mac_address_copy (&ipn->ipn_mac, mac);
519  }
520  else
521  {
522  IP_NEIGHBOR_INFO ("add: %U, %U",
524  sw_if_index, format_ip46_address, ip, type,
526  mac);
527 
528  ipn = ip_neighbor_alloc (&key, mac, flags);
529 
530  if (NULL == ipn)
531  return VNET_API_ERROR_LIMIT_EXCEEDED;
532  }
533 
534  /* Update time stamp and flags. */
535  ip_neighbor_refresh (ipn);
536 
538  fproto, &ipn->ipn_key->ipnk_ip,
540 
541 check_customers:
542  /* Customer(s) requesting event for this address? */
544 
545  if (stats_index)
546  *stats_index = adj_nbr_find (fproto,
547  fib_proto_to_link (fproto),
548  &ipn->ipn_key->ipnk_ip,
549  ipn->ipn_key->ipnk_sw_if_index);
550  return 0;
551 }
552 
553 int
554 ip_neighbor_del (const ip46_address_t * ip, ip46_type_t type, u32 sw_if_index)
555 {
556  ip_neighbor_t *ipn;
557 
558  /* main thread only */
559  ASSERT (0 == vlib_get_thread_index ());
560 
561  IP_NEIGHBOR_INFO ("delete: %U, %U",
563  sw_if_index, format_ip46_address, ip, type);
564 
565  const ip_neighbor_key_t key = {
566  .ipnk_ip = *ip,
567  .ipnk_sw_if_index = sw_if_index,
568  .ipnk_type = type,
569  };
570 
571  ipn = ip_neighbor_db_find (&key);
572 
573  if (NULL == ipn)
574  return (VNET_API_ERROR_NO_SUCH_ENTRY);
575 
576  ip_neighbor_free (ipn);
577 
578  return (0);
579 }
580 
582 {
585 
586 static walk_rc_t
588 {
590 
591  vec_add1 (ctx->ipn_del, ipni);
592 
593  return (WALK_CONTINUE);
594 }
595 
596 void
598 {
599  IP_NEIGHBOR_INFO ("delete-all: %U, %U",
600  format_ip46_type, type,
602  sw_if_index);
603 
605  .ipn_del = NULL,
606  };
607  index_t *ipni;
608 
609  ip_neighbor_walk (type, sw_if_index, ip_neighbor_del_all_walk_cb, &ctx);
610 
611  vec_foreach (ipni, ctx.ipn_del) ip_neighbor_free (ip_neighbor_get (*ipni));
612  vec_free (ctx.ipn_del);
613 }
614 
615 void
617 {
618  ip_neighbor_t *ipn;
619  ip_adjacency_t *adj;
620 
621  adj = adj_get (ai);
622 
624  .ipnk_ip = adj->sub_type.nbr.next_hop,
625  .ipnk_type = fib_proto_to_ip46 (adj->ia_nh_proto),
626  .ipnk_sw_if_index = adj->rewrite_header.sw_if_index,
627  };
628  ipn = ip_neighbor_db_find (&key);
629 
630  switch (adj->lookup_next_index)
631  {
632  case IP_LOOKUP_NEXT_ARP:
633  if (NULL != ipn)
634  {
635  adj_nbr_walk_nh (adj->rewrite_header.sw_if_index,
636  adj->ia_nh_proto,
637  &ipn->ipn_key->ipnk_ip,
639  }
640  else
641  {
642  /*
643  * no matching ARP entry.
644  * construct the rewrite required to for an ARP packet, and stick
645  * that in the adj's pipe to smoke.
646  */
648  (ai,
651  (vnm,
652  adj->rewrite_header.sw_if_index,
655 
656  /*
657  * since the FIB has added this adj for a route, it makes sense it
658  * may want to forward traffic sometime soon. Let's send a
659  * speculative ARP. just one. If we were to do periodically that
660  * wouldn't be bad either, but that's more code than i'm prepared to
661  * write at this time for relatively little reward.
662  */
663  /*
664  * adj_nbr_update_rewrite may actually call fib_walk_sync.
665  * fib_walk_sync may allocate a new adjacency and potentially cause
666  * a realloc for adj_pool. When that happens, adj pointer is no
667  * longer valid here.x We refresh adj pointer accordingly.
668  */
669  adj = adj_get (ai);
670  ip_neighbor_probe (adj);
671  }
672  break;
676  case IP_LOOKUP_NEXT_DROP:
677  case IP_LOOKUP_NEXT_PUNT:
683  case IP_LOOKUP_N_NEXT:
684  ASSERT (0);
685  break;
686  }
687 }
688 
689 void
691 {
692  ip_neighbor_add (&l->ip, l->type, &l->mac, l->sw_if_index,
693  IP_NEIGHBOR_FLAG_DYNAMIC, NULL);
694 }
695 
696 static clib_error_t *
698  unformat_input_t * input, vlib_cli_command_t * cmd)
699 {
700  ip46_address_t ip = ip46_address_initializer;
702  vnet_main_t *vnm = vnet_get_main ();
704  u32 sw_if_index = ~0;
705  int is_add = 1;
706  int count = 1;
707 
708  flags = IP_NEIGHBOR_FLAG_DYNAMIC;
709 
711  {
712  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
713  if (unformat (input, "%U %U %U",
714  unformat_vnet_sw_interface, vnm, &sw_if_index,
716  unformat_mac_address_t, &mac))
717  ;
718  else if (unformat (input, "delete") || unformat (input, "del"))
719  is_add = 0;
720  else if (unformat (input, "static"))
721  {
722  flags |= IP_NEIGHBOR_FLAG_STATIC;
723  flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
724  }
725  else if (unformat (input, "no-fib-entry"))
726  flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
727  else if (unformat (input, "count %d", &count))
728  ;
729  else
730  break;
731  }
732 
733  if (sw_if_index == ~0 ||
735  return clib_error_return (0,
736  "specify interface, IP address and MAC: `%U'",
737  format_unformat_error, input);
738 
739  while (count)
740  {
741  if (is_add)
742  ip_neighbor_add (&ip, ip46_address_get_type (&ip), &mac, sw_if_index,
743  flags, NULL);
744  else
745  ip_neighbor_del (&ip, ip46_address_get_type (&ip), sw_if_index);
746 
748  mac_address_increment (&mac);
749 
750  --count;
751  }
752 
753  return NULL;
754 }
755 
756 /* *INDENT-OFF* */
757 /*?
758  * Add or delete IPv4 ARP cache entries.
759  *
760  * @note 'set ip neighbor' options (e.g. delete, static, 'fib-id <id>',
761  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
762  * any order and combination.
763  *
764  * @cliexpar
765  * @parblock
766  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
767  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
768  * @cliexcmd{set ip neighbor GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
769  * @cliexcmd{set ip neighbor delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
770  *
771  * To add or delete an IPv4 ARP cache entry to or from a specific fib
772  * table:
773  * @cliexcmd{set ip neighbor fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
774  * @cliexcmd{set ip neighbor fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
775  *
776  * Add or delete IPv4 static ARP cache entries as follows:
777  * @cliexcmd{set ip neighbor static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
778  * @cliexcmd{set ip neighbor static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
779  *
780  * For testing / debugging purposes, the 'set ip neighbor' command can add or
781  * delete multiple entries. Supply the 'count N' parameter:
782  * @cliexcmd{set ip neighbor count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
783  * @endparblock
784  ?*/
785 VLIB_CLI_COMMAND (ip_neighbor_command, static) = {
786  .path = "set ip neighbor",
787  .short_help =
788  "set ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
789  .function = ip_neighbor_cmd,
790 };
791 VLIB_CLI_COMMAND (ip_neighbor_command2, static) = {
792  .path = "ip neighbor",
793  .short_help =
794  "ip neighbor [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
795  .function = ip_neighbor_cmd,
796 };
797 /* *INDENT-ON* */
798 
799 static int
800 ip_neighbor_sort (void *a1, void *a2)
801 {
802  index_t *ipni1 = a1, *ipni2 = a2;
803  ip_neighbor_t *ipn1, *ipn2;
804  int cmp;
805 
806  ipn1 = ip_neighbor_get (*ipni1);
807  ipn2 = ip_neighbor_get (*ipni2);
808 
810  ipn1->ipn_key->ipnk_sw_if_index,
811  ipn2->ipn_key->ipnk_sw_if_index);
812  if (!cmp)
813  cmp = ip46_address_cmp (&ipn1->ipn_key->ipnk_ip, &ipn2->ipn_key->ipnk_ip);
814  return cmp;
815 }
816 
817 static index_t *
819 {
820  index_t *ipnis = NULL;
821  ip_neighbor_t *ipn;
822 
823  /* *INDENT-OFF* */
824  pool_foreach (ipn, ip_neighbor_pool,
825  ({
826  if ((sw_if_index == ~0 ||
827  ipn->ipn_key->ipnk_sw_if_index == sw_if_index) &&
828  (IP46_TYPE_ANY == type ||
829  ipn->ipn_key->ipnk_type == type))
830  vec_add1 (ipnis, ip_neighbor_get_index(ipn));
831  }));
832 
833  /* *INDENT-ON* */
834 
835  if (ipnis)
837  return ipnis;
838 }
839 
840 static clib_error_t *
842  unformat_input_t * input,
844 {
845  ip_neighbor_elt_t *elt, *head;
846 
847  head = pool_elt_at_index (ip_neighbor_elt_pool,
848  ip_neighbor_list_head[type]);
849 
850 
851  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
852  "Flags", "Ethernet", "Interface");
853 
854  /* *INDENT-OFF*/
855  /* the list is time sorted, newest first, so start from the back
856  * and work forwards. Stop when we get to one that is alive */
857  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
858  ipne_anchor, head, elt,
859  ({
861  }));
862  /* *INDENT-ON*/
863 
864  return (NULL);
865 }
866 
867 static clib_error_t *
869  unformat_input_t * input,
871 {
872  index_t *ipni, *ipnis = NULL;
874 
875  /* Filter entries by interface if given. */
876  sw_if_index = ~0;
878  &sw_if_index);
879 
880  ipnis = ip_neighbor_entries (sw_if_index, type);
881 
882  if (ipnis)
883  vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
884  "Flags", "Ethernet", "Interface");
885 
886  vec_foreach (ipni, ipnis)
887  {
888  vlib_cli_output (vm, "%U", format_ip_neighbor, *ipni);
889  }
890  vec_free (ipnis);
891 
892  return (NULL);
893 }
894 
895 static clib_error_t *
897  unformat_input_t * input, vlib_cli_command_t * cmd)
898 {
899  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_ANY));
900 }
901 
902 static clib_error_t *
904  unformat_input_t * input, vlib_cli_command_t * cmd)
905 {
906  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_IP6));
907 }
908 
909 static clib_error_t *
911  unformat_input_t * input, vlib_cli_command_t * cmd)
912 {
913  return (ip_neighbor_show_i (vm, input, cmd, IP46_TYPE_IP4));
914 }
915 
916 static clib_error_t *
918  unformat_input_t * input, vlib_cli_command_t * cmd)
919 {
920  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP6));
921 }
922 
923 static clib_error_t *
925  unformat_input_t * input, vlib_cli_command_t * cmd)
926 {
927  return (ip_neighbor_show_sorted_i (vm, input, cmd, IP46_TYPE_IP4));
928 }
929 
930 /*?
931  * Display all the IP neighbor entries.
932  *
933  * @cliexpar
934  * Example of how to display the IPv4 ARP table:
935  * @cliexstart{show ip neighbor}
936  * Time FIB IP4 Flags Ethernet Interface
937  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
938  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
939  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
940  * Proxy arps enabled for:
941  * Fib_index 0 6.0.0.1 - 6.0.0.11
942  * @cliexend
943  ?*/
944 /* *INDENT-OFF* */
945 VLIB_CLI_COMMAND (show_ip_neighbors_cmd_node, static) = {
946  .path = "show ip neighbors",
947  .function = ip_neighbor_show,
948  .short_help = "show ip neighbors [interface]",
949 };
950 VLIB_CLI_COMMAND (show_ip4_neighbors_cmd_node, static) = {
951  .path = "show ip4 neighbors",
952  .function = ip4_neighbor_show,
953  .short_help = "show ip4 neighbors [interface]",
954 };
955 VLIB_CLI_COMMAND (show_ip6_neighbors_cmd_node, static) = {
956  .path = "show ip6 neighbors",
957  .function = ip6_neighbor_show,
958  .short_help = "show ip6 neighbors [interface]",
959 };
960 VLIB_CLI_COMMAND (show_ip_neighbor_cmd_node, static) = {
961  .path = "show ip neighbor",
962  .function = ip_neighbor_show,
963  .short_help = "show ip neighbor [interface]",
964 };
965 VLIB_CLI_COMMAND (show_ip4_neighbor_cmd_node, static) = {
966  .path = "show ip4 neighbor",
967  .function = ip4_neighbor_show,
968  .short_help = "show ip4 neighbor [interface]",
969 };
970 VLIB_CLI_COMMAND (show_ip6_neighbor_cmd_node, static) = {
971  .path = "show ip6 neighbor",
972  .function = ip6_neighbor_show,
973  .short_help = "show ip6 neighbor [interface]",
974 };
975 VLIB_CLI_COMMAND (show_ip4_neighbor_sorted_cmd_node, static) = {
976  .path = "show ip4 neighbor-sorted",
977  .function = ip4_neighbor_show_sorted,
978  .short_help = "show ip4 neighbor-sorted",
979 };
980 VLIB_CLI_COMMAND (show_ip6_neighbor_sorted_cmd_node, static) = {
981  .path = "show ip6 neighbor-sorted",
982  .function = ip6_neighbor_show_sorted,
983  .short_help = "show ip6 neighbor-sorted",
984 };
985 /* *INDENT-ON* */
986 
987 static ip_neighbor_vft_t ip_nbr_vfts[IP46_N_TYPES];
988 
989 void
991 {
992  ip_nbr_vfts[type] = *vft;
993 }
994 
995 void
996 ip_neighbor_probe_dst (const ip_adjacency_t * adj, const ip46_address_t * dst)
997 {
999  adj->rewrite_header.sw_if_index))
1000  return;
1001 
1002  switch (adj->ia_nh_proto)
1003  {
1004  case FIB_PROTOCOL_IP6:
1005  ip6_neighbor_probe_dst (adj, &dst->ip6);
1006  break;
1007  case FIB_PROTOCOL_IP4:
1008  ip4_neighbor_probe_dst (adj, &dst->ip4);
1009  break;
1010  case FIB_PROTOCOL_MPLS:
1011  ASSERT (0);
1012  break;
1013  }
1014 }
1015 
1016 void
1018 {
1019  ip_neighbor_probe_dst (adj, &adj->sub_type.nbr.next_hop);
1020 }
1021 
1022 void
1024  ip46_type_t type,
1025  const ip46_address_t * addr, u32 sw_if_index)
1026 {
1027  vnet_main_t *vnm = vnet_get_main ();
1028 
1029  if (type == IP46_TYPE_IP4 || type == IP46_TYPE_BOTH)
1030  ip4_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip4 : NULL);
1031  if (type == IP46_TYPE_IP6 || type == IP46_TYPE_BOTH)
1032  ip6_neighbor_advertise (vm, vnm, sw_if_index, (addr) ? &addr->ip6 : NULL);
1033 }
1034 
1035 void
1038 {
1040  index_t ipni;
1041 
1042  if (~0 == sw_if_index)
1043  {
1044  uword **hash;
1045 
1046  vec_foreach (hash, ip_neighbor_db[type].ipndb_hash)
1047  {
1048  /* *INDENT-OFF* */
1049  hash_foreach (key, ipni, *hash,
1050  ({
1051  if (WALK_STOP == cb (ipni, ctx))
1052  break;
1053  }));
1054  /* *INDENT-ON* */
1055  }
1056  }
1057  else
1058  {
1059  uword *hash;
1060 
1061  if (vec_len (ip_neighbor_db[type].ipndb_hash) <= sw_if_index)
1062  return;
1063  hash = ip_neighbor_db[type].ipndb_hash[sw_if_index];
1064 
1065  /* *INDENT-OFF* */
1066  hash_foreach (key, ipni, hash,
1067  ({
1068  if (WALK_STOP == cb (ipni, ctx))
1069  break;
1070  }));
1071  /* *INDENT-ON* */
1072  }
1073 }
1074 
1075 int
1077  const ip4_address_t * start,
1078  const ip4_address_t * end)
1079 {
1080  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_add)
1081  {
1082  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_add
1083  (fib_index, start, end));
1084  }
1085 
1086  return (-1);
1087 }
1088 
1089 int
1091  const ip4_address_t * start,
1092  const ip4_address_t * end)
1093 {
1094  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del)
1095  {
1096  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_del
1097  (fib_index, start, end));
1098  }
1099  return -1;
1100 }
1101 
1102 int
1104 {
1105  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable)
1106  {
1107  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_enable (sw_if_index));
1108  }
1109  return -1;
1110 }
1111 
1112 int
1114 {
1115  if (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable)
1116  {
1117  return (ip_nbr_vfts[IP46_TYPE_IP4].inv_proxy4_disable (sw_if_index));
1118  }
1119  return -1;
1120 }
1121 
1122 int
1123 ip6_neighbor_proxy_add (u32 sw_if_index, const ip6_address_t * addr)
1124 {
1125  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add)
1126  {
1127  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_add (sw_if_index, addr));
1128  }
1129  return -1;
1130 }
1131 
1132 int
1133 ip6_neighbor_proxy_del (u32 sw_if_index, const ip6_address_t * addr)
1134 {
1135  if (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del)
1136  {
1137  return (ip_nbr_vfts[IP46_TYPE_IP6].inv_proxy6_del (sw_if_index, addr));
1138  }
1139  return -1;
1140 }
1141 
1142 static void
1144  u32 sw_if_index, uword opaque)
1145 {
1146  ip_neighbor_t *ipn;
1147  adj_index_t ai;
1148 
1149  IP_NEIGHBOR_DBG ("mac-change: %U",
1151  sw_if_index);
1152 
1153  /* *INDENT-OFF* */
1154  pool_foreach (ipn, ip_neighbor_pool,
1155  ({
1156  if (ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1159  &ipn->ipn_key->ipnk_ip,
1161  ipn);
1162  }));
1163  /* *INDENT-ON* */
1164 
1165  ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
1166 
1167  if (ADJ_INDEX_INVALID != ai)
1169 }
1170 
1171 void
1173 {
1174  index_t *ipnis = NULL, *ipni;
1175  ip_neighbor_t *ipn;
1176 
1177  IP_NEIGHBOR_DBG ("populate: %U %U",
1179  sw_if_index, format_ip46_type, type);
1180 
1181  /* *INDENT-OFF* */
1182  pool_foreach (ipn, ip_neighbor_pool,
1183  ({
1184  if (ipn->ipn_key->ipnk_type == type &&
1185  ipn->ipn_key->ipnk_sw_if_index == sw_if_index)
1186  vec_add1 (ipnis, ipn - ip_neighbor_pool);
1187  }));
1188  /* *INDENT-ON* */
1189 
1190  vec_foreach (ipni, ipnis)
1191  {
1192  ipn = ip_neighbor_get (*ipni);
1193 
1196  &ipn->ipn_key->ipnk_ip,
1198  }
1199  vec_free (ipnis);
1200 }
1201 
1202 void
1204 {
1205  index_t *ipnis = NULL, *ipni;
1206  ip_neighbor_t *ipn;
1207 
1208  IP_NEIGHBOR_DBG ("flush: %U %U",
1210  sw_if_index, format_ip46_type, type);
1211 
1212  /* *INDENT-OFF* */
1213  pool_foreach (ipn, ip_neighbor_pool,
1214  ({
1215  if (ipn->ipn_key->ipnk_type == type &&
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_free (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 (type, ~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 (type, ~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 {
1287  ip46_type_t type;
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  FOREACH_IP46_TYPE (type) ip_neighbor_populate (type, sw_if_index);
1297  }
1298  else
1299  {
1300  /* admin down, flush all neighbours */
1301  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, 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  {
1322  ip46_type_t type;
1323 
1324  FOREACH_IP46_TYPE (type) ip_neighbor_flush (type, sw_if_index);
1325  }
1326 
1327  return (NULL);
1328 }
1329 
1331 
1333 {
1335  ip46_address_t addr;
1339 
1340 static walk_rc_t
1342 {
1344  ip_neighbor_t *ipn;
1345 
1346  ipn = ip_neighbor_get (ipni);
1347 
1348  ASSERT (ipn->ipn_key->ipnk_type == ctx->type);
1349 
1350  if (IP46_TYPE_IP4 == ctx->type)
1351  {
1353  &ipn->ipn_key->ipnk_ip.ip4,
1354  &ctx->addr.ip4,
1355  ctx->length) &&
1356  ip_neighbor_is_dynamic (ipn))
1357  {
1358  vec_add1 (ctx->ipnis, ip_neighbor_get_index (ipn));
1359  }
1360  }
1361  return (WALK_CONTINUE);
1362 }
1363 
1364 
1365 /*
1366  * callback when an interface address is added or deleted
1367  */
1368 static void
1370  uword opaque,
1371  u32 sw_if_index,
1373  u32 address_length,
1374  u32 if_address_index, u32 is_del)
1375 {
1376  /*
1377  * Flush the ARP cache of all entries covered by the address
1378  * that is being removed.
1379  */
1380  IP_NEIGHBOR_DBG ("addr-%d: %U, %U/%d",
1381  (is_del ? "del" : "add"),
1383  sw_if_index, format_ip4_address, address, address_length);
1384 
1385  if (is_del)
1386  {
1388  .addr.ip4 = *address,
1389  .type = IP46_TYPE_IP4,
1390  .length = address_length,
1391  };
1392  index_t *ipni;
1393 
1394  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1395  ip_neighbor_walk_covered, &ctx);
1396 
1397  vec_foreach (ipni, ctx.ipnis)
1399 
1400  vec_free (ctx.ipnis);
1401  }
1402 }
1403 
1404 /*
1405  * callback when an interface address is added or deleted
1406  */
1407 static void
1409  uword opaque,
1410  u32 sw_if_index,
1411  ip6_address_t * address,
1412  u32 address_length,
1413  u32 if_address_index, u32 is_del)
1414 {
1415  /*
1416  * Flush the ARP cache of all entries covered by the address
1417  * that is being removed.
1418  */
1419  IP_NEIGHBOR_DBG ("addr-change: %U, %U/%d %s",
1421  sw_if_index, format_ip6_address, address, address_length,
1422  (is_del ? "del" : "add"));
1423 
1424  if (is_del)
1425  {
1427  .addr.ip6 = *address,
1428  .type = IP46_TYPE_IP6,
1429  .length = address_length,
1430  };
1431  index_t *ipni;
1432 
1433  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1434  ip_neighbor_walk_covered, &ctx);
1435 
1436  vec_foreach (ipni, ctx.ipnis)
1438 
1439  vec_free (ctx.ipnis);
1440  }
1441 }
1442 
1444 {
1448 
1449 static walk_rc_t
1451 {
1453  ip_neighbor_t *ipn;
1454 
1455  ipn = ip_neighbor_get (ipni);
1458 
1459  return (WALK_CONTINUE);
1460 }
1461 
1462 static void
1464  uword opaque,
1465  u32 sw_if_index,
1466  u32 new_fib_index, u32 old_fib_index)
1467 {
1469  .old_fib_index = old_fib_index,
1470  .new_fib_index = new_fib_index,
1471  };
1472 
1473  ip_neighbor_walk (IP46_TYPE_IP4, sw_if_index,
1475 }
1476 
1477 static void
1479  uword opaque,
1480  u32 sw_if_index,
1481  u32 new_fib_index, u32 old_fib_index)
1482 {
1484  .old_fib_index = old_fib_index,
1485  .new_fib_index = new_fib_index,
1486  };
1487 
1488  ip_neighbor_walk (IP46_TYPE_IP6, sw_if_index,
1490 }
1491 
1493 {
1498 
1499 #define IP_NEIGHBOR_PROCESS_SLEEP_LONG (0)
1500 
1503 {
1504  ip_neighbor_t *ipn;
1505  u32 ipndb_age;
1506  u32 ttl;
1507 
1508  ipn = ip_neighbor_get (ipni);
1509  ipndb_age = ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age;
1510  ttl = now - ipn->ipn_time_last_updated;
1511  *wait = ipndb_age;
1512 
1513  if (ttl > ipndb_age)
1514  {
1515  IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
1516  format_ip_neighbor, ipni, now,
1517  ipn->ipn_time_last_updated, ipndb_age);
1518  if (ipn->ipn_n_probes > 2)
1519  {
1520  /* 3 strikes and yea-re out */
1521  IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
1522  *wait = 1;
1523  return (IP_NEIGHBOR_AGE_DEAD);
1524  }
1525  else
1526  {
1527  adj_index_t ai;
1528 
1531 
1532  if (ADJ_INDEX_INVALID != ai)
1534 
1535  ipn->ipn_n_probes++;
1536  *wait = 1;
1537  }
1538  }
1539  else
1540  {
1541  /* here we are sure that ttl <= ipndb_age */
1542  *wait = ipndb_age - ttl + 1;
1543  return (IP_NEIGHBOR_AGE_ALIVE);
1544  }
1545 
1546  return (IP_NEIGHBOR_AGE_PROBE);
1547 }
1548 
1550 {
1553 
1554 static uword
1556  vlib_node_runtime_t * rt,
1558 {
1559  uword event_type, *event_data = NULL;
1560  f64 timeout;
1561 
1562  /* Set the timeout to an effectively infinite value when the process starts */
1564 
1565  while (1)
1566  {
1567  f64 now;
1568 
1569  if (!timeout)
1571  else
1573 
1574  event_type = vlib_process_get_events (vm, &event_data);
1575  vec_reset_length (event_data);
1576 
1577  now = vlib_time_now (vm);
1578 
1579  switch (event_type)
1580  {
1581  case ~0:
1582  {
1583  /* timer expired */
1584  ip_neighbor_elt_t *elt, *head;
1585  f64 wait;
1586 
1587  timeout = ip_neighbor_db[type].ipndb_age;
1588  head = pool_elt_at_index (ip_neighbor_elt_pool,
1589  ip_neighbor_list_head[type]);
1590 
1591  /* *INDENT-OFF*/
1592  /* the list is time sorted, newest first, so start from the back
1593  * and work forwards. Stop when we get to one that is alive */
1594  restart:
1595  clib_llist_foreach_reverse(ip_neighbor_elt_pool,
1596  ipne_anchor, head, elt,
1597  ({
1599 
1600  res = ip_neighbour_age_out(elt->ipne_index, now, &wait);
1601 
1602  if (IP_NEIGHBOR_AGE_ALIVE == res) {
1603  /* the oldest neighbor has not yet expired, go back to sleep */
1604  timeout = clib_min (wait, timeout);
1605  break;
1606  }
1607  else if (IP_NEIGHBOR_AGE_DEAD == res) {
1608  /* the oldest neighbor is dead, pop it, then restart the walk
1609  * again from the back */
1611  goto restart;
1612  }
1613 
1614  timeout = clib_min (wait, timeout);
1615  }));
1616  /* *INDENT-ON* */
1617  break;
1618  }
1620  {
1621 
1622  if (!ip_neighbor_db[type].ipndb_age)
1623  {
1624  /* aging has been disabled */
1625  timeout = 0;
1626  break;
1627  }
1628  ip_neighbor_elt_t *elt, *head;
1629 
1630  head = pool_elt_at_index (ip_neighbor_elt_pool,
1631  ip_neighbor_list_head[type]);
1632  /* no neighbors yet */
1633  if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
1634  {
1635  timeout = ip_neighbor_db[type].ipndb_age;
1636  break;
1637  }
1638 
1639  /* poke the oldset neighbour for aging, which returns how long we sleep for */
1640  elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
1641  ip_neighbour_age_out (elt->ipne_index, now, &timeout);
1642  break;
1643  }
1644  }
1645  }
1646  return 0;
1647 }
1648 
1649 static uword
1652 {
1653  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP4));
1654 }
1655 
1656 static uword
1659 {
1660  return (ip_neighbor_age_loop (vm, rt, f, IP46_TYPE_IP6));
1661 }
1662 
1663 /* *INDENT-OFF* */
1665  .function = ip4_neighbor_age_process,
1666  .type = VLIB_NODE_TYPE_PROCESS,
1667  .name = "ip4-neighbor-age-process",
1668 };
1670  .function = ip6_neighbor_age_process,
1671  .type = VLIB_NODE_TYPE_PROCESS,
1672  .name = "ip6-neighbor-age-process",
1673 };
1674 /* *INDENT-ON* */
1675 
1676 int
1677 ip_neighbor_config (ip46_type_t type, u32 limit, u32 age, bool recycle)
1678 {
1679  ip_neighbor_db[type].ipndb_limit = limit;
1680  ip_neighbor_db[type].ipndb_recycle = recycle;
1681  ip_neighbor_db[type].ipndb_age = age;
1682 
1684  (IP46_TYPE_IP4 == type ?
1688 
1689  return (0);
1690 }
1691 
1692 static clib_error_t *
1694  unformat_input_t * input, vlib_cli_command_t * cmd)
1695 {
1696  ip46_type_t type;
1697 
1698  /* *INDENT-OFF* */
1699  FOREACH_IP46_TYPE(type) {
1700  vlib_cli_output (vm, "%U:", format_ip46_type, type);
1701  vlib_cli_output (vm, " limit:%d, age:%d, recycle:%d",
1702  ip_neighbor_db[type].ipndb_limit,
1703  ip_neighbor_db[type].ipndb_age,
1704  ip_neighbor_db[type].ipndb_recycle);
1705  }
1706 
1707  /* *INDENT-ON* */
1708  return (NULL);
1709 }
1710 
1711 /* *INDENT-OFF* */
1712 VLIB_CLI_COMMAND (show_ip_neighbor_cfg_cmd_node, static) = {
1713  .path = "show ip neighbor-config",
1714  .function = ip_neighbor_config_show,
1715  .short_help = "show ip neighbor-config",
1716 };
1717 /* *INDENT-ON* */
1718 
1719 static clib_error_t *
1721 {
1722  {
1725  };
1727  }
1728  {
1731  };
1733  }
1734  {
1737  };
1739  }
1740  {
1743  };
1745  }
1746  {
1748  .function = ip_neighbor_ethernet_change_mac,
1749  .function_opaque = 0,
1750  };
1752  }
1753 
1754  ipn_logger = vlib_log_register_class ("ip", "neighbor");
1755 
1756  ip46_type_t type;
1757 
1758  FOREACH_IP46_TYPE (type)
1760  clib_llist_make_head (ip_neighbor_elt_pool, ipne_anchor);
1761 
1762  return (NULL);
1763 }
1764 
1765 /* *INDENT-OFF* */
1767 {
1768  .runs_after = VLIB_INITS("ip_main_init"),
1769 };
1770 /* *INDENT-ON* */
1771 
1772 /*
1773  * fd.io coding-style-patch-verification: ON
1774  *
1775  * Local Variables:
1776  * eval: (c-set-style "gnu")
1777  * End:
1778  */
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:1450
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:1203
#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:1369
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:996
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:903
void ip_neighbor_del_all(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:597
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:455
void ip_neighbor_sweep(ip46_type_t type)
Definition: ip_neighbor.c:1266
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:1669
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:697
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:1408
#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:1463
static ip_neighbor_age_state_t ip_neighbour_age_out(index_t ipni, f64 now, f64 *wait)
Definition: ip_neighbor.c:1502
int ip_neighbor_config(ip46_type_t type, u32 limit, u32 age, bool recycle)
Definition: ip_neighbor.c:1677
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:910
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:1664
static clib_error_t * ip_neighbor_interface_admin_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip_neighbor.c:1284
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:554
#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:1076
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:1017
#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
void ip_neighbor_publish(index_t ipni)
int ip4_neighbor_proxy_delete(u32 fib_index, const ip4_address_t *start, const ip4_address_t *end)
Definition: ip_neighbor.c:1090
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:397
Aggregate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
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:1650
void ip_neighbor_populate(ip46_type_t type, u32 sw_if_index)
Definition: ip_neighbor.c:1172
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:46
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:1239
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:1549
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:917
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:990
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:868
#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:587
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:818
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:1657
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: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:1499
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:1693
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:800
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:1720
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:1478
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:1143
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:1036
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:1555
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:107
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:1341
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:690
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:1123
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:1113
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.
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 void ip_neighbor_free(ip_neighbor_t *ipn)
Definition: ip_neighbor.c:374
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:1103
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
#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:896
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:1023
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:418
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:924
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:841
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: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:1133
static walk_rc_t ip_neighbor_mark_one(index_t ipni, void *ctx)
Definition: ip_neighbor.c:1227
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
enum ip_neighbor_flags_t_ ip_neighbor_flags_t
void adj_nbr_update_rewrite(adj_index_t adj_index, adj_nbr_rewrite_flag_t flags, u8 *rewrite)
adj_nbr_update_rewrite
Definition: adj_nbr.c: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:1492
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:616
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