FD.io VPP  v17.01.1-3-gc6833f8
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  adj->lookup_next_index = 0;
65 
66  fib_node_init(&adj->ia_node,
68  adj->ia_nh_proto = proto;
69  adj->ia_flags = 0;
70 
73 
74  return (adj);
75 }
76 
77 static int
79 {
80  if (ADJ_INDEX_INVALID == adj_index)
81  return (!0);
82 
83  return (0);
84 }
85 
86 /**
87  * @brief Pretty print helper function for formatting specific adjacencies.
88  * @param s - input string to format
89  * @param args - other args passed to format function such as:
90  * - vnet_main_t
91  * - ip_lookup_main_t
92  * - adj_index
93  */
94 u8 *
95 format_ip_adjacency (u8 * s, va_list * args)
96 {
98  ip_adjacency_t * adj;
99  u32 adj_index;
100 
101  adj_index = va_arg (*args, u32);
102  fiaf = va_arg (*args, format_ip_adjacency_flags_t);
103  adj = adj_get(adj_index);
104 
105  switch (adj->lookup_next_index)
106  {
108  s = format (s, "%U", format_adj_nbr, adj_index, 0);
109  break;
110  case IP_LOOKUP_NEXT_ARP:
111  s = format (s, "%U", format_adj_nbr_incomplete, adj_index, 0);
112  break;
114  s = format (s, "%U", format_adj_glean, adj_index, 0);
115  break;
117  s = format (s, "%U", format_adj_midchain, adj_index, 2);
118  break;
119  default:
120  break;
121  }
122 
123  if (fiaf & FORMAT_IP_ADJACENCY_DETAIL)
124  {
125  s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
126  s = format (s, " node:[%d]:%U",
127  adj->rewrite_header.node_index,
129  adj->rewrite_header.node_index);
130  s = format (s, " next:[%d]:%U",
131  adj->rewrite_header.next_index,
133  vlib_get_main(),
134  adj->rewrite_header.node_index,
135  adj->rewrite_header.next_index);
136  s = format(s, "\n children:\n ");
138  }
139 
140  return s;
141 }
142 
143 /*
144  * adj_last_lock_gone
145  *
146  * last lock/reference to the adj has gone, we no longer need it.
147  */
148 static void
150 {
151  vlib_main_t * vm = vlib_get_main();
152 
154  ADJ_DBG(adj, "last-lock-gone");
155 
157 
158  switch (adj->lookup_next_index)
159  {
161  dpo_reset(&adj->sub_type.midchain.next_dpo);
162  /* FALL THROUGH */
163  case IP_LOOKUP_NEXT_ARP:
165  /*
166  * complete and incomplete nbr adjs
167  */
169  adj->ia_nh_proto,
170  adj->ia_link,
171  &adj->sub_type.nbr.next_hop,
172  adj->rewrite_header.sw_if_index);
173  break;
176  adj->rewrite_header.sw_if_index);
177  break;
178  default:
179  /*
180  * type not stored in any DB from which we need to remove it
181  */
182  break;
183  }
184 
186 
187  fib_node_deinit(&adj->ia_node);
188  pool_put(adj_pool, adj);
189 }
190 
191 void
193 {
194  ip_adjacency_t *adj;
195 
196  if (adj_index_is_special(adj_index))
197  {
198  return;
199  }
200 
201  adj = adj_get(adj_index);
202  ASSERT(adj);
203 
204  ADJ_DBG(adj, "lock");
205  fib_node_lock(&adj->ia_node);
206 }
207 
208 void
210 {
211  ip_adjacency_t *adj;
212 
213  if (adj_index_is_special(adj_index))
214  {
215  return;
216  }
217 
218  adj = adj_get(adj_index);
219  ASSERT(adj);
220 
221  ADJ_DBG(adj, "unlock");
222  ASSERT(adj);
223 
224  fib_node_unlock(&adj->ia_node);
225 }
226 
227 u32
229  fib_node_type_t child_type,
230  fib_node_index_t child_index)
231 {
232  ASSERT(ADJ_INDEX_INVALID != adj_index);
233  if (adj_index_is_special(adj_index))
234  {
235  return (~0);
236  }
237 
239  adj_index,
240  child_type,
241  child_index));
242 }
243 
244 void
246  u32 sibling_index)
247 {
248  if (adj_index_is_special(adj_index))
249  {
250  return;
251  }
252 
254  adj_index,
255  sibling_index);
256 }
257 
258 /**
259  * @brief Return the link type of the adjacency
260  */
263 {
264  const ip_adjacency_t *adj;
265 
266  adj = adj_get(ai);
267 
268  return (adj->ia_link);
269 }
270 
271 /**
272  * @brief Return the sw interface index of the adjacency.
273  */
274 u32
276 {
277  const ip_adjacency_t *adj;
278 
279  adj = adj_get(ai);
280 
281  return (adj->rewrite_header.sw_if_index);
282 }
283 
284 /**
285  * @brief Return the link type of the adjacency
286  */
287 const u8*
289 {
290  vnet_rewrite_header_t *rw;
291  ip_adjacency_t *adj;
292 
293  adj = adj_get(ai);
294  rw = &adj->rewrite_header;
295 
296  ASSERT (rw->data_bytes != 0xfefe);
297 
298  return (rw->data - rw->data_bytes);
299 }
300 
301 static fib_node_t *
303 {
304  ip_adjacency_t *adj;
305 
306  adj = adj_get(index);
307 
308  return (&adj->ia_node);
309 }
310 
311 #define ADJ_FROM_NODE(_node) \
312  ((ip_adjacency_t*)((char*)_node - STRUCT_OFFSET_OF(ip_adjacency_t, ia_node)))
313 
314 static void
316 {
318 }
319 
323 {
324  /*
325  * Que pasa. yo soj en el final!
326  */
327  ASSERT(0);
328 
330 }
331 
332 /*
333  * Adjacency's graph node virtual function table
334  */
335 static const fib_node_vft_t adj_vft = {
337  .fnv_last_lock = adj_node_last_lock_gone,
338  .fnv_back_walk = adj_back_walk_notify,
339 };
340 
341 static clib_error_t *
343 {
345 
349 
350  /*
351  * one special adj to reserve index 0
352  */
353  special_v4_miss_adj_with_index_zero = adj_alloc(FIB_PROTOCOL_IP4);
354 
355  return (NULL);
356 }
357 
359 
360 static clib_error_t *
362  unformat_input_t * input,
363  vlib_cli_command_t * cmd)
364 {
366  u32 sw_if_index = ~0;
367 
369  {
370  if (unformat (input, "%d", &ai))
371  ;
372  else if (unformat (input, "%U",
374  &sw_if_index))
375  ;
376  else
377  break;
378  }
379 
380  if (ADJ_INDEX_INVALID != ai)
381  {
382  if (pool_is_free_index(adj_pool, ai))
383  {
384  vlib_cli_output (vm, "adjacency %d invalid", ai);
385  return 0;
386  }
387 
388  vlib_cli_output (vm, "[@%d] %U",
389  ai,
392  }
393  else
394  {
395  /* *INDENT-OFF* */
396  pool_foreach_index(ai, adj_pool,
397  ({
398  if (~0 != sw_if_index &&
399  sw_if_index != adj_get_sw_if_index(ai))
400  {
401  }
402  else
403  {
404  vlib_cli_output (vm, "[@%d] %U",
405  ai,
408  }
409  }));
410  /* *INDENT-ON* */
411  }
412 
413  return 0;
414 }
415 
416 /*?
417  * Show all adjacencies.
418  * @cliexpar
419  * @cliexstart{sh adj}
420  * [@0]
421  * [@1] glean: loop0
422  * [@2] ipv4 via 1.0.0.2 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
423  * [@3] mpls via 1.0.0.2 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
424  * [@4] ipv4 via 1.0.0.3 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
425  * [@5] mpls via 1.0.0.3 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
426  * @cliexend
427  ?*/
428 VLIB_CLI_COMMAND (adj_show_command, static) = {
429  .path = "show adj",
430  .short_help = "show adj [<adj_index>] [interface]",
431  .function = adj_show,
432 };
433 
434 /*
435  * DEPRECATED: DO NOT USE
436  */
439  ip_adjacency_t * copy_adj,
440  u32 n_adj,
441  u32 * adj_index_return)
442 {
443  ip_adjacency_t * adj;
444 
445  ASSERT(1==n_adj);
446 
448 
449  if (copy_adj)
450  *adj = *copy_adj;
451 
452  *adj_index_return = adj_get_index(adj);
453  return adj;
454 }
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:369
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:970
static int adj_index_is_special(adj_index_t adj_index)
Definition: adj.c:78
void adj_lock(adj_index_t adj_index)
An adjacency is a representation of an attached L3 peer.
Definition: adj.c:192
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:183
const u8 * adj_get_rewrite(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:288
#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:262
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:188
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:198
ip_lookup_main_t lookup_main
Definition: ip4.h:97
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:949
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:438
void adj_child_remove(adj_index_t adj_index, u32 sibling_index)
Remove a child dependent.
Definition: adj.c:245
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
union ip_adjacency_t_::@175 sub_type
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:215
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
ip_adjacency_flags_t ia_flags
Flags on the adjacency.
Definition: lookup.h:281
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:209
format_function_t format_vlib_next_node_name
Definition: node_funcs.h:1105
void adj_nbr_remove(adj_index_t ai, 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 "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:78
#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:275
enum format_ip_adjacency_flags_t_ format_ip_adjacency_flags_t
void fib_node_lock(fib_node_t *node)
Definition: fib_node.c:204
void adj_midchain_module_init(void)
Module initialisation.
Definition: adj_midchain.c:556
#define ADJ_FROM_NODE(_node)
Definition: adj.c:311
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:321
An node in the FIB graph.
Definition: fib_node.h:273
void adj_nbr_module_init(void)
Module initialisation.
Definition: adj_nbr.c:1079
void fib_node_unlock(fib_node_t *node)
Definition: fib_node.c:210
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:30
fib_node_t ia_node
Definition: lookup.h:276
void adj_glean_module_init(void)
Module initialisation.
Definition: adj_glean.c:282
static clib_error_t * adj_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adj.c:361
fib_node_list_t fn_children
Vector of nodes that depend upon/use/share this node.
Definition: fib_node.h:290
static void adj_last_lock_gone(ip_adjacency_t *adj)
Definition: adj.c:149
u16 mcast_group_index
Force re-lookup in a different FIB.
Definition: lookup.h:207
struct ip_adjacency_t_::@175::@176 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
fib_node_get_t fnv_get
Definition: fib_node.h:261
u8 * format_adj_glean(u8 *s, va_list *ap)
Format/display a glean adjacency.
Definition: adj_glean.c:223
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
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1163
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:73
Context passed between object during a back walk.
Definition: fib_node.h:186
#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:480
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:302
ip6_main_t ip6_main
Definition: ip6_forward.c:2828
ip_lookup_main_t lookup_main
Definition: ip6.h:135
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:89
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:194
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:199
u32 fn_locks
Number of dependents on this node.
Definition: fib_node.h:296
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:228
u8 * format_ip_adjacency(u8 *s, va_list *args)
Pretty print helper function for formatting specific adjacencies.
Definition: adj.c:95
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:210
static void adj_node_last_lock_gone(fib_node_t *node)
Definition: adj.c:315
A FIB graph nodes virtual function table.
Definition: fib_node.h:260
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:1195
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1099
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:83
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:191
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:342
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:174
struct ip_adjacency_t_::@175::@177 midchain
IP_LOOKUP_NEXT_MIDCHAIN.