FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
adj.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.h>
17 #include <vnet/adj/adj_internal.h>
18 #include <vnet/adj/adj_glean.h>
19 #include <vnet/adj/adj_midchain.h>
20 #include <vnet/fib/fib_node_list.h>
21 
22 /*
23  * Special Adj with index zero. we need to define this since the v4 mtrie
24  * assumes an index of 0 implies the ply is empty. therefore all 'real'
25  * adjs need a non-zero index.
26  */
28 
29 /* Adjacency packet/byte counters indexed by adjacency index. */
31 
32 /*
33  * the single adj pool
34  */
36 
37 always_inline void
39 {
40  if (CLIB_DEBUG > 0)
41  {
42  memset (adj, 0xfe, sizeof (adj[0]));
43  }
44 }
45 
48 {
49  ip_adjacency_t *adj;
50 
51  pool_get(adj_pool, adj);
52 
53  adj_poison(adj);
54 
55  /* Make sure certain fields are always initialized. */
56  /* Validate adjacency counters. */
57  vlib_validate_combined_counter(&adjacency_counters,
58  adj_get_index(adj));
59 
60  adj->rewrite_header.sw_if_index = ~0;
61  adj->mcast_group_index = ~0;
62  adj->saved_lookup_next_index = 0;
63  adj->n_adj = 1;
64 
65  fib_node_init(&adj->ia_node,
67  adj->ia_nh_proto = proto;
68 
71 
72  return (adj);
73 }
74 
75 static int
77 {
78  if (ADJ_INDEX_INVALID == adj_index)
79  return (!0);
80 
81  return (0);
82 }
83 
84 /**
85  * @brief Pretty print helper function for formatting specific adjacencies.
86  * @param s - input string to format
87  * @param args - other args passed to format function such as:
88  * - vnet_main_t
89  * - ip_lookup_main_t
90  * - adj_index
91  */
92 u8 *
93 format_ip_adjacency (u8 * s, va_list * args)
94 {
96  ip_adjacency_t * adj;
97  u32 adj_index;
98 
99  adj_index = va_arg (*args, u32);
100  fiaf = va_arg (*args, format_ip_adjacency_flags_t);
101  adj = adj_get(adj_index);
102 
103  switch (adj->lookup_next_index)
104  {
106  s = format (s, "%U", format_adj_nbr, adj_index, 0);
107  break;
108  case IP_LOOKUP_NEXT_ARP:
109  s = format (s, "%U", format_adj_nbr_incomplete, adj_index, 0);
110  break;
112  s = format (s, "%U", format_adj_glean, adj_index, 0);
113  break;
115  s = format (s, "%U", format_adj_midchain, adj_index, 2);
116  break;
117  default:
118  break;
119  }
120 
121  if (fiaf & FORMAT_IP_ADJACENCY_DETAIL)
122  {
123  s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
124  s = format (s, " node:[%d]:%U",
125  adj->rewrite_header.node_index,
127  adj->rewrite_header.node_index);
128  s = format (s, " next:[%d]:%U",
129  adj->rewrite_header.next_index,
131  vlib_get_main(),
132  adj->rewrite_header.node_index,
133  adj->rewrite_header.next_index);
134  s = format(s, "\n children:\n ");
136  }
137 
138  return s;
139 }
140 
141 /*
142  * adj_last_lock_gone
143  *
144  * last lock/reference to the adj has gone, we no longer need it.
145  */
146 static void
148 {
149  vlib_main_t * vm = vlib_get_main();
150 
152  ADJ_DBG(adj, "last-lock-gone");
153 
155 
156  switch (adj->lookup_next_index)
157  {
159  dpo_reset(&adj->sub_type.midchain.next_dpo);
160  /* FALL THROUGH */
161  case IP_LOOKUP_NEXT_ARP:
163  /*
164  * complete and incomplete nbr adjs
165  */
167  adj->ia_link,
168  &adj->sub_type.nbr.next_hop,
169  adj->rewrite_header.sw_if_index);
170  break;
173  adj->rewrite_header.sw_if_index);
174  break;
175  default:
176  /*
177  * type not stored in any DB from which we need to remove it
178  */
179  break;
180  }
181 
183 
184  fib_node_deinit(&adj->ia_node);
185  pool_put(adj_pool, adj);
186 }
187 
188 void
190 {
191  ip_adjacency_t *adj;
192 
193  if (adj_index_is_special(adj_index))
194  {
195  return;
196  }
197 
198  adj = adj_get(adj_index);
199  ASSERT(adj);
200 
201  ADJ_DBG(adj, "lock");
202  fib_node_lock(&adj->ia_node);
203 }
204 
205 void
207 {
208  ip_adjacency_t *adj;
209 
210  if (adj_index_is_special(adj_index))
211  {
212  return;
213  }
214 
215  adj = adj_get(adj_index);
216  ASSERT(adj);
217 
218  ADJ_DBG(adj, "unlock");
219  ASSERT(adj);
220 
221  fib_node_unlock(&adj->ia_node);
222 }
223 
224 u32
226  fib_node_type_t child_type,
227  fib_node_index_t child_index)
228 {
229  ASSERT(ADJ_INDEX_INVALID != adj_index);
230  if (adj_index_is_special(adj_index))
231  {
232  return (~0);
233  }
234 
236  adj_index,
237  child_type,
238  child_index));
239 }
240 
241 void
243  u32 sibling_index)
244 {
245  if (adj_index_is_special(adj_index))
246  {
247  return;
248  }
249 
251  adj_index,
252  sibling_index);
253 }
254 
255 /**
256  * @brief Return the link type of the adjacency
257  */
260 {
261  const ip_adjacency_t *adj;
262 
263  adj = adj_get(ai);
264 
265  return (adj->ia_link);
266 }
267 
268 /**
269  * @brief Return the sw interface index of the adjacency.
270  */
271 u32
273 {
274  const ip_adjacency_t *adj;
275 
276  adj = adj_get(ai);
277 
278  return (adj->rewrite_header.sw_if_index);
279 }
280 
281 /**
282  * @brief Return the link type of the adjacency
283  */
284 const u8*
286 {
287  vnet_rewrite_header_t *rw;
288  ip_adjacency_t *adj;
289 
290  adj = adj_get(ai);
291  rw = &adj->rewrite_header;
292 
293  ASSERT (rw->data_bytes != 0xfefe);
294 
295  return (rw->data - rw->data_bytes);
296 }
297 
298 static fib_node_t *
300 {
301  ip_adjacency_t *adj;
302 
303  adj = adj_get(index);
304 
305  return (&adj->ia_node);
306 }
307 
308 #define ADJ_FROM_NODE(_node) \
309  ((ip_adjacency_t*)((char*)_node - STRUCT_OFFSET_OF(ip_adjacency_t, ia_node)))
310 
311 static void
313 {
315 }
316 
320 {
321  /*
322  * Que pasa. yo soj en el final!
323  */
324  ASSERT(0);
325 
327 }
328 
329 /*
330  * Adjacency's graph node virtual function table
331  */
332 static const fib_node_vft_t adj_vft = {
334  .fnv_last_lock = adj_node_last_lock_gone,
335  .fnv_back_walk = adj_back_walk_notify,
336 };
337 
338 static clib_error_t *
340 {
342 
346 
347  /*
348  * one special adj to reserve index 0
349  */
350  special_v4_miss_adj_with_index_zero = adj_alloc(FIB_PROTOCOL_IP4);
351 
352  return (NULL);
353 }
354 
356 
357 static clib_error_t *
359  unformat_input_t * input,
360  vlib_cli_command_t * cmd)
361 {
363  u32 sw_if_index = ~0;
364 
366  {
367  if (unformat (input, "%d", &ai))
368  ;
369  else if (unformat (input, "%U",
371  &sw_if_index))
372  ;
373  else
374  break;
375  }
376 
377  if (ADJ_INDEX_INVALID != ai)
378  {
379  vlib_cli_output (vm, "[@%d] %U",
380  ai,
383  }
384  else
385  {
386  /* *INDENT-OFF* */
387  pool_foreach_index(ai, adj_pool,
388  ({
389  if (~0 != sw_if_index &&
390  sw_if_index == adj_get_sw_if_index(ai))
391  {
392  vlib_cli_output (vm, "[@%d] %U",
393  ai,
396  }
397  }));
398  /* *INDENT-ON* */
399  }
400 
401  return 0;
402 }
403 
404 /*?
405  * Show all adjacencies.
406  * @cliexpar
407  * @cliexstart{sh adj}
408  * [@0]
409  * [@1] glean: loop0
410  * [@2] ipv4 via 1.0.0.2 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
411  * [@3] mpls via 1.0.0.2 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
412  * [@4] ipv4 via 1.0.0.3 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
413  * [@5] mpls via 1.0.0.3 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
414  * @cliexend
415  ?*/
416 VLIB_CLI_COMMAND (adj_show_command, static) = {
417  .path = "show adj",
418  .short_help = "show adj [<adj_index>] [interface]",
419  .function = adj_show,
420 };
421 
422 /*
423  * DEPRECATED: DO NOT USE
424  */
427  ip_adjacency_t * copy_adj,
428  u32 n_adj,
429  u32 * adj_index_return)
430 {
431  ip_adjacency_t * adj;
432 
433  ASSERT(1==n_adj);
434 
436 
437  if (copy_adj)
438  *adj = *copy_adj;
439 
440  *adj_index_return = adj_get_index(adj);
441  return adj;
442 }
void adj_glean_remove(fib_protocol_t proto, u32 sw_if_index)
Definition: adj_glean.c:92
ip_adjacency_t * adj_pool
The global adjacnecy pool.
Definition: adj.c:35
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:110
enum fib_node_type_t_ fib_node_type_t
The types of nodes in a FIB graph.
ip_adjacency_t * adjacency_heap
Definition: lookup.h:335
format_function_t format_vlib_node_name
Definition: node_funcs.h:1104
u8 * format_adj_nbr(u8 *s, va_list *ap)
Format a neigbour (REWRITE) adjacency.
Definition: adj_nbr.c:804
static int adj_index_is_special(adj_index_t adj_index)
Definition: adj.c:76
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
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:172
const u8 * adj_get_rewrite(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:285
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:259
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:174
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
struct ip_adjacency_t_::@164::@165 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:187
ip_lookup_main_t lookup_main
Definition: ip4.h:96
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
ip_adjacency_t * ip_add_adjacency(ip_lookup_main_t *lm, ip_adjacency_t *copy_adj, u32 n_adj, u32 *adj_index_return)
Definition: adj.c:426
void adj_child_remove(adj_index_t adj_index, u32 sibling_index)
Remove a child dependent.
Definition: adj.c:242
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
u32 fib_node_child_add(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_type_t type, fib_node_index_t index)
Definition: fib_node.c:96
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:58
vnet_link_t ia_link
Definition: lookup.h:199
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
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:206
format_function_t format_vlib_next_node_name
Definition: node_funcs.h:1105
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:77
#define ADJ_DBG(_e, _fmt, _args...)
big switch to turn on Adjacency debugging
Definition: adj_internal.h:41
#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
u32 adj_get_sw_if_index(adj_index_t ai)
Return the sw interface index of the adjacency.
Definition: adj.c:272
enum format_ip_adjacency_flags_t_ format_ip_adjacency_flags_t
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
void fib_node_lock(fib_node_t *node)
Definition: fib_node.c:193
void adj_midchain_module_init(void)
Module initialisation.
Definition: adj_midchain.c:587
#define ADJ_FROM_NODE(_node)
Definition: adj.c:308
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
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static fib_node_back_walk_rc_t adj_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: adj.c:318
An node in the FIB graph.
Definition: fib_node.h:242
void adj_nbr_module_init(void)
Module initialisation.
Definition: adj_nbr.c:913
void fib_node_unlock(fib_node_t *node)
Definition: fib_node.c:199
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:30
fib_node_t ia_node
Definition: lookup.h:256
void adj_glean_module_init(void)
Module initialisation.
Definition: adj_glean.c:243
static clib_error_t * adj_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adj.c:358
union ip_adjacency_t_::@164 sub_type
fib_node_list_t fn_children
Vector of nodes that depend upon/use/share this node.
Definition: fib_node.h:259
static void adj_last_lock_gone(ip_adjacency_t *adj)
Definition: adj.c:147
u16 mcast_group_index
Force re-lookup in a different FIB.
Definition: lookup.h:191
fib_node_get_t fnv_get
Definition: fib_node.h:230
u8 * format_adj_glean(u8 *s, va_list *ap)
Format/display a glean adjacency.
Definition: adj_glean.c:184
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
static void adj_poison(ip_adjacency_t *adj)
Definition: adj.c:38
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
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:72
Context passed between object during a back walk.
Definition: fib_node.h:160
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u8 * format_adj_midchain(u8 *s, va_list *ap)
Format a midchain adjacency.
Definition: adj_midchain.c:511
u32 fib_node_list_get_size(fib_node_list_t list)
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static fib_node_t * adj_get_node(fib_node_index_t index)
Definition: adj.c:299
ip6_main_t ip6_main
Definition: ip6_forward.c:2655
ip_lookup_main_t lookup_main
Definition: ip6.h:132
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
This packets follow a mid-chain adjacency.
Definition: lookup.h:88
void fib_node_child_remove(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_index_t sibling_index)
Definition: fib_node.c:121
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:179
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:183
u32 fn_locks
Number of dependents on this node.
Definition: fib_node.h:265
u32 adj_child_add(adj_index_t adj_index, fib_node_type_t child_type, fib_node_index_t child_index)
Add a child dependent to an adjacency.
Definition: adj.c:225
u8 * format_ip_adjacency(u8 *s, va_list *args)
Pretty print helper function for formatting specific adjacencies.
Definition: adj.c:93
ip_adjacency_t * adj_alloc(fib_protocol_t proto)
Definition: adj.c:47
A collection of combined counters.
Definition: counter.h:212
u16 saved_lookup_next_index
Highest possible perf subgraph arc interposition, e.g.
Definition: lookup.h:194
static void adj_node_last_lock_gone(fib_node_t *node)
Definition: adj.c:312
A FIB graph nodes virtual function table.
Definition: fib_node.h:229
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
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1060
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:82
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:171
static ip_adjacency_t * special_v4_miss_adj_with_index_zero
Definition: adj.c:27
static clib_error_t * adj_module_init(vlib_main_t *vm)
Definition: adj.c:339
struct _unformat_input_t unformat_input_t
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:390
u8 * fib_node_children_format(fib_node_list_t list, u8 *s)
Definition: fib_node.c:163
struct ip_adjacency_t_::@164::@166 midchain
IP_LOOKUP_NEXT_MIDCHAIN.