FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
adj_nbr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/adj/adj_nbr.h>
17 #include <vnet/adj/adj_internal.h>
19 #include <vnet/fib/fib_walk.h>
20 
21 /*
22  * Vector Hash tables of neighbour (traditional) adjacencies
23  * Key: interface(for the vector index), address (and its proto),
24  * link-type/ether-type.
25  */
26 static BVT(clib_bihash) **adj_nbr_tables[FIB_PROTOCOL_MAX];
27 
28 // FIXME SIZE APPROPRIATELY. ASK DAVEB.
29 #define ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS (64 * 64)
30 #define ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE (32<<20)
31 
32 
33 #define ADJ_NBR_SET_KEY(_key, _lt, _nh) \
34 { \
35  _key.key[0] = (_nh)->as_u64[0]; \
36  _key.key[1] = (_nh)->as_u64[1]; \
37  _key.key[2] = (_lt); \
38 }
39 
40 #define ADJ_NBR_ITF_OK(_proto, _itf) \
41  (((_itf) < vec_len(adj_nbr_tables[_proto])) && \
42  (NULL != adj_nbr_tables[_proto][sw_if_index]))
43 
44 static void
45 adj_nbr_insert (fib_protocol_t nh_proto,
46  vnet_link_t link_type,
47  const ip46_address_t *nh_addr,
48  u32 sw_if_index,
49  adj_index_t adj_index)
50 {
51  BVT(clib_bihash_kv) kv;
52 
53  if (sw_if_index >= vec_len(adj_nbr_tables[nh_proto]))
54  {
55  vec_validate(adj_nbr_tables[nh_proto], sw_if_index);
56  }
57  if (NULL == adj_nbr_tables[nh_proto][sw_if_index])
58  {
59  adj_nbr_tables[nh_proto][sw_if_index] =
60  clib_mem_alloc_aligned(sizeof(BVT(clib_bihash)),
62  memset(adj_nbr_tables[nh_proto][sw_if_index],
63  0,
64  sizeof(BVT(clib_bihash)));
65 
66  BV(clib_bihash_init) (adj_nbr_tables[nh_proto][sw_if_index],
67  "Adjacency Neighbour table",
70  }
71 
72  ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
73  kv.value = adj_index;
74 
75  BV(clib_bihash_add_del) (adj_nbr_tables[nh_proto][sw_if_index], &kv, 1);
76 }
77 
78 void
80  vnet_link_t link_type,
81  const ip46_address_t *nh_addr,
82  u32 sw_if_index)
83 {
84  BVT(clib_bihash_kv) kv;
85 
86  if (!ADJ_NBR_ITF_OK(nh_proto, sw_if_index))
87  return;
88 
89  ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
90 
91  BV(clib_bihash_add_del) (adj_nbr_tables[nh_proto][sw_if_index], &kv, 0);
92 }
93 
94 static adj_index_t
96  vnet_link_t link_type,
97  const ip46_address_t *nh_addr,
98  u32 sw_if_index)
99 {
100  BVT(clib_bihash_kv) kv;
101 
102  ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
103 
104  if (!ADJ_NBR_ITF_OK(nh_proto, sw_if_index))
105  return (ADJ_INDEX_INVALID);
106 
107  if (BV(clib_bihash_search)(adj_nbr_tables[nh_proto][sw_if_index],
108  &kv, &kv) < 0)
109  {
110  return (ADJ_INDEX_INVALID);
111  }
112  else
113  {
114  return (kv.value);
115  }
116 }
117 
118 static inline u32
120 {
121  switch (proto) {
122  case FIB_PROTOCOL_IP4:
123  return (ip4_arp_node.index);
124  case FIB_PROTOCOL_IP6:
125  return (ip6_discover_neighbor_node.index);
126  case FIB_PROTOCOL_MPLS:
127  break;
128  }
129  ASSERT(0);
130  return (ip4_arp_node.index);
131 }
132 
133 static ip_adjacency_t*
135  vnet_link_t link_type,
136  const ip46_address_t *nh_addr,
137  u32 sw_if_index)
138 {
139  ip_adjacency_t *adj;
140 
141  adj = adj_alloc(nh_proto);
142 
143  adj_nbr_insert(nh_proto, link_type, nh_addr,
144  sw_if_index,
145  adj_get_index(adj));
146 
147  /*
148  * since we just added the ADJ we have no rewrite string for it,
149  * so its for ARP
150  */
152  adj->sub_type.nbr.next_hop = *nh_addr;
153  adj->ia_link = link_type;
154  adj->ia_nh_proto = nh_proto;
155  adj->rewrite_header.sw_if_index = sw_if_index;
156  memset(&adj->sub_type.midchain.next_dpo, 0,
157  sizeof(adj->sub_type.midchain.next_dpo));
158 
159  return (adj);
160 }
161 
162 /*
163  * adj_add_for_nbr
164  *
165  * Add an adjacency for the neighbour requested.
166  *
167  * The key for an adj is:
168  * - the Next-hops protocol (i.e. v4 or v6)
169  * - the address of the next-hop
170  * - the interface the next-hop is reachable through
171  */
174  vnet_link_t link_type,
175  const ip46_address_t *nh_addr,
176  u32 sw_if_index)
177 {
178  adj_index_t adj_index;
179  ip_adjacency_t *adj;
180 
181  adj_index = adj_nbr_find(nh_proto, link_type, nh_addr, sw_if_index);
182 
183  if (ADJ_INDEX_INVALID == adj_index)
184  {
185  vnet_main_t *vnm;
186 
187  vnm = vnet_get_main();
188  adj = adj_nbr_alloc(nh_proto, link_type, nh_addr, sw_if_index);
189  adj_index = adj_get_index(adj);
190  adj_lock(adj_index);
191 
192  vnet_rewrite_init(vnm, sw_if_index,
193  adj_get_nd_node(nh_proto),
194  vnet_tx_node_index_for_sw_interface(vnm, sw_if_index),
195  &adj->rewrite_header);
196 
197  /*
198  * we need a rewrite where the destination IP address is converted
199  * to the appropriate link-layer address. This is interface specific.
200  * So ask the interface to do it.
201  */
202  vnet_update_adjacency_for_sw_interface(vnm, sw_if_index, adj_index);
203  }
204  else
205  {
206  adj_lock(adj_index);
207  }
208 
209  return (adj_index);
210 }
211 
214  vnet_link_t link_type,
215  const ip46_address_t *nh_addr,
216  u32 sw_if_index,
217  u8 *rewrite)
218 {
219  adj_index_t adj_index;
220  ip_adjacency_t *adj;
221 
222  adj_index = adj_nbr_find(nh_proto, link_type, nh_addr, sw_if_index);
223 
224  if (ADJ_INDEX_INVALID == adj_index)
225  {
226  adj = adj_nbr_alloc(nh_proto, link_type, nh_addr, sw_if_index);
227  adj->rewrite_header.sw_if_index = sw_if_index;
228  }
229  else
230  {
231  adj = adj_get(adj_index);
232  }
233 
234  adj_lock(adj_get_index(adj));
237  rewrite);
238 
239  return (adj_get_index(adj));
240 }
241 
242 /**
243  * adj_nbr_update_rewrite
244  *
245  * Update the adjacency's rewrite string. A NULL string implies the
246  * rewirte is reset (i.e. when ARP/ND etnry is gone).
247  * NB: the adj being updated may be handling traffic in the DP.
248  */
249 void
252  u8 *rewrite)
253 {
254  ip_adjacency_t *adj;
255  u32 old_next;
256 
257  ASSERT(ADJ_INDEX_INVALID != adj_index);
258 
259  adj = adj_get(adj_index);
260  old_next = adj->lookup_next_index;
261 
262  if (flags & ADJ_NBR_REWRITE_FLAG_COMPLETE)
263  {
264  /*
265  * update the adj's rewrite string and build the arc
266  * from the rewrite node to the interface's TX node
267  */
271  vnet_get_main(),
272  adj->rewrite_header.sw_if_index),
273  rewrite);
274  }
275  else
276  {
280  vnet_get_main(),
281  adj->rewrite_header.sw_if_index),
282  rewrite);
283  }
284 
285  if (old_next != adj->lookup_next_index)
286  {
287  /*
288  * time for walkies fido.
289  * The link type MPLS Adj never has children. So if it is this adj
290  * that is updated, we need to walk from its IP sibling.
291  */
292  if (VNET_LINK_MPLS == adj->ia_link)
293  {
294  adj_index = adj_nbr_find(adj->ia_nh_proto,
296  &adj->sub_type.nbr.next_hop,
297  adj->rewrite_header.sw_if_index);
298 
299  ASSERT(ADJ_INDEX_INVALID != adj_index);
300  }
301 
302  fib_node_back_walk_ctx_t bw_ctx = {
304  /*
305  * This walk only needs to go back one level, but there is no control
306  * here. the first receiving fib_entry_t will quash the walk
307  */
308  };
309 
310  fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_index, &bw_ctx);
311  }
312 }
313 
314 /**
315  * adj_nbr_update_rewrite_internal
316  *
317  * Update the adjacency's rewrite string. A NULL string implies the
318  * rewirte is reset (i.e. when ARP/ND etnry is gone).
319  * NB: the adj being updated may be handling traffic in the DP.
320  */
321 void
323  u32 adj_next_index,
324  u32 this_node,
325  u32 next_node,
326  u8 *rewrite)
327 {
328  vlib_main_t * vm = vlib_get_main();
329 
330  /*
331  * Updating a rewrite string is not atomic;
332  * - the rewrite string is too long to write in one instruction
333  * - when swapping from incomplete to complete, we also need to update
334  * the VLIB graph next-index.
335  * ideally we would only want to suspend forwarding via this adj whilst we
336  * do this, but we do not have that level of granularity - it's suspend all
337  * worker threads or nothing.
338  * The other chioces are:
339  * - to mark the adj down and back walk so child load-balances drop this adj
340  * from the set.
341  * - update the next_node index of this adj to point to error-drop
342  * both of which will mean for MAC change we will drop for this adj
343  * which is not acceptable.
344  * So the pause all threads is preferable. We don't update MAC addresses often
345  * so it's no big deal.
346  */
348 
349  adj->lookup_next_index = adj_next_index;
350 
351  if (NULL != rewrite)
352  {
353  /*
354  * new rewrite provided.
355  * fill in the adj's rewrite string, and build the VLIB graph arc.
356  */
357  vnet_rewrite_set_data_internal(&adj->rewrite_header,
358  sizeof(adj->rewrite_data),
359  rewrite,
360  vec_len(rewrite));
361 
362  adj->rewrite_header.node_index = this_node;
363  adj->rewrite_header.next_index = vlib_node_add_next (vlib_get_main(),
364  this_node,
365  next_node);
366 
367  vec_free(rewrite);
368  }
369  else
370  {
371  vnet_rewrite_clear_data_internal(&adj->rewrite_header,
372  sizeof(adj->rewrite_data));
373  }
374 
375  /*
376  * done with the rewirte update - let the workers loose.
377  */
379 }
380 
381 typedef struct adj_db_count_ctx_t_ {
384 
385 static void
386 adj_db_count (BVT(clib_bihash_kv) * kvp,
387  void *arg)
388 {
389  adj_db_count_ctx_t * ctx = arg;
390  ctx->count++;
391 }
392 
393 u32
395 {
396  adj_db_count_ctx_t ctx = {
397  .count = 0,
398  };
399  fib_protocol_t proto;
400  u32 sw_if_index = 0;
401 
402  for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
403  {
404  vec_foreach_index(sw_if_index, adj_nbr_tables[proto])
405  {
406  if (NULL != adj_nbr_tables[proto][sw_if_index])
407  {
409  adj_nbr_tables[proto][sw_if_index],
410  adj_db_count,
411  &ctx);
412  }
413  }
414  }
415  return (ctx.count);
416 }
417 
418 /**
419  * @brief Context for a walk of the adjacency neighbour DB
420  */
421 typedef struct adj_walk_ctx_t_
422 {
424  void *awc_ctx;
426 
427 static void
428 adj_nbr_walk_cb (BVT(clib_bihash_kv) * kvp,
429  void *arg)
430 {
431  adj_walk_ctx_t *ctx = arg;
432 
433  // FIXME: can't stop early...
434  ctx->awc_cb(kvp->value, ctx->awc_ctx);
435 }
436 
437 void
438 adj_nbr_walk (u32 sw_if_index,
439  fib_protocol_t adj_nh_proto,
440  adj_walk_cb_t cb,
441  void *ctx)
442 {
443  if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
444  return;
445 
446  adj_walk_ctx_t awc = {
447  .awc_ctx = ctx,
448  .awc_cb = cb,
449  };
450 
452  adj_nbr_tables[adj_nh_proto][sw_if_index],
454  &awc);
455 }
456 
457 /**
458  * @brief Context for a walk of the adjacency neighbour DB
459  */
460 typedef struct adj_walk_nh_ctx_t_
461 {
463  void *awc_ctx;
464  const ip46_address_t *awc_nh;
466 
467 static void
468 adj_nbr_walk_nh_cb (BVT(clib_bihash_kv) * kvp,
469  void *arg)
470 {
471  ip_adjacency_t *adj;
472  adj_walk_nh_ctx_t *ctx = arg;
473 
474  adj = adj_get(kvp->value);
475 
476  if (!ip46_address_cmp(&adj->sub_type.nbr.next_hop, ctx->awc_nh))
477  ctx->awc_cb(kvp->value, ctx->awc_ctx);
478 }
479 
480 /**
481  * @brief Walk adjacencies on a link with a given v4 next-hop.
482  * that is visit the adjacencies with different link types.
483  */
484 void
485 adj_nbr_walk_nh4 (u32 sw_if_index,
486  const ip4_address_t *addr,
487  adj_walk_cb_t cb,
488  void *ctx)
489 {
490  if (!ADJ_NBR_ITF_OK(FIB_PROTOCOL_IP4, sw_if_index))
491  return;
492 
493  ip46_address_t nh = {
494  .ip4 = *addr,
495  };
496 
497  adj_walk_nh_ctx_t awc = {
498  .awc_ctx = ctx,
499  .awc_cb = cb,
500  .awc_nh = &nh,
501  };
502 
504  adj_nbr_tables[FIB_PROTOCOL_IP4][sw_if_index],
506  &awc);
507 }
508 
509 /**
510  * @brief Walk adjacencies on a link with a given v6 next-hop.
511  * that is visit the adjacencies with different link types.
512  */
513 void
514 adj_nbr_walk_nh6 (u32 sw_if_index,
515  const ip6_address_t *addr,
516  adj_walk_cb_t cb,
517  void *ctx)
518 {
519  if (!ADJ_NBR_ITF_OK(FIB_PROTOCOL_IP6, sw_if_index))
520  return;
521 
522  ip46_address_t nh = {
523  .ip6 = *addr,
524  };
525 
526  adj_walk_nh_ctx_t awc = {
527  .awc_ctx = ctx,
528  .awc_cb = cb,
529  .awc_nh = &nh,
530  };
531 
533  adj_nbr_tables[FIB_PROTOCOL_IP6][sw_if_index],
535  &awc);
536 }
537 
538 /**
539  * @brief Walk adjacencies on a link with a given next-hop.
540  * that is visit the adjacencies with different link types.
541  */
542 void
543 adj_nbr_walk_nh (u32 sw_if_index,
544  fib_protocol_t adj_nh_proto,
545  const ip46_address_t *nh,
546  adj_walk_cb_t cb,
547  void *ctx)
548 {
549  if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
550  return;
551 
552  adj_walk_nh_ctx_t awc = {
553  .awc_ctx = ctx,
554  .awc_cb = cb,
555  .awc_nh = nh,
556  };
557 
559  adj_nbr_tables[adj_nh_proto][sw_if_index],
561  &awc);
562 }
563 
564 /**
565  * Context for the state change walk of the DB
566  */
568 {
569  /**
570  * Flags passed from the vnet notifiy function
571  */
572  int flags;
574 
575 static adj_walk_rc_t
577  void *arg)
578 {
579  /*
580  * Back walk the graph to inform the forwarding entries
581  * that this interface state has changed.
582  */
584 
585  fib_node_back_walk_ctx_t bw_ctx = {
589  };
590 
591  fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
592 
593  return (ADJ_WALK_RC_CONTINUE);
594 }
595 
596 static clib_error_t *
598  u32 sw_if_index,
599  u32 flags)
600 {
601  fib_protocol_t proto;
602 
603  /*
604  * walk each adj on the interface and trigger a walk from that adj
605  */
606  for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
607  {
609  .flags = flags,
610  };
611 
612  adj_nbr_walk(sw_if_index, proto,
614  &ctx);
615  }
616 
617  return (NULL);
618 }
619 
621 
622 static adj_walk_rc_t
624  void *arg)
625 {
626  /*
627  * Back walk the graph to inform the forwarding entries
628  * that this interface has been deleted.
629  */
630  fib_node_back_walk_ctx_t bw_ctx = {
632  };
633 
634  fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
635 
636  return (ADJ_WALK_RC_CONTINUE);
637 }
638 
639 /**
640  * adj_nbr_interface_add_del
641  *
642  * Registered to receive interface Add and delete notifications
643  */
644 static clib_error_t *
646  u32 sw_if_index,
647  u32 is_add)
648 {
649  fib_protocol_t proto;
650 
651  if (is_add)
652  {
653  /*
654  * not interested in interface additions. we will not back walk
655  * to resolve paths through newly added interfaces. Why? The control
656  * plane should have the brains to add interfaces first, then routes.
657  * So the case where there are paths with a interface that matches
658  * one just created is the case where the path resolved through an
659  * interface that was deleted, and still has not been removed. The
660  * new interface added, is NO GUARANTEE that the interface being
661  * added now, even though it may have the same sw_if_index, is the
662  * same interface that the path needs. So tough!
663  * If the control plane wants these routes to resolve it needs to
664  * remove and add them again.
665  */
666  return (NULL);
667  }
668 
669  for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
670  {
671  adj_nbr_walk(sw_if_index, proto,
673  NULL);
674  }
675 
676  return (NULL);
677 
678 }
679 
681 
682 
683 static adj_walk_rc_t
685  void *arg)
686 {
687  vlib_cli_output (arg, "[@%d] %U",
688  ai,
691 
692  return (ADJ_WALK_RC_CONTINUE);
693 }
694 
695 static clib_error_t *
697  unformat_input_t * input,
698  vlib_cli_command_t * cmd)
699 {
701  u32 sw_if_index = ~0;
702 
704  {
705  if (unformat (input, "%d", &ai))
706  ;
707  else if (unformat (input, "%U",
709  &sw_if_index))
710  ;
711  else
712  break;
713  }
714 
715  if (ADJ_INDEX_INVALID != ai)
716  {
717  vlib_cli_output (vm, "[@%d] %U",
718  ai,
721  }
722  else if (~0 != sw_if_index)
723  {
724  fib_protocol_t proto;
725 
726  for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
727  {
728  adj_nbr_walk(sw_if_index, proto,
730  vm);
731  }
732  }
733  else
734  {
735  fib_protocol_t proto;
736 
737  for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
738  {
739  vec_foreach_index(sw_if_index, adj_nbr_tables[proto])
740  {
741  adj_nbr_walk(sw_if_index, proto,
743  vm);
744  }
745  }
746  }
747 
748  return 0;
749 }
750 
751 /*?
752  * Show all neighbour adjacencies.
753  * @cliexpar
754  * @cliexstart{sh adj nbr}
755  * [@2] ipv4 via 1.0.0.2 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
756  * [@3] mpls via 1.0.0.2 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
757  * [@4] ipv4 via 1.0.0.3 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
758  * [@5] mpls via 1.0.0.3 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
759  * @cliexend
760  ?*/
761 VLIB_CLI_COMMAND (ip4_show_fib_command, static) = {
762  .path = "show adj nbr",
763  .short_help = "show adj nbr [<adj_index>] [interface]",
764  .function = adj_nbr_show,
765 };
766 
767 static ip46_type_t
769 {
770  switch (proto)
771  {
772  case FIB_PROTOCOL_IP4:
773  return (IP46_TYPE_IP4);
774  case FIB_PROTOCOL_IP6:
775  return (IP46_TYPE_IP6);
776  default:
777  return (IP46_TYPE_IP4);
778  }
779  return (IP46_TYPE_IP4);
780 }
781 
782 u8*
783 format_adj_nbr_incomplete (u8* s, va_list *ap)
784 {
785  index_t index = va_arg(*ap, index_t);
786  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
787  vnet_main_t * vnm = vnet_get_main();
788  ip_adjacency_t * adj = adj_get(index);
789 
790  s = format (s, "arp-%U", format_vnet_link, adj->ia_link);
791  s = format (s, ": via %U",
792  format_ip46_address, &adj->sub_type.nbr.next_hop,
794  s = format (s, " %U",
796  vnm,
798  adj->rewrite_header.sw_if_index));
799 
800  return (s);
801 }
802 
803 u8*
804 format_adj_nbr (u8* s, va_list *ap)
805 {
806  index_t index = va_arg(*ap, index_t);
807  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
808  vnet_main_t * vnm = vnet_get_main();
809  ip_adjacency_t * adj = adj_get(index);
810 
811  s = format (s, "%U", format_vnet_link, adj->ia_link);
812  s = format (s, " via %U ",
813  format_ip46_address, &adj->sub_type.nbr.next_hop,
815  s = format (s, "%U",
817  vnm->vlib_main, &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
818 
819  return (s);
820 }
821 
822 static void
824 {
825  adj_lock(dpo->dpoi_index);
826 }
827 static void
829 {
830  adj_unlock(dpo->dpoi_index);
831 }
832 
833 static void
835 {
836  fib_show_memory_usage("Adjacency",
839  sizeof(ip_adjacency_t));
840 }
841 
842 const static dpo_vft_t adj_nbr_dpo_vft = {
844  .dv_unlock = adj_dpo_unlock,
845  .dv_format = format_adj_nbr,
846  .dv_mem_show = adj_mem_show,
847 };
848 const static dpo_vft_t adj_nbr_incompl_dpo_vft = {
850  .dv_unlock = adj_dpo_unlock,
851  .dv_format = format_adj_nbr_incomplete,
852 };
853 
854 /**
855  * @brief The per-protocol VLIB graph nodes that are assigned to an adjacency
856  * object.
857  *
858  * this means that these graph nodes are ones from which a nbr is the
859  * parent object in the DPO-graph.
860  */
861 const static char* const nbr_ip4_nodes[] =
862 {
863  "ip4-rewrite-transit",
864  NULL,
865 };
866 const static char* const nbr_ip6_nodes[] =
867 {
868  "ip6-rewrite",
869  NULL,
870 };
871 const static char* const nbr_mpls_nodes[] =
872 {
873  "mpls-output",
874  NULL,
875 };
876 const static char* const nbr_ethernet_nodes[] =
877 {
878  "adj-l2-rewrite",
879  NULL,
880 };
881 const static char* const * const nbr_nodes[DPO_PROTO_NUM] =
882 {
887 };
888 
889 const static char* const nbr_incomplete_ip4_nodes[] =
890 {
891  "ip4-arp",
892  NULL,
893 };
894 const static char* const nbr_incomplete_ip6_nodes[] =
895 {
896  "ip6-discover-neighbor",
897  NULL,
898 };
899 const static char* const nbr_incomplete_mpls_nodes[] =
900 {
901  "mpls-adj-incomplete",
902  NULL,
903 };
904 
905 const static char* const * const nbr_incomplete_nodes[DPO_PROTO_NUM] =
906 {
910 };
911 
912 void
914 {
916  &adj_nbr_dpo_vft,
917  nbr_nodes);
919  &adj_nbr_incompl_dpo_vft,
920  nbr_incomplete_nodes);
921 }
format_function_t format_ip46_address
Definition: format.h:61
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:318
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:543
#define vec_foreach_index(var, v)
Iterate over vector indices.
Context for a walk of the adjacency neighbour DB.
Definition: adj_nbr.c:421
ip_adjacency_t * adj_pool
The global adjacnecy pool.
Definition: adj.c:35
void vnet_rewrite_init(vnet_main_t *vnm, u32 sw_if_index, u32 this_node, u32 next_node, vnet_rewrite_header_t *rw)
Definition: rewrite.c:195
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:313
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
u8 * format_adj_nbr(u8 *s, va_list *ap)
Format a neigbour (REWRITE) adjacency.
Definition: adj_nbr.c:804
static ip46_type_t adj_proto_to_46(fib_protocol_t proto)
Definition: adj_nbr.c:768
void adj_lock(adj_index_t adj_index)
An adjacency is a representation of an attached L3 peer.
Definition: adj.c:189
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
static const char *const nbr_ethernet_nodes[]
Definition: adj_nbr.c:876
static const char *const nbr_incomplete_ip6_nodes[]
Definition: adj_nbr.c:894
static adj_walk_rc_t adj_nbr_interface_state_change_one(adj_index_t ai, void *arg)
Definition: adj_nbr.c:576
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u8 * format_vnet_link(u8 *s, va_list ap)
Definition: fib_types.c:38
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:174
Context for the state change walk of the DB.
Definition: adj_nbr.c:567
struct ip_adjacency_t_::@164::@165 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
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
adj_walk_cb_t awc_cb
Definition: adj_nbr.c:423
void adj_nbr_walk_nh4(u32 sw_if_index, const ip4_address_t *addr, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given v4 next-hop.
Definition: adj_nbr.c:485
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
u8 * format_adj_nbr_incomplete(u8 *s, va_list *ap)
Format aa incomplete neigbour (ARP) adjacency.
Definition: adj_nbr.c:783
static const char *const nbr_incomplete_mpls_nodes[]
Definition: adj_nbr.c:899
adj_index_t adj_nbr_add_or_lock_w_rewrite(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index, u8 *rewrite)
Add (and lock) a new or lock an existing neighbour adjacency.
Definition: adj_nbr.c:213
#define ip46_address_cmp(ip46_1, ip46_2)
Definition: ip6_packet.h:73
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1063
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
vnet_link_t ia_link
Definition: lookup.h:199
void adj_nbr_update_rewrite_internal(ip_adjacency_t *adj, u32 adj_next_index, u32 this_node, u32 next_node, u8 *rewrite)
adj_nbr_update_rewrite_internal
Definition: adj_nbr.c:322
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:117
vlib_node_registration_t ip6_discover_neighbor_node
(constructor) VLIB_REGISTER_NODE (ip6_discover_neighbor_node)
Definition: ip6_forward.c:1714
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:221
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
int flags
Flags passed from the vnet notifiy function.
Definition: adj_nbr.c:572
void fib_walk_sync(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_back_walk_ctx_t *ctx)
Back walk all the children of a FIB node.
Definition: fib_walk.c:624
static void vnet_rewrite_clear_data_internal(vnet_rewrite_header_t *rw, int max_size)
Definition: rewrite.h:92
static const char *const nbr_incomplete_ip4_nodes[]
Definition: adj_nbr.c:889
static BVT(clib_bihash)
Definition: adj_nbr.c:26
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
static clib_error_t * adj_nbr_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: adj_nbr.c:597
static clib_error_t * adj_nbr_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adj_nbr.c:696
struct adj_walk_ctx_t_ adj_walk_ctx_t
Context for a walk of the adjacency neighbour DB.
static const char *const nbr_mpls_nodes[]
Definition: adj_nbr.c:871
static void adj_nbr_walk_cb(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: adj_nbr.c:428
static void adj_dpo_lock(dpo_id_t *dpo)
Definition: adj_nbr.c:823
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:210
unsigned long u64
Definition: types.h:89
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:206
void vnet_update_adjacency_for_sw_interface(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: rewrite.c:312
static const char *const nbr_ip6_nodes[]
Definition: adj_nbr.c:866
format_function_t format_vnet_rewrite
Definition: rewrite.h:292
u32 adj_nbr_db_size(void)
Return the size of the adjacency database.
Definition: adj_nbr.c:394
Context for a walk of the adjacency neighbour DB.
Definition: adj_nbr.c:460
#define ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS
vlib_node_registration_t ip4_arp_node
(constructor) VLIB_REGISTER_NODE (ip4_arp_node)
Definition: ip4_forward.c:2049
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
fib_node_bw_reason_flag_t fnbw_reason
The reason/trigger for the backwalk.
Definition: fib_node.h:164
format_function_t format_vnet_sw_interface_name
#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
vlib_main_t * vlib_main
Definition: vnet.h:88
static adj_index_t adj_get_index(ip_adjacency_t *adj)
Get a pointer to an adjacency object from its index.
Definition: adj_internal.h:83
static clib_error_t * adj_nbr_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
adj_nbr_interface_add_del
Definition: adj_nbr.c:645
const ip46_address_t * awc_nh
Definition: adj_nbr.c:464
static void adj_nbr_walk_nh_cb(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: adj_nbr.c:468
#define ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE
void adj_nbr_module_init(void)
Module initialisation.
Definition: adj_nbr.c:913
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
ip46_type_t
Definition: format.h:63
#define ADJ_NBR_SET_KEY(_key, _lt, _nh)
void clib_bihash_foreach_key_value_pair(clib_bihash *h, void *callback, void *arg)
Visit active (key,value) pairs in a bi-hash table.
union ip_adjacency_t_::@164 sub_type
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_nbr_interface_state_change)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static adj_walk_rc_t adj_nbr_show_one(adj_index_t ai, void *arg)
Definition: adj_nbr.c:684
u32 vnet_tx_node_index_for_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: rewrite.c:188
static void vnet_rewrite_set_data_internal(vnet_rewrite_header_t *rw, int max_size, void *data, int data_bytes)
Definition: rewrite.h:102
adj_walk_rc_t(* adj_walk_cb_t)(adj_index_t ai, void *ctx)
Call back function when walking adjacencies.
Definition: adj_types.h:50
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1182
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void adj_nbr_remove(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Definition: adj_nbr.c:79
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:72
static void adj_mem_show(void)
Definition: adj_nbr.c:834
static ip_adjacency_t * adj_nbr_alloc(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Definition: adj_nbr.c:134
void adj_nbr_walk(u32 sw_if_index, fib_protocol_t adj_nh_proto, adj_walk_cb_t cb, void *ctx)
Walk the neighbour Adjacencies on a given interface.
Definition: adj_nbr.c:438
Context passed between object during a back walk.
Definition: fib_node.h:160
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:490
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int clib_bihash_search(clib_bihash *h, clib_bihash_kv *search_v, clib_bihash_kv *return_v)
Search a bi-hash table.
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
void * awc_ctx
Definition: adj_nbr.c:424
static const char *const nbr_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to an adjacency object.
Definition: adj_nbr.c:861
static u32 adj_get_rewrite_node(vnet_link_t linkt)
Definition: adj_internal.h:45
static u32 adj_get_nd_node(fib_protocol_t proto)
Definition: adj_nbr.c:119
struct adj_walk_nh_ctx_t_ adj_walk_nh_ctx_t
Context for a walk of the adjacency neighbour DB.
#define DPO_PROTO_NUM
Definition: dpo.h:72
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:154
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:183
enum adj_nbr_rewrite_flag_t_ adj_nbr_rewrite_flag_t
When adding a rewrite to an adjacency these are flags that apply to that rewrite. ...
ip_adjacency_t * adj_alloc(fib_protocol_t proto)
Definition: adj.c:47
static void adj_db_count(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: adj_nbr.c:386
static adj_walk_rc_t adj_nbr_interface_delete_one(adj_index_t ai, void *arg)
Definition: adj_nbr.c:623
#define FIB_PROTOCOL_MAX
Definition outside of enum so it does not need to be included in non-defaulted switch statements...
Definition: fib_types.h:54
adj_walk_cb_t awc_cb
Definition: adj_nbr.c:462
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1214
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:82
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:173
struct adj_db_count_ctx_t_ adj_db_count_ctx_t
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:256
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(adj_nbr_interface_add_del)
vhost_vring_addr_t addr
Definition: vhost-user.h:81
struct _unformat_input_t unformat_input_t
static void adj_dpo_unlock(dpo_id_t *dpo)
Definition: adj_nbr.c:828
u32 flags
Definition: vhost-user.h:75
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
#define ADJ_NBR_ITF_OK(_proto, _itf)
static 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)
Definition: adj_nbr.c:95
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:250
struct adj_nbr_interface_state_change_ctx_t_ adj_nbr_interface_state_change_ctx_t
Context for the state change walk of the DB.
struct ip_adjacency_t_::@164::@166 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
format_function_t format_ip_adjacency
Definition: format.h:58
void adj_nbr_walk_nh6(u32 sw_if_index, const ip6_address_t *addr, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given v6 next-hop.
Definition: adj_nbr.c:514
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109