FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * node.c - skeleton vpp engine plug-in dual-loop node skeleton
3  *
4  * Copyright (c) <current-year> <your-organization>
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 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vppinfra/error.h>
21 #include <flowperpkt/flowperpkt.h>
22 
23 /**
24  * @file flow record generator graph node
25  */
26 
27 typedef struct
28 {
29  /** interface handle */
31  /** ToS bits */
33  /** packet timestamp */
35  /** size of the buffer */
38 
39 /* packet trace format function */
40 static u8 *
41 format_flowperpkt_trace (u8 * s, va_list * args)
42 {
43  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
44  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
45  flowperpkt_trace_t *t = va_arg (*args, flowperpkt_trace_t *);
46 
47  s = format (s,
48  "FLOWPERPKT: sw_if_index %d, tos %0x2, timestamp %lld, size %d",
49  t->sw_if_index, t->tos, t->timestamp, t->buffer_size);
50  return s;
51 }
52 
54 
55 #define foreach_flowperpkt_error \
56 _(SWAPPED, "Mac swap packets processed")
57 
58 typedef enum
59 {
60 #define _(sym,str) FLOWPERPKT_ERROR_##sym,
62 #undef _
65 
66 static char *flowperpkt_error_strings[] = {
67 #define _(sym,string) string,
69 #undef _
70 };
71 
72 typedef enum
73 {
77 
78 /**
79  * @brief add an entry to the flow record under construction
80  * @param vm vlib_main_t * current worker thread main structure pointer
81  * @param fm flowperpkt_main_t * flow-per-packet main structure pointer
82  * @param sw_if_index u32 interface handle
83  * @param tos u8 ToS bits from the packet
84  * @param timestamp u64 timestamp, nanoseconds since 1/1/70
85  * @param length u16 ip length of the packet
86  * @param do_flush int 1 = flush all cached records, 0 = construct a record
87  */
88 
89 static inline void
91  flowperpkt_main_t * fm,
92  u32 sw_if_index,
93  u8 tos, u64 timestamp, u16 length, int do_flush)
94 {
95  u32 my_cpu_number = vm->cpu_index;
97  ip4_header_t *ip;
98  udp_header_t *udp;
102  vlib_frame_t *f;
103  vlib_buffer_t *b0;
104  u16 offset;
105  u32 bi0;
107 
108  /* Find or allocate a buffer */
109  b0 = fm->buffers_per_worker[my_cpu_number];
110 
111  /* Need to allocate a buffer? */
112  if (PREDICT_FALSE (b0 == 0))
113  {
114  /* Nothing to flush */
115  if (do_flush)
116  return;
117 
118  /* $$$$ drop counter? */
119  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
120  return;
121 
122  /* Initialize the buffer */
123  b0 = fm->buffers_per_worker[my_cpu_number] = vlib_get_buffer (vm, bi0);
124  fl =
128  offset = 0;
129  }
130  else
131  {
132  /* use the current buffer */
133  bi0 = vlib_get_buffer_index (vm, b0);
134  offset = fm->next_record_offset_per_worker[my_cpu_number];
135  }
136 
137  /* Find or allocate a frame */
138  f = fm->frames_per_worker[my_cpu_number];
139  if (PREDICT_FALSE (f == 0))
140  {
141  u32 *to_next;
142  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
143  fm->frames_per_worker[my_cpu_number] = f;
144 
145  /* Enqueue the buffer */
146  to_next = vlib_frame_vector_args (f);
147  to_next[0] = bi0;
148  f->n_vectors = 1;
149  }
150 
151  /* Fresh packet, construct header */
152  if (PREDICT_FALSE (offset == 0))
153  {
154  flow_report_stream_t *stream;
155 
156  stream = &frm->streams[0];
157 
158  b0->current_data = 0;
159  b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
160  sizeof (*s);
162  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
163  vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
164 
165  tp = vlib_buffer_get_current (b0);
166  ip = (ip4_header_t *) & tp->ip4;
167  udp = (udp_header_t *) (ip + 1);
168  h = (ipfix_message_header_t *) (udp + 1);
169  s = (ipfix_set_header_t *) (h + 1);
170 
171  ip->ip_version_and_header_length = 0x45;
172  ip->ttl = 254;
173  ip->protocol = IP_PROTOCOL_UDP;
176  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
177  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
178 
179  /* FIXUP: message header export_time */
180  h->export_time = (u32)
181  (((f64) frm->unix_time_0) +
182  (vlib_time_now (frm->vlib_main) - frm->vlib_time_0));
183  h->export_time = clib_host_to_net_u32 (h->export_time);
184  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
185 
186  /* FIXUP: message header sequence_number */
187  h->sequence_number = stream->sequence_number++;
188  h->sequence_number = clib_host_to_net_u32 (h->sequence_number);
189 
190  offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
191  }
192 
193  /* Add data, unless we're flushing stale data */
194  if (PREDICT_TRUE (do_flush == 0))
195  {
196 
197  /* Add data */
198  /* Egress interface */
199  {
200  u32 egress_interface = clib_host_to_net_u32 (sw_if_index);
201  clib_memcpy (b0->data + offset, &egress_interface,
202  sizeof (egress_interface));
203  offset += sizeof (egress_interface);
204  }
205  /* ToS */
206  b0->data[offset++] = tos;
207 
208  /* Timestamp */
209  clib_memcpy (b0->data + offset, &timestamp, sizeof (f64));
210  offset += sizeof (f64);
211 
212  /* pkt size */
213  {
214  u16 pkt_size = clib_host_to_net_u16 (length);
215  clib_memcpy (b0->data + offset, &pkt_size, sizeof (pkt_size));
216  offset += sizeof (pkt_size);
217  }
218 
219  b0->current_length +=
220  /* sw_if_index + tos + timestamp + length = 15 */
221  sizeof (u32) + sizeof (u8) + sizeof (f64) + sizeof (u16);
222 
223  }
224  /* Time to flush the buffer? */
225  if (PREDICT_FALSE
226  (do_flush || (offset + sizeof (u32) + sizeof (u8)
227  + sizeof (f64)) > frm->path_mtu))
228  {
229  tp = vlib_buffer_get_current (b0);
230  ip = (ip4_header_t *) & tp->ip4;
231  udp = (udp_header_t *) (ip + 1);
232  h = (ipfix_message_header_t *) (udp + 1);
233  s = (ipfix_set_header_t *) (h + 1);
234 
236  b0->current_length -
237  (sizeof (*ip) + sizeof (*udp) +
238  sizeof (*h)));
240  (sizeof (*ip) + sizeof (*udp)));
241 
242  ip->length = clib_host_to_net_u16 (b0->current_length);
243 
244  ip->checksum = ip4_header_checksum (ip);
245  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
246 
247  if (frm->udp_checksum)
248  {
249  /* RFC 7011 section 10.3.2. */
250  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
251  if (udp->checksum == 0)
252  udp->checksum = 0xffff;
253  }
254 
255  ASSERT (ip->checksum == ip4_header_checksum (ip));
256 
258  fm->frames_per_worker[my_cpu_number]);
259  fm->frames_per_worker[my_cpu_number] = 0;
260  fm->buffers_per_worker[my_cpu_number] = 0;
261  offset = 0;
262  }
263 
264  fm->next_record_offset_per_worker[my_cpu_number] = offset;
265 }
266 
267 void
269 {
270  vlib_main_t *vm = vlib_get_main ();
272 
273  add_to_flow_record (vm, fm, 0 /* sw_if_index */ ,
274  0 /* ToS */ ,
275  0ULL /* timestamp */ ,
276  0 /* length */ ,
277  1 /* do_flush */ );
278 }
279 
280 
281 static uword
283  vlib_node_runtime_t * node, vlib_frame_t * frame)
284 {
285  u32 n_left_from, *from, *to_next;
286  flowperpkt_next_t next_index;
287  ip4_main_t *im = &ip4_main;
288  ip_lookup_main_t *lm = &im->lookup_main;
291  u64 now;
292 
293  now = (u64) ((vlib_time_now (vm) - fm->vlib_time_0) * 1e9);
294  now += fm->nanosecond_time_0;
295 
296  from = vlib_frame_vector_args (frame);
297  n_left_from = frame->n_vectors;
298  next_index = node->cached_next_index;
299 
300  while (n_left_from > 0)
301  {
302  u32 n_left_to_next;
303 
304  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
305 
306  while (n_left_from >= 4 && n_left_to_next >= 2)
307  {
308  u32 next0 = FLOWPERPKT_NEXT_DROP;
309  u32 next1 = FLOWPERPKT_NEXT_DROP;
310  ip4_header_t *ip0, *ip1;
311  u16 len0, len1;
312  u32 bi0, bi1;
313  vlib_buffer_t *b0, *b1;
314 
315  /* Prefetch next iteration. */
316  {
317  vlib_buffer_t *p2, *p3;
318 
319  p2 = vlib_get_buffer (vm, from[2]);
320  p3 = vlib_get_buffer (vm, from[3]);
321 
322  vlib_prefetch_buffer_header (p2, LOAD);
323  vlib_prefetch_buffer_header (p3, LOAD);
324 
327  }
328 
329  /* speculatively enqueue b0 and b1 to the current next frame */
330  to_next[0] = bi0 = from[0];
331  to_next[1] = bi1 = from[1];
332  from += 2;
333  to_next += 2;
334  n_left_from -= 2;
335  n_left_to_next -= 2;
336 
337  b0 = vlib_get_buffer (vm, bi0);
338  b1 = vlib_get_buffer (vm, bi1);
339 
340 
343  &next0, 0 /* sizeof config data */ );
344 
347  &next1, 0 /* sizeof config data */ );
348 
349  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
350  vnet_buffer (b0)->ip.save_rewrite_length);
351 
352  len0 = vlib_buffer_length_in_chain (vm, b0);
353 
354  if (PREDICT_TRUE ((b0->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
355  add_to_flow_record (vm, fm,
356  vnet_buffer (b0)->sw_if_index[VLIB_TX],
357  ip0->tos, now, len0, 0 /* flush */ );
358 
359  ip1 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b1) +
360  vnet_buffer (b1)->ip.save_rewrite_length);
361  len1 = vlib_buffer_length_in_chain (vm, b1);
362 
363  if (PREDICT_TRUE ((b1->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
364  add_to_flow_record (vm, fm,
365  vnet_buffer (b1)->sw_if_index[VLIB_TX],
366  ip1->tos, now, len1, 0 /* flush */ );
367 
368  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
369  {
370  if (b0->flags & VLIB_BUFFER_IS_TRACED)
371  {
372  flowperpkt_trace_t *t =
373  vlib_add_trace (vm, node, b0, sizeof (*t));
374  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
375  t->tos = ip0->tos;
376  t->timestamp = now;
377  t->buffer_size = len0;
378 
379  }
380  if (b1->flags & VLIB_BUFFER_IS_TRACED)
381  {
382  flowperpkt_trace_t *t =
383  vlib_add_trace (vm, node, b1, sizeof (*t));
384 
385  t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
386  t->tos = ip1->tos;
387  t->timestamp = now;
388  t->buffer_size = len1;
389  }
390  }
391 
392  /* verify speculative enqueues, maybe switch current next frame */
393  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
394  to_next, n_left_to_next,
395  bi0, bi1, next0, next1);
396  }
397 
398  while (n_left_from > 0 && n_left_to_next > 0)
399  {
400  u32 bi0;
401  vlib_buffer_t *b0;
402  u32 next0 = FLOWPERPKT_NEXT_DROP;
403  ip4_header_t *ip0;
404  u16 len0;
405 
406  /* speculatively enqueue b0 to the current next frame */
407  bi0 = from[0];
408  to_next[0] = bi0;
409  from += 1;
410  to_next += 1;
411  n_left_from -= 1;
412  n_left_to_next -= 1;
413 
414  b0 = vlib_get_buffer (vm, bi0);
415 
418  &next0, 0 /* sizeof config data */ );
419 
420  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
421  vnet_buffer (b0)->ip.save_rewrite_length);
422  /*
423  * egressInterface, TLV type 14, u32
424  * ipClassOfService, TLV type 5, u8
425  * flowStartNanoseconds, TLV type 156, dateTimeNanoseconds (f64)
426  * Implementation: f64 nanoseconds since VPP started
427  * dataLinkFrameSize, TLV type 312, u16
428  */
429  len0 = vlib_buffer_length_in_chain (vm, b0);
430 
431  if (PREDICT_TRUE ((b0->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
432  add_to_flow_record (vm, fm,
433  vnet_buffer (b0)->sw_if_index[VLIB_TX],
434  ip0->tos, now, len0, 0 /* do flush */ );
435 
437  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
438  {
439  flowperpkt_trace_t *t =
440  vlib_add_trace (vm, node, b0, sizeof (*t));
441  t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
442  t->tos = ip0->tos;
443  t->timestamp = now;
444  t->buffer_size = len0;
445  }
446 
447  /* verify speculative enqueue, maybe switch current next frame */
448  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
449  to_next, n_left_to_next,
450  bi0, next0);
451  }
452 
453  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
454  }
455  return frame->n_vectors;
456 }
457 
458 /**
459  * @brief IPFIX flow-per-packet graph node
460  * @node flowperpkt
461  *
462  * This is the IPFIX flow-record-per-packet node.
463  *
464  * @param vm vlib_main_t corresponding to the current thread.
465  * @param node vlib_node_runtime_t data for this node.
466  * @param frame vlib_frame_t whose contents should be dispatched.
467  *
468  * @par Graph mechanics: buffer metadata, next index usage
469  *
470  * <em>Uses:</em>
471  * - <code>vnet_buffer(b)->ip.save_rewrite_length</code>
472  * - tells the node the length of the rewrite which was applied in
473  * ip4/6_rewrite_inline, allows the code to find the IP header without
474  * having to parse L2 headers, or make stupid assumptions about their
475  * length.
476  * - <code>vnet_buffer(b)->flags & VLIB_BUFFER_FLOW_REPORT</code>
477  * - Used to suppress flow record generation for flow record packets.
478  *
479  * <em>Sets:</em>
480  * - <code>vnet_buffer(b)->flags & VLIB_BUFFER_FLOW_REPORT</code>
481  * - To suppress flow record generation for flow record packets
482  *
483  * <em>Next Index:</em>
484  * - Next configured output feature on the interface, usually
485  * "interface-output." Generated flow records head for ip4-lookup
486  */
487 
488 /* *INDENT-OFF* */
490  .function = flowperpkt_node_fn,
491  .name = "flowperpkt",
492  .vector_size = sizeof (u32),
493  .format_trace = format_flowperpkt_trace,
495 
496  .n_errors = ARRAY_LEN(flowperpkt_error_strings),
497  .error_strings = flowperpkt_error_strings,
498 
499  .n_next_nodes = FLOWPERPKT_N_NEXT,
500 
501  /* edit / add dispositions here */
502  .next_nodes = {
503  [FLOWPERPKT_NEXT_DROP] = "error-drop",
504  },
505 };
506 /* *INDENT-ON* */
507 
508 /*
509  * fd.io coding-style-patch-verification: ON
510  *
511  * Local Variables:
512  * eval: (c-set-style "gnu")
513  * End:
514  */
vnet_config_main_t config_main
Definition: feature.h:55
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
#define CLIB_UNUSED(x)
Definition: clib.h:79
u8 tos
ToS bits.
Definition: node.c:32
static void add_to_flow_record(vlib_main_t *vm, flowperpkt_main_t *fm, u32 sw_if_index, u8 tos, u64 timestamp, u16 length, int do_flush)
add an entry to the flow record under construction
Definition: node.c:90
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:124
ip4_address_t src_address
Definition: ip4_packet.h:138
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:402
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 nanosecond_time_0
Time reference pair.
Definition: flowperpkt.h:52
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
flowperpkt_error_t
Definition: node.c:58
struct _vlib_node_registration vlib_node_registration_t
ip4_address_t src_address
Definition: flow_report.h:96
ip_lookup_main_t lookup_main
Definition: ip4.h:96
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:112
u16 buffer_size
size of the buffer
Definition: node.c:36
ip4_address_t ipfix_collector
Definition: flow_report.h:94
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:485
static u8 * format_flowperpkt_trace(u8 *s, va_list *args)
Definition: node.c:41
flow_report_stream_t * streams
Definition: flow_report.h:91
flow-per-packet plugin header file
static void vlib_buffer_init_for_free_list(vlib_buffer_t *_dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:606
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
static char * flowperpkt_error_strings[]
Definition: node.c:66
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:190
ip4_address_t dst_address
Definition: ip4_packet.h:138
u32 cpu_index
Definition: main.h:159
unsigned long u64
Definition: types.h:89
vlib_buffer_t ** buffers_per_worker
ipfix buffers under construction, per-worker thread
Definition: flowperpkt.h:45
static uword flowperpkt_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:282
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:82
flow_report_main_t flow_report_main
Definition: flow_report.c:21
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
u64 timestamp
packet timestamp
Definition: node.c:34
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:122
vlib_node_registration_t flowperpkt_node
IPFIX flow-per-packet graph node.
Definition: node.c:53
#define PREDICT_FALSE(x)
Definition: clib.h:97
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define foreach_flowperpkt_error
Definition: node.c:55
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
static u32 version_length(u16 length)
Definition: ipfix_packet.h:31
vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]
rx unicast, multicast, tx interface/feature configuration.
Definition: lookup.h:360
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
#define clib_memcpy(a, b, c)
Definition: string.h:64
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:99
#define ARRAY_LEN(x)
Definition: clib.h:59
#define VLIB_BUFFER_FLOW_REPORT
Definition: buffer.h:102
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:306
u16 cached_next_index
Definition: node.h:463
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
vlib_main_t * vlib_main
Definition: flow_report.h:113
#define vnet_buffer(b)
Definition: buffer.h:333
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1336
flowperpkt_main_t flowperpkt_main
Definition: flowperpkt.c:53
IPv4 main type.
Definition: ip4.h:95
u16 * next_record_offset_per_worker
next record offset, per worker thread
Definition: flowperpkt.h:49
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
static 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
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:114
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
struct clib_bihash_value offset
template key/value backing page structure
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:166
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
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
u8 data[0]
Packet data.
Definition: buffer.h:154
u32 sw_if_index
interface handle
Definition: node.c:30
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:337
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:194
flowperpkt_next_t
Definition: node.c:72
Definition: defs.h:46
vlib_frame_t ** frames_per_worker
frames containing ipfix buffers, per-worker thread
Definition: flowperpkt.h:47
void flowperpkt_flush_callback(void)
Definition: node.c:268