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