FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
l2_node.c
Go to the documentation of this file.
1 /*
2  * l2_node.c - l2 ipfix-per-packet graph node
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 l2 flow record generator graph node
25  */
26 
27 typedef struct
28 {
29  /** interface handle */
32  /** src and dst L2 addresses */
33  u8 src_mac[6];
34  u8 dst_mac[6];
35  /** Ethertype */
37  /** packet timestamp */
39  /** size of the buffer */
42 
43 /* packet trace format function */
44 static u8 *
45 format_flowperpkt_l2_trace (u8 * s, va_list * args)
46 {
47  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
48  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
49  flowperpkt_l2_trace_t *t = va_arg (*args, flowperpkt_l2_trace_t *);
50 
51  s = format (s,
52  "FLOWPERPKT-L2: rx_sw_if_index %d, tx_sw_if_index %d, src %U dst %U ethertype %0x2, timestamp %lld, size %d",
56  t->ethertype, t->timestamp, t->buffer_size);
57  return s;
58 }
59 
61 
62 /* No counters at the moment */
63 #define foreach_flowperpkt_l2_error
64 
65 typedef enum
66 {
67 #define _(sym,str) FLOWPERPKT_ERROR_##sym,
69 #undef _
72 
73 static char *flowperpkt_l2_error_strings[] = {
74 #define _(sym,string) string,
76 #undef _
77 };
78 
79 typedef enum
80 {
85 
86 /**
87  * @brief add an entry to the flow record under construction
88  * @param vm vlib_main_t * current worker thread main structure pointer
89  * @param fm flowperpkt_main_t * flow-per-packet main structure pointer
90  * @param sw_if_index u32 interface handle
91  * @param tos u8 ToS bits from the packet
92  * @param timestamp u64 timestamp, nanoseconds since 1/1/70
93  * @param length u16 ip length of the packet
94  * @param do_flush int 1 = flush all cached records, 0 = construct a record
95  */
96 
97 static inline void
99  vlib_node_runtime_t * node,
100  flowperpkt_main_t * fm,
101  u32 rx_sw_if_index, u32 tx_sw_if_index,
102  u8 * src_mac, u8 * dst_mac,
103  u16 ethertype, u64 timestamp, u16 length, int do_flush)
104 {
105  u32 my_cpu_number = vm->cpu_index;
107  ip4_header_t *ip;
108  udp_header_t *udp;
112  vlib_frame_t *f;
113  vlib_buffer_t *b0;
114  u16 offset;
115  u32 bi0;
117 
118  /* Find or allocate a buffer */
119  b0 = fm->l2_buffers_per_worker[my_cpu_number];
120 
121  /* Need to allocate a buffer? */
122  if (PREDICT_FALSE (b0 == 0))
123  {
124  /* Nothing to flush */
125  if (do_flush)
126  return;
127 
128  /* $$$$ drop counter? */
129  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
130  return;
131 
132  /* Initialize the buffer */
133  b0 = fm->l2_buffers_per_worker[my_cpu_number] =
134  vlib_get_buffer (vm, bi0);
135  fl =
139  offset = 0;
140  }
141  else
142  {
143  /* use the current buffer */
144  bi0 = vlib_get_buffer_index (vm, b0);
145  offset = fm->l2_next_record_offset_per_worker[my_cpu_number];
146  }
147 
148  /* Find or allocate a frame */
149  f = fm->l2_frames_per_worker[my_cpu_number];
150  if (PREDICT_FALSE (f == 0))
151  {
152  u32 *to_next;
153  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
154  fm->l2_frames_per_worker[my_cpu_number] = f;
155 
156  /* Enqueue the buffer */
157  to_next = vlib_frame_vector_args (f);
158  to_next[0] = bi0;
159  f->n_vectors = 1;
160  }
161 
162  /* Fresh packet, construct header */
163  if (PREDICT_FALSE (offset == 0))
164  {
165  flow_report_stream_t *stream;
166 
167  stream = &frm->streams[0];
168 
169  b0->current_data = 0;
170  b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
171  sizeof (*s);
173  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
174  vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
175 
176  tp = vlib_buffer_get_current (b0);
177  ip = (ip4_header_t *) & tp->ip4;
178  udp = (udp_header_t *) (ip + 1);
179  h = (ipfix_message_header_t *) (udp + 1);
180  s = (ipfix_set_header_t *) (h + 1);
181 
182  ip->ip_version_and_header_length = 0x45;
183  ip->ttl = 254;
184  ip->protocol = IP_PROTOCOL_UDP;
188  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
189  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
190  udp->checksum = 0;
191 
192  /* FIXUP: message header export_time */
193  h->export_time = (u32)
194  (((f64) frm->unix_time_0) +
195  (vlib_time_now (frm->vlib_main) - frm->vlib_time_0));
196  h->export_time = clib_host_to_net_u32 (h->export_time);
197  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
198 
199  /* FIXUP: message header sequence_number */
200  h->sequence_number = stream->sequence_number++;
201  h->sequence_number = clib_host_to_net_u32 (h->sequence_number);
202 
203  offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
204  }
205 
206  /* Add data, unless we're flushing stale data */
207  if (PREDICT_TRUE (do_flush == 0))
208  {
209 
210  /* Add data */
211  /* Ingress interface */
212  {
213  u32 ingress_interface = clib_host_to_net_u32 (rx_sw_if_index);
214  clib_memcpy (b0->data + offset, &ingress_interface,
215  sizeof (ingress_interface));
216  offset += sizeof (ingress_interface);
217  }
218  /* Egress interface */
219  {
220  u32 egress_interface = clib_host_to_net_u32 (tx_sw_if_index);
221  clib_memcpy (b0->data + offset, &egress_interface,
222  sizeof (egress_interface));
223  offset += sizeof (egress_interface);
224  }
225  /* src mac address */
226  {
227  clib_memcpy (b0->data + offset, src_mac, 6);
228  offset += 6;
229  }
230  /* dst mac address */
231  {
232  clib_memcpy (b0->data + offset, dst_mac, 6);
233  offset += 6;
234  }
235 
236  /* ethertype */
237  b0->data[offset++] = ethertype >> 8;
238  b0->data[offset++] = ethertype & 0xFF;
239 
240  /* Timestamp */
241  clib_memcpy (b0->data + offset, &timestamp, sizeof (f64));
242  offset += sizeof (f64);
243 
244  /* pkt size */
245  {
246  u16 pkt_size = clib_host_to_net_u16 (length);
247  clib_memcpy (b0->data + offset, &pkt_size, sizeof (pkt_size));
248  offset += sizeof (pkt_size);
249  }
250 
251  b0->current_length +=
252  /* 2*sw_if_index + 2*mac + ethertype + timestamp + length = 32 */
253  2 * sizeof (u32) + 12 + sizeof (u16) + sizeof (f64) + sizeof (u16);
254 
255  }
256  /* Time to flush the buffer? */
257  if (PREDICT_FALSE
258  (do_flush || (offset + 2 * sizeof (u32) + 12 + sizeof (u16) +
259  +sizeof (f64) + sizeof (u16)) > frm->path_mtu))
260  {
261  tp = vlib_buffer_get_current (b0);
262  ip = (ip4_header_t *) & tp->ip4;
263  udp = (udp_header_t *) (ip + 1);
264  h = (ipfix_message_header_t *) (udp + 1);
265  s = (ipfix_set_header_t *) (h + 1);
266 
268  b0->current_length -
269  (sizeof (*ip) + sizeof (*udp) +
270  sizeof (*h)));
272  (sizeof (*ip) + sizeof (*udp)));
273 
274  ip->length = clib_host_to_net_u16 (b0->current_length);
275 
276  ip->checksum = ip4_header_checksum (ip);
277  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
278 
279  if (frm->udp_checksum)
280  {
281  /* RFC 7011 section 10.3.2. */
282  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
283  if (udp->checksum == 0)
284  udp->checksum = 0xffff;
285  }
286 
287  ASSERT (ip->checksum == ip4_header_checksum (ip));
288 
289  if (PREDICT_FALSE (vlib_get_trace_count (vm, node) > 0))
290  {
292  0 /* follow chain */ );
294  vlib_add_trace (vm, node, b0, sizeof (*t));
295  memset (t, 0, sizeof (*t));
296  t->rx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
297  t->tx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
298  t->buffer_size = b0->current_length;
299  }
300 
302  fm->l2_frames_per_worker[my_cpu_number]);
303  fm->l2_frames_per_worker[my_cpu_number] = 0;
304  fm->l2_buffers_per_worker[my_cpu_number] = 0;
305  offset = 0;
306  }
307 
308  fm->l2_next_record_offset_per_worker[my_cpu_number] = offset;
309 }
310 
311 void
313 {
316  vlib_node_runtime_t *node;
317  node = vlib_node_get_runtime (vm, flowperpkt_l2_node.index);
318 
319  add_to_flow_record_l2 (vm, node, fm, 0 /* rx_sw_if_index */ ,
320  0 /* tx_sw_if_index */ ,
321  0 /* src mac */ ,
322  0 /* dst mac */ ,
323  0 /* ethertype */ ,
324  0ULL /* timestamp */ ,
325  0 /* length */ ,
326  1 /* do_flush */ );
327 }
328 
329 
330 static uword
332  vlib_node_runtime_t * node, vlib_frame_t * frame)
333 {
334  u32 n_left_from, *from, *to_next;
335  flowperpkt_l2_next_t next_index;
337  u64 now;
338 
339  now = (u64) ((vlib_time_now (vm) - fm->vlib_time_0) * 1e9);
340  now += fm->nanosecond_time_0;
341 
342  from = vlib_frame_vector_args (frame);
343  n_left_from = frame->n_vectors;
344  next_index = node->cached_next_index;
345 
346  while (n_left_from > 0)
347  {
348  u32 n_left_to_next;
349 
350  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
351 
352  while (n_left_from >= 4 && n_left_to_next >= 2)
353  {
356  ethernet_header_t *eh0, *eh1;
357  u16 len0, len1;
358  u32 bi0, bi1;
359  vlib_buffer_t *b0, *b1;
360 
361  /* Prefetch next iteration. */
362  {
363  vlib_buffer_t *p2, *p3;
364 
365  p2 = vlib_get_buffer (vm, from[2]);
366  p3 = vlib_get_buffer (vm, from[3]);
367 
368  vlib_prefetch_buffer_header (p2, LOAD);
369  vlib_prefetch_buffer_header (p3, LOAD);
370 
373  }
374 
375  /* speculatively enqueue b0 and b1 to the current next frame */
376  to_next[0] = bi0 = from[0];
377  to_next[1] = bi1 = from[1];
378  from += 2;
379  to_next += 2;
380  n_left_from -= 2;
381  n_left_to_next -= 2;
382 
383  b0 = vlib_get_buffer (vm, bi0);
384  b1 = vlib_get_buffer (vm, bi1);
385 
386  vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
387  &next0, b0);
388  vnet_feature_next (vnet_buffer (b1)->sw_if_index[VLIB_TX],
389  &next1, b1);
390 
391  eh0 = vlib_buffer_get_current (b0);
392  len0 = vlib_buffer_length_in_chain (vm, b0);
393 
394  if (PREDICT_TRUE ((b0->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
395  add_to_flow_record_l2 (vm, node, fm,
396  vnet_buffer (b0)->sw_if_index[VLIB_RX],
397  vnet_buffer (b0)->sw_if_index[VLIB_TX],
398  eh0->src_address,
399  eh0->dst_address,
400  eh0->type, now, len0, 0 /* flush */ );
401 
402  eh1 = vlib_buffer_get_current (b0);
403  len1 = vlib_buffer_length_in_chain (vm, b0);
404 
405  if (PREDICT_TRUE ((b1->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
406  add_to_flow_record_l2 (vm, node, fm,
407  vnet_buffer (b1)->sw_if_index[VLIB_RX],
408  vnet_buffer (b1)->sw_if_index[VLIB_TX],
409  eh1->src_address,
410  eh1->dst_address,
411  eh1->type, now, len1, 0 /* flush */ );
412 
413  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
414  {
415  if (b0->flags & VLIB_BUFFER_IS_TRACED)
416  {
418  vlib_add_trace (vm, node, b0, sizeof (*t));
419  t->rx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
420  t->tx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
421  clib_memcpy (t->src_mac, eh0->src_address, 6);
422  clib_memcpy (t->dst_mac, eh0->dst_address, 6);
423  t->ethertype = clib_net_to_host_u16 (eh0->type);
424  t->timestamp = now;
425  t->buffer_size = len0;
426  }
427  if (b1->flags & VLIB_BUFFER_IS_TRACED)
428  {
430  vlib_add_trace (vm, node, b1, sizeof (*t));
431  t->rx_sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
432  t->tx_sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
433  clib_memcpy (t->src_mac, eh1->src_address, 6);
434  clib_memcpy (t->dst_mac, eh1->dst_address, 6);
435  t->ethertype = clib_net_to_host_u16 (eh1->type);
436  t->timestamp = now;
437  t->buffer_size = len1;
438  }
439  }
440 
441  /* verify speculative enqueues, maybe switch current next frame */
442  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
443  to_next, n_left_to_next,
444  bi0, bi1, next0, next1);
445  }
446 
447  while (n_left_from > 0 && n_left_to_next > 0)
448  {
449  u32 bi0;
450  vlib_buffer_t *b0;
452  ethernet_header_t *eh0;
453  u16 len0;
454 
455  /* speculatively enqueue b0 to the current next frame */
456  bi0 = from[0];
457  to_next[0] = bi0;
458  from += 1;
459  to_next += 1;
460  n_left_from -= 1;
461  n_left_to_next -= 1;
462 
463  b0 = vlib_get_buffer (vm, bi0);
464 
465  vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
466  &next0, b0);
467 
468  eh0 = vlib_buffer_get_current (b0);
469  len0 = vlib_buffer_length_in_chain (vm, b0);
470 
471  if (PREDICT_TRUE ((b0->flags & VLIB_BUFFER_FLOW_REPORT) == 0))
472  add_to_flow_record_l2 (vm, node, fm,
473  vnet_buffer (b0)->sw_if_index[VLIB_RX],
474  vnet_buffer (b0)->sw_if_index[VLIB_TX],
475  eh0->src_address,
476  eh0->dst_address,
477  eh0->type, now, len0, 0 /* flush */ );
478 
480  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
481  {
483  vlib_add_trace (vm, node, b0, sizeof (*t));
484  t->rx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
485  t->tx_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
486  clib_memcpy (t->src_mac, eh0->src_address, 6);
487  clib_memcpy (t->dst_mac, eh0->dst_address, 6);
488  t->ethertype = clib_net_to_host_u16 (eh0->type);
489  t->timestamp = now;
490  t->buffer_size = len0;
491  }
492 
493  /* verify speculative enqueue, maybe switch current next frame */
494  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
495  to_next, n_left_to_next,
496  bi0, next0);
497  }
498 
499  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
500  }
501  return frame->n_vectors;
502 }
503 
504 /**
505  * @brief IPFIX l2 flow-per-packet graph node
506  * @node flowperpkt-l2
507  *
508  * This is the IPFIX flow-record-per-packet node.
509  *
510  * @param vm vlib_main_t corresponding to the current thread.
511  * @param node vlib_node_runtime_t data for this node.
512  * @param frame vlib_frame_t whose contents should be dispatched.
513  *
514  * @par Graph mechanics: buffer metadata, next index usage
515  *
516  * <em>Uses:</em>
517  * - <code>vnet_buffer(b)->ip.save_rewrite_length</code>
518  * - tells the node the length of the rewrite which was applied in
519  * ip4/6_rewrite_inline, allows the code to find the IP header without
520  * having to parse L2 headers, or make stupid assumptions about their
521  * length.
522  * - <code>vnet_buffer(b)->flags & VLIB_BUFFER_FLOW_REPORT</code>
523  * - Used to suppress flow record generation for flow record packets.
524  *
525  * <em>Sets:</em>
526  * - <code>vnet_buffer(b)->flags & VLIB_BUFFER_FLOW_REPORT</code>
527  * - To suppress flow record generation for flow record packets
528  *
529  * <em>Next Index:</em>
530  * - Next configured output feature on the interface, usually
531  * "interface-output." Generated flow records head for ip4-lookup
532  */
533 
534 /* *INDENT-OFF* */
536  .function = flowperpkt_l2_node_fn,
537  .name = "flowperpkt-l2",
538  .vector_size = sizeof (u32),
539  .format_trace = format_flowperpkt_l2_trace,
540  .type = VLIB_NODE_TYPE_INTERNAL,
541 
543  .error_strings = flowperpkt_l2_error_strings,
544 
545  .n_next_nodes = FLOWPERPKT_L2_N_NEXT,
546 
547  /* edit / add dispositions here */
548  .next_nodes = {
549  [FLOWPERPKT_L2_NEXT_DROP] = "error-drop",
550  [FLOWPERPKT_L2_NEXT_IP4_LOOKUP] = "ip4-lookup",
551  },
552 };
553 /* *INDENT-ON* */
554 
555 /*
556  * fd.io coding-style-patch-verification: ON
557  *
558  * Local Variables:
559  * eval: (c-set-style "gnu")
560  * End:
561  */
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
vlib_frame_t ** l2_frames_per_worker
Definition: flowperpkt.h:52
#define CLIB_UNUSED(x)
Definition: clib.h:79
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:143
ip4_address_t src_address
Definition: ip4_packet.h:163
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 nanosecond_time_0
Time reference pair.
Definition: flowperpkt.h:59
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:185
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:459
u8 src_address[6]
Definition: packet.h:54
struct _vlib_node_registration vlib_node_registration_t
ip4_address_t src_address
Definition: flow_report.h:96
u16 buffer_size
size of the buffer
Definition: l2_node.c:40
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u16 flags_and_fragment_offset
Definition: ip4_packet.h:144
u16 ethertype
Ethertype.
Definition: l2_node.c:36
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:100
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:512
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:104
flow_report_stream_t * streams
Definition: flow_report.h:91
flow-per-packet plugin header file
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
ip4_address_t dst_address
Definition: ip4_packet.h:163
u8 dst_address[6]
Definition: packet.h:53
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:89
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:164
static void add_to_flow_record_l2(vlib_main_t *vm, vlib_node_runtime_t *node, flowperpkt_main_t *fm, u32 rx_sw_if_index, u32 tx_sw_if_index, u8 *src_mac, u8 *dst_mac, u16 ethertype, u64 timestamp, u16 length, int do_flush)
add an entry to the flow record under construction
Definition: l2_node.c:98
static char * flowperpkt_l2_error_strings[]
Definition: l2_node.c:73
u32 cpu_index
Definition: main.h:159
unsigned long u64
Definition: types.h:89
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:70
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:71
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
u64 timestamp
packet timestamp
Definition: l2_node.c:38
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:390
#define VLIB_BUFFER_FLOW_REPORT
Definition: buffer.h:92
u32 rx_sw_if_index
interface handle
Definition: l2_node.c:30
#define PREDICT_FALSE(x)
Definition: clib.h:97
flowperpkt_l2_next_t
Definition: l2_node.c:79
#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
static_always_inline void vnet_feature_next(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:221
#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 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
void flowperpkt_flush_callback_l2(void)
Definition: l2_node.c:312
static u32 version_length(u16 length)
Definition: ipfix_packet.h:31
static u8 * format_flowperpkt_l2_trace(u8 *s, va_list *args)
Definition: l2_node.c:45
vlib_buffer_t ** l2_buffers_per_worker
Definition: flowperpkt.h:48
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:88
#define clib_memcpy(a, b, c)
Definition: string.h:69
#define ARRAY_LEN(x)
Definition: clib.h:59
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:455
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
vlib_main_t * vlib_main
Definition: flow_report.h:113
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1394
flowperpkt_main_t flowperpkt_main
Definition: flowperpkt.c:54
u16 * l2_next_record_offset_per_worker
Definition: flowperpkt.h:56
u8 src_mac[6]
src and dst L2 addresses
Definition: l2_node.c:33
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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
static uword flowperpkt_l2_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l2_node.c:331
#define foreach_flowperpkt_l2_error
Definition: l2_node.c:63
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
double f64
Definition: types.h:142
flowperpkt_l2_error_t
Definition: l2_node.c:65
unsigned char u8
Definition: types.h:56
vlib_node_registration_t flowperpkt_l2_node
IPFIX l2 flow-per-packet graph node.
Definition: l2_node.c:60
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:484
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
static void vlib_buffer_init_for_free_list(vlib_buffer_t *dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:777
#define vnet_buffer(b)
Definition: buffer.h:294
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:152
u16 flags
Copy of main node flags.
Definition: node.h:449
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
u8 ip_version_and_header_length
Definition: ip4_packet.h:131
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:385
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:245
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:238
Definition: defs.h:46