FD.io VPP  v16.06
Vector Packet Processing
sticky_hash.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include <vnet/l2/l2_classify.h>
16 
17 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/ip/ip_packet.h>
22 #include <vnet/ip/ip4_packet.h>
23 #include <vnet/ip/ip6_packet.h>
24 #include <vppinfra/error.h>
25 
26 typedef struct {
29  /* Not strictly needed, for show command */
32 
33 typedef struct {
35 
36  /* next index added to l2_classify */
38 
39  /* session pool */
41 
42  /* Forward and reverse data session setup buffers */
43  u8 fdata[3 * sizeof (u32x4)];
44  u8 rdata[3 * sizeof (u32x4)];
45 
46  /* convenience variables */
52 
53 typedef struct {
54  /* $$$$ fill in with per-pkt trace data */
58 
59 /* packet trace format function */
60 static u8 * format_sticky_hash_miss_trace (u8 * s, va_list * args)
61 {
62  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
63  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
64  sticky_hash_miss_trace_t * t = va_arg (*args, sticky_hash_miss_trace_t *);
65 
66  s = format (s, "STICKY_HASH_MISS: sw_if_index %d",
67  t->sw_if_index);
68  return s;
69 }
70 
71 typedef CLIB_PACKED(struct {
73  ip4_header_t ip;
74 }) classify_data_or_mask_t;
75 
76 sticky_hash_main_t sticky_hash_main;
77 
79 
80 #define foreach_sticky_hash_miss_error \
81 _(MISSES, "forward flow classify misses")
82 
83 typedef enum {
84 #define _(sym,str) STICKY_HASH_MISS_ERROR_##sym,
86 #undef _
87  STICKY_HASH_MISS_N_ERROR,
89 
90 static char * sticky_hash_miss_error_strings[] = {
91 #define _(sym,string) string,
93 #undef _
94 };
95 
96 /*
97  * To drop a pkt and increment one of the previous counters:
98  *
99  * set b0->error = error_node->errors[STICKY_HASH_MISS_ERROR_EXAMPLE];
100  * set next0 to a disposition index bound to "error-drop".
101  *
102  * To manually increment the specific counter STICKY_HASH_MISS_ERROR_EXAMPLE:
103  *
104  * vlib_node_t *n = vlib_get_node (vm, sticky_hash_miss.index);
105  * u32 node_counter_base_index = n->error_heap_index;
106  * vlib_error_main_t * em = &vm->error_main;
107  * em->counters[node_counter_base_index + STICKY_HASH_MISS_ERROR_EXAMPLE] += 1;
108  *
109  */
110 
111 typedef enum {
115 
116 static uword
118  vlib_node_runtime_t * node,
119  vlib_frame_t * frame)
120 {
121  u32 n_left_from, * from, * to_next;
122  sticky_hash_miss_next_t next_index;
123  sticky_hash_main_t * mp = &sticky_hash_main;
124  vlib_node_t *n = vlib_get_node (vm, sticky_hash_miss_node.index);
125  u32 node_counter_base_index = n->error_heap_index;
126  vlib_error_main_t * em = &vm->error_main;
128  ip4_main_t * im = &ip4_main;
129 
130  from = vlib_frame_vector_args (frame);
131  n_left_from = frame->n_vectors;
132  next_index = node->cached_next_index;
133 
134  while (n_left_from > 0)
135  {
136  u32 n_left_to_next;
137 
138  vlib_get_next_frame (vm, node, next_index,
139  to_next, n_left_to_next);
140 
141  while (n_left_from > 0 && n_left_to_next > 0)
142  {
143  u32 bi0;
144  vlib_buffer_t * b0;
145  u32 next0;
146  u32 sw_if_index0;
147  u32 fib_index0, ft_index0, rt_index0;
148  vnet_classify_table_3_t * ft0, * rt0;
149  vnet_classify_entry_3_t * fe0, * re0;
150  classify_data_or_mask_t * h0;
151  u8 was_found0;
152  ip4_fib_t * fib0;
154  u32 tmp;
155 
156  /* speculatively enqueue b0 to the current next frame */
157  bi0 = from[0];
158  to_next[0] = bi0;
159  from += 1;
160  to_next += 1;
161  n_left_from -= 1;
162  n_left_to_next -= 1;
163 
164  b0 = vlib_get_buffer (vm, bi0);
165 
166  sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
167  next0 = mp->cached_next_index;
168 
169  h0 = vlib_buffer_get_current (b0);
170 
171  /* Add forward and reverse entries for this flow */
172  clib_memcpy (mp->fdata, h0, sizeof (mp->fdata));
173  clib_memcpy (mp->rdata, h0, sizeof (mp->rdata));
174 
175  h0 = (classify_data_or_mask_t *)(mp->rdata);
176 
177  /* swap src + dst addresses to form reverse data */
178  tmp = h0->ip.src_address.as_u32;
179  h0->ip.src_address.as_u32 = h0->ip.dst_address.as_u32;
180  h0->ip.dst_address.as_u32 = tmp;
181 
182  /* dig up fwd + rev tables */
183  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
184  fib0 = vec_elt_at_index (im->fibs, fib_index0);
185 
186  ft_index0 = fib0->fwd_classify_table_index;
187  rt_index0 = fib0->rev_classify_table_index;
188 
189  ft0 = (vnet_classify_table_3_t *)
190  pool_elt_at_index (cm->tables, ft_index0);
191  rt0 = (vnet_classify_table_3_t *)
192  pool_elt_at_index (cm->tables, rt_index0);
193 
194  fe0 = vnet_classify_find_or_add_entry_3 (ft0, mp->fdata, &was_found0);
195  fe0->next_index = L2_CLASSIFY_NEXT_IP4_INPUT;
196  fe0->advance = sizeof (ethernet_header_t);
197 
198  re0 = vnet_classify_find_or_add_entry_3 (rt0, mp->rdata, 0);
199  re0->next_index = L2_CLASSIFY_NEXT_IP4_INPUT; /* $$$ FIXME */
200  re0->advance = sizeof (ethernet_header_t);
201 
202  /* Note: we could get a whole vector of misses for the same sess */
203  if (was_found0 == 0)
204  {
205  pool_get (mp->sessions, s);
206 
207  fe0->opaque_index = s - mp->sessions;
208  re0->opaque_index = s - mp->sessions;
209 
210  s->fwd_entry_index = fe0 - ft0->entries;
211  s->rev_entry_index = re0 - rt0->entries;
212  s->fib_index = fib_index0;
213  }
214 
216  && (b0->flags & VLIB_BUFFER_IS_TRACED))) {
218  vlib_add_trace (vm, node, b0, sizeof (*t));
219  t->sw_if_index = sw_if_index0;
220  t->next_index = next0;
221  }
222 
223  em->counters[node_counter_base_index + STICKY_HASH_MISS_ERROR_MISSES]
224  += 1;
225 
226  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
227 
228  /* verify speculative enqueue, maybe switch current next frame */
229  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
230  to_next, n_left_to_next,
231  bi0, next0);
232  }
233 
234  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
235  }
236 
237  return frame->n_vectors;
238 }
239 
240 VLIB_REGISTER_NODE (sticky_hash_miss_node) = {
241  .function = sticky_hash_miss_node_fn,
242  .name = "sticky-hash-miss",
243  .vector_size = sizeof (u32),
244  .format_trace = format_sticky_hash_miss_trace,
246 
247  .n_errors = ARRAY_LEN(sticky_hash_miss_error_strings),
248  .error_strings = sticky_hash_miss_error_strings,
249 
250  .n_next_nodes = STICKY_HASH_MISS_N_NEXT,
251 
252  /* edit / add dispositions here */
253  .next_nodes = {
254  [STICKY_HASH_MISS_NEXT_IP4_INPUT] = "ip4-input",
255  },
256 };
257 
259 {
260  sticky_hash_main_t * mp = &sticky_hash_main;
261 
262  mp->vlib_main = vm;
263  mp->vnet_main = vnet_get_main();
266 
267  return 0;
268 }
269 
271 
274  u32 fwd_sw_if_index, u8 * fwd_mask,
275  u32 rev_sw_if_index, u8 * rev_mask,
276  u32 nbuckets, int enable_disable)
277 {
278  ip4_main_t * im = &ip4_main;
279  u32 fib_index;
280  ip4_fib_t * fib;
283  vnet_classify_table_3_t * ft, * rt;
284 
285  fib_index = vec_elt (im->fib_index_by_sw_if_index, fwd_sw_if_index);
286  fib = vec_elt_at_index (im->fibs, fib_index);
287 
288  if (fib->fwd_classify_table_index == ~0)
289  {
290  /* Set up forward table */
291  ft = (vnet_classify_table_3_t *)
292  vnet_classify_new_table (cm, fwd_mask, nbuckets,
293  0 /* skip */, 3 /* match */);
295  = ft - (vnet_classify_table_3_t *) cm->tables;
296  mp->fwd_miss_next_index =
298  sticky_hash_miss_node.index);
299  ft->miss_next_index = mp->fwd_miss_next_index;
300 
301  /* Set up reverse table */
302  rt = (vnet_classify_table_3_t *)
303  vnet_classify_new_table (cm, rev_mask, nbuckets,
304  0 /* skip */, 3 /* match */);
306  = rt - (vnet_classify_table_3_t *) cm->tables;
307  }
308 
309  vec_validate
311  fwd_sw_if_index);
312 
313  vec_validate
315  fwd_sw_if_index);
316 
317  vec_validate
319  fwd_sw_if_index);
320 
322  [fwd_sw_if_index] = fib->fwd_classify_table_index;
323 
325  [fwd_sw_if_index] = ~0;
326 
328  [fwd_sw_if_index] = ~0;
329 
330 
331  vec_validate
333  rev_sw_if_index);
334 
335  vec_validate
337  rev_sw_if_index);
338 
339  vec_validate
341  rev_sw_if_index);
342 
343 
345  [rev_sw_if_index] = fib->rev_classify_table_index;
346 
348  [rev_sw_if_index] = ~0;
349 
351  [rev_sw_if_index] = ~0;
352 
353  vnet_l2_classify_enable_disable (fwd_sw_if_index, enable_disable);
354  vnet_l2_classify_enable_disable (rev_sw_if_index, enable_disable);
355  return 0;
356 }
357 
358 static clib_error_t *
360  unformat_input_t * input,
361  vlib_cli_command_t * cmd)
362 {
363  u32 fwd_sw_if_index = ~0, rev_sw_if_index = ~0;
364  int enable_disable = 1;
365  u32 nbuckets = 2;
366  int rv;
367  sticky_hash_main_t * mp = &sticky_hash_main;
368  classify_data_or_mask_t fwd_mask, rev_mask;
369  u8 * fm = 0, * rm = 0;
370 
371  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
372  if (unformat (input, "fwd %U", unformat_vnet_sw_interface, mp->vnet_main,
373  &fwd_sw_if_index))
374  ;
375  if (unformat (input, "rev %U", unformat_vnet_sw_interface, mp->vnet_main,
376  &rev_sw_if_index))
377  ;
378  else if (unformat (input, "nbuckets %d", &nbuckets))
379  ;
380  else if (unformat (input, "disable"))
381  enable_disable = 0;
382 
383  else break;
384  }
385 
386  nbuckets = 1<<max_log2(nbuckets);
387 
388  if (fwd_sw_if_index == ~0)
389  return clib_error_return (0, "fwd interface not set");
390 
391  if (rev_sw_if_index == ~0)
392  return clib_error_return (0, "rev interface not set");
393 
394  if (!is_pow2(nbuckets))
395  return clib_error_return (0, "nbuckets %d not a power of 2", nbuckets);
396 
397  ASSERT(sizeof(fwd_mask) <= 3 * sizeof (u32x4));
398 
399  /* Mask on src/dst address, depending on direction */
400  memset(&fwd_mask, 0, sizeof (fwd_mask));
401  memset (&fwd_mask.ip.src_address, 0xff, 4);
402 
403  memset(&rev_mask, 0, sizeof (rev_mask));
404  memset (&rev_mask.ip.dst_address, 0xff, 4);
405 
406  vec_validate (fm, 3 * sizeof(u32x4) - 1);
407  vec_validate (rm, 3 * sizeof(u32x4) - 1);
408 
409  clib_memcpy (fm, &fwd_mask, sizeof (fwd_mask));
410  clib_memcpy (rm, &rev_mask, sizeof (rev_mask));
411 
412  rv = ip4_sticky_hash_enable_disable (mp, fwd_sw_if_index, fm,
413  rev_sw_if_index, rm,
414  nbuckets, enable_disable);
415 
416  vec_free (fm);
417  vec_free (rm);
418  switch (rv)
419  {
420  case 0:
421  return 0;
422 
423  default:
424  return clib_error_return (0, "ip4_sticky_hash_enable_disable returned %d",
425  rv);
426  }
427 
428  return 0;
429 }
430 
431 VLIB_CLI_COMMAND (sticky_hash_init_command, static) = {
432  .path = "ip sticky classify",
433  .short_help = "ip sticky classify fwd <intfc> rev <intfc> "
434  "[nbuckets <nn>][disable]",
436 };
437 
438 
439 u8 * format_sticky_hash_session (u8 * s, va_list * args)
440 {
441  sticky_hash_main_t * mp = va_arg(*args, sticky_hash_main_t *);
442  sticky_hash_session_t * session = va_arg(*args, sticky_hash_session_t *);
443  vnet_classify_table_3_t * t;
444  vnet_classify_entry_3_t * e;
445  ip4_main_t * im = &ip4_main;
447  ip4_fib_t * fib;
448  classify_data_or_mask_t * match;
449 
450  fib = vec_elt_at_index (im->fibs, session->fib_index);
451 
452  t = (vnet_classify_table_3_t *)
453  pool_elt_at_index (cm->tables, fib->fwd_classify_table_index);
454  e = pool_elt_at_index (t->entries, session->fwd_entry_index);
455  match = (classify_data_or_mask_t *)(e->key);
456 
457  s = format
458  (s,
459  "[%6d] fwd src %U next index %d session %d fib %d\n"
460  " hits %lld last-heard %.6f\n",
461  e - t->entries,
462  format_ip4_address, &match->ip.src_address,
463  e->next_index, e->opaque_index, fib->table_id,
464  e->hits, e->last_heard);
465 
466  if (e->opaque_index != session - mp->sessions)
467  s = format (s, "WARNING: forward session index mismatch!\n");
468 
469  t = (vnet_classify_table_3_t *)
470  pool_elt_at_index (cm->tables, fib->rev_classify_table_index);
471  e = pool_elt_at_index (t->entries, session->rev_entry_index);
472  match = (classify_data_or_mask_t *)(e->key);
473 
474  s = format
475  (s,
476  "[%6d] rev dst %U next index %d session %d\n"
477  " hits %lld last-heard %.6f\n",
478  e - t->entries,
479  format_ip4_address, &match->ip.dst_address,
480  e->next_index, e->opaque_index, e->hits, e->last_heard);
481 
482  if (e->opaque_index != session - mp->sessions)
483  s = format (s, "WARNING: reverse session index mismatch!\n");
484  s = format (s, "---------\n");
485 
486  return s;
487 }
488 
489 static clib_error_t *
491  unformat_input_t * input,
492  vlib_cli_command_t * cmd)
493 {
494  sticky_hash_main_t * mp = &sticky_hash_main;
496  int verbose = 0;
497  int dump_classifier_tables = 0;
498  ip4_fib_t * fib;
499  ip4_main_t * im4 = &ip4_main;
501 
502  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
503  if (unformat (input, "verbose"))
504  verbose = 1;
505  else if (unformat (input, "dump-tables")
506  || unformat (input, "dump-classifier-tables"))
507  dump_classifier_tables = 1;
508  else
509  break;
510  }
511 
512  if (pool_elts (mp->sessions) == 0)
513  vlib_cli_output (vm, "No ip sticky hash sessions");
514 
515 
516  vlib_cli_output (vm, "%d active sessions\n",
517  pool_elts (mp->sessions));
518 
519  vec_foreach (fib, im4->fibs)
520  {
521  if (fib->fwd_classify_table_index != ~0)
522  vlib_cli_output (vm, "fib %d fwd table: \n%U",
523  fib->table_id,
525  cm,
527  (cm->tables, fib->fwd_classify_table_index),
528  dump_classifier_tables);
529  if (fib->rev_classify_table_index != ~0)
530  vlib_cli_output (vm, "fib %d rev table: \n%U",
531  fib->table_id,
533  cm,
535  (cm->tables, fib->rev_classify_table_index),
536  dump_classifier_tables);
537  }
538 
539  if (verbose)
540  {
541  pool_foreach (s, mp->sessions,
542  ({
543  vlib_cli_output (vm, "%U", format_sticky_hash_session, mp, s);
544  }));
545  }
546  return 0;
547 }
548 
549 VLIB_CLI_COMMAND (show_sticky_hash_command, static) = {
550  .path = "show sticky classify",
551  .short_help = "Display sticky classifier tables",
553 };
554 
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
u32 error_heap_index
Definition: node.h:244
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
static u8 * format_sticky_hash_miss_trace(u8 *s, va_list *args)
Definition: sticky_hash.c:60
sticky_hash_session_t * sessions
Definition: sticky_hash.c:40
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
vlib_node_registration_t sticky_hash_miss_node
(constructor) VLIB_REGISTER_NODE (sticky_hash_miss_node)
Definition: sticky_hash.c:240
u8 rdata[3 *sizeof(u32x4)]
Definition: sticky_hash.c:44
u32 table_id
Definition: ip4.h:58
#define foreach_sticky_hash_miss_error
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
struct _vlib_node_registration vlib_node_registration_t
static char * sticky_hash_miss_error_strings[]
Definition: sticky_hash.c:90
u8 fdata[3 *sizeof(u32x4)]
Definition: sticky_hash.c:43
always_inline uword max_log2(uword x)
Definition: clib.h:216
u32 * fib_index_by_sw_if_index
Definition: ip4.h:137
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Definition: pool.h:186
format_function_t format_ip4_address
Definition: format.h:71
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
vnet_classify_main_t * vnet_classify_main
Definition: sticky_hash.c:49
u32 fwd_classify_table_index
Definition: ip4.h:67
u32 * classify_table_index_by_sw_if_index[L2_CLASSIFY_N_TABLES]
Definition: l2_classify.h:58
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define pool_foreach(VAR, POOL, BODY)
Definition: pool.h:328
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
vlib_main_t * vlib_main
Definition: sticky_hash.c:47
vnet_classify_table_t * vnet_classify_new_table(vnet_classify_main_t *cm, u8 *mask, u32 nbuckets, u32 memory_size, u32 skip_n_vectors, u32 match_n_vectors)
Definition: vnet_classify.c:99
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline uword pool_elts(void *v)
Definition: pool.h:97
u8 * format_sticky_hash_session(u8 *s, va_list *args)
Definition: sticky_hash.c:439
void vnet_l2_classify_enable_disable(u32 sw_if_index, int enable_disable)
Definition: l2_classify.c:428
u32 rev_classify_table_index
Definition: ip4.h:68
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
l2_classify_main_t l2_classify_main
Definition: l2_classify.c:47
sticky_hash_miss_next_t
Definition: sticky_hash.c:111
#define pool_elt_at_index(p, i)
Definition: pool.h:346
vlib_error_main_t error_main
Definition: main.h:124
clib_error_t * sticky_hash_miss_init(vlib_main_t *vm)
Definition: sticky_hash.c:258
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
u64 * counters
Definition: error.h:73
u16 n_vectors
Definition: node.h:307
vnet_main_t * vnet_main
Definition: sticky_hash.c:48
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
Definition: ip4.h:47
u8 * format_classify_table(u8 *s, va_list *args)
#define clib_memcpy(a, b, c)
Definition: string.h:63
typedef CLIB_PACKED(struct{ethernet_header_t eh;ip4_header_t ip;})
Definition: sticky_hash.c:71
vlib_node_registration_t l2_classify_node
(constructor) VLIB_REGISTER_NODE (l2_classify_node)
Definition: l2_classify.c:49
#define ARRAY_LEN(x)
Definition: clib.h:59
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:50
always_inline uword is_pow2(uword x)
Definition: clib.h:252
u16 cached_next_index
Definition: node.h:422
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ip4_fib_t * fibs
Definition: ip4.h:132
#define vnet_buffer(b)
Definition: buffer.h:300
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
static clib_error_t * show_ip4_sticky_hash_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sticky_hash.c:490
l2_classify_main_t * l2_classify_main
Definition: sticky_hash.c:50
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:225
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:21
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:919
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:91
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
static int ip4_sticky_hash_enable_disable(sticky_hash_main_t *mp, u32 fwd_sw_if_index, u8 *fwd_mask, u32 rev_sw_if_index, u8 *rev_mask, u32 nbuckets, int enable_disable)
Definition: sticky_hash.c:273
static uword sticky_hash_miss_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: sticky_hash.c:117
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:197
unsigned char u8
Definition: types.h:56
always_inline void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
#define vec_foreach(var, vec)
Vector iterator.
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
static clib_error_t * ip4_sticky_hash_init_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sticky_hash.c:359
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
sticky_hash_miss_error_t
Definition: sticky_hash.c:88
Definition: defs.h:45