FD.io VPP  v21.01.1
Vector Packet Processing
flow_report_classify.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  */
17 #include <vnet/api_errno.h>
19 #include <vnet/ip/ip4.h>
20 #include <vnet/udp/udp_local.h>
21 
22 /* Common prefix of tcp and udp headers
23  * containing only source and destination port fields */
24 typedef struct
25 {
28 
30 
31 u8 *
33  flow_report_t * fr,
34  ip4_address_t * collector_address,
36  u16 collector_port,
38  u32 n_elts, u32 * stream_index)
39 {
43  u32 flow_table_index = fr->opaque.as_uword;
44  u8 *ip_start;
47  tcpudp_header_t *tcpudp;
48  udp_header_t *udp;
53  ipfix_field_specifier_t *first_field;
54  u8 *rewrite = 0;
56  u32 field_count = 0;
57  u32 field_index = 0;
58  flow_report_stream_t *stream;
59  u8 ip_version;
60  u8 transport_protocol;
61  u8 *virt_mask;
62  u8 *real_mask;
63 
64  stream = &frm->streams[fr->stream_index];
65 
66  ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
67 
68  ip_version = table->ip_version;
69  transport_protocol = table->transport_protocol;
70 
71  tblp = pool_elt_at_index (vcm->tables, table->classify_table_index);
72 
73  virt_mask = (u8 *) (tblp->mask - tblp->skip_n_vectors);
74  real_mask = (u8 *) (tblp->mask);
75 
76  /* Determine field count */
77  ip_start = virt_mask + sizeof (ethernet_header_t);
78 #define _(field,mask,item,length) \
79  if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0)) \
80  { \
81  field_count++; \
82  \
83  fr->fields_to_send = clib_bitmap_set (fr->fields_to_send, \
84  field_index, 1); \
85  } \
86  field_index++;
88 #undef _
89 
90  /* Add packetTotalCount manually */
91  field_count += 1;
92 
93  /* $$$ enterprise fields, at some later date */
94 
95  /* allocate rewrite space */
96  vec_validate_aligned (rewrite,
98  + field_count * sizeof (ipfix_field_specifier_t) - 1,
100 
101  tp = (ip4_ipfix_template_packet_t *) rewrite;
102  ip = (ip4_header_t *) & tp->ip4;
103  udp = (udp_header_t *) (ip + 1);
104  h = (ipfix_message_header_t *) (udp + 1);
105  s = (ipfix_set_header_t *) (h + 1);
106  t = (ipfix_template_header_t *) (s + 1);
107  first_field = f = (ipfix_field_specifier_t *) (t + 1);
108 
109  ip->ip_version_and_header_length = 0x45;
110  ip->ttl = 254;
111  ip->protocol = IP_PROTOCOL_UDP;
112  ip->src_address.as_u32 = src_address->as_u32;
113  ip->dst_address.as_u32 = collector_address->as_u32;
114  udp->src_port = clib_host_to_net_u16 (stream->src_port);
115  udp->dst_port = clib_host_to_net_u16 (collector_port);
116  udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
117 
118  /* FIXUP: message header export_time */
119  /* FIXUP: message header sequence_number */
120  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
121 
122  /* Take another trip through the mask and build the template */
123  ip_start = virt_mask + sizeof (ethernet_header_t);
124 #define _(field,mask,item,length) \
125  if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0)) \
126  { \
127  f->e_id_length = ipfix_e_id_length (0 /* enterprise */, \
128  item, length); \
129  f++; \
130  }
132 #undef _
133 
134  /* Add packetTotalCount manually */
135  f->e_id_length =
136  ipfix_e_id_length (0 /* enterprise */ , packetTotalCount, 8);
137  f++;
138 
139  /* Back to the template packet... */
140  ip = (ip4_header_t *) & tp->ip4;
141  udp = (udp_header_t *) (ip + 1);
142 
143  ASSERT (f - first_field);
144  /* Field count in this template */
145  t->id_count = ipfix_id_count (fr->template_id, f - first_field);
146 
147  /* set length in octets */
148  s->set_id_length =
149  ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
150 
151  /* message length in octets */
152  h->version_length = version_length ((u8 *) f - (u8 *) h);
153 
154  ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
155  ip->checksum = ip4_header_checksum (ip);
156 
157  return rewrite;
158 }
159 
160 vlib_frame_t *
162  flow_report_t * fr,
163  vlib_frame_t * f, u32 * to_next, u32 node_index)
164 {
167  u32 flow_table_index = fr->opaque.as_uword;
170  vnet_classify_entry_t *v, *save_v;
171  vlib_buffer_t *b0 = 0;
172  u32 next_offset = 0;
173  u32 record_offset = 0;
174  u32 bi0 = ~0;
175  int i, j, k;
178  ipfix_set_header_t *s = 0;
179  u8 *ip_start;
180  ip4_header_t *ip;
181  ip6_header_t *ip6;
182  tcpudp_header_t *tcpudp;
183  udp_header_t *udp;
184  int field_index;
185  u32 records_this_buffer;
186  u16 new_l0, old_l0;
187  ip_csum_t sum0;
188  vlib_main_t *vm = frm->vlib_main;
189  flow_report_stream_t *stream;
190  u8 ip_version;
191  u8 transport_protocol;
192  u8 *virt_key;
193 
194  stream = &frm->streams[fr->stream_index];
195 
196  ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
197 
198  ip_version = table->ip_version;
199  transport_protocol = table->transport_protocol;
200 
201  t = pool_elt_at_index (vcm->tables, table->classify_table_index);
202 
204 
205  for (i = 0; i < t->nbuckets; i++)
206  {
207  b = &t->buckets[i];
208  if (b->offset == 0)
209  continue;
210 
211  save_v = vnet_classify_get_entry (t, b->offset);
212  for (j = 0; j < (1 << b->log2_pages); j++)
213  {
214  for (k = 0; k < t->entries_per_page; k++)
215  {
217  (t, save_v, j * t->entries_per_page + k);
218 
220  continue;
221 
222  /* OK, we have something to send... */
223  if (PREDICT_FALSE (b0 == 0))
224  {
225  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
226  goto flush;
227  b0 = vlib_get_buffer (vm, bi0);
228 
229  u32 copy_len = sizeof (ip4_header_t) +
230  sizeof (udp_header_t) + sizeof (ipfix_message_header_t);
231  clib_memcpy_fast (b0->data, fr->rewrite, copy_len);
232  b0->current_data = 0;
233  b0->current_length = copy_len;
234  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
235  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
236  vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
237 
238  tp = vlib_buffer_get_current (b0);
239  ip = (ip4_header_t *) & tp->ip4;
240  udp = (udp_header_t *) (ip + 1);
241  h = (ipfix_message_header_t *) (udp + 1);
242  s = (ipfix_set_header_t *) (h + 1);
243 
244  /* FIXUP: message header export_time */
245  h->export_time = (u32)
246  (((f64) frm->unix_time_0) +
247  (vlib_time_now (frm->vlib_main) - frm->vlib_time_0));
248  h->export_time = clib_host_to_net_u32 (h->export_time);
249 
250  /* FIXUP: message header sequence_number */
251  h->sequence_number = stream->sequence_number;
252  h->sequence_number =
253  clib_host_to_net_u32 (h->sequence_number);
254 
255  next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
256  record_offset = next_offset;
257  records_this_buffer = 0;
258  }
259 
260  field_index = 0;
261  virt_key = (u8 *) (v->key - t->skip_n_vectors);
262  ip_start = virt_key + sizeof (ethernet_header_t);
263 #define _(field,mask,item,length) \
264  if (clib_bitmap_get (fr->fields_to_send, field_index)) \
265  { \
266  clib_memcpy_fast (b0->data + next_offset, &field, \
267  length); \
268  next_offset += length; \
269  } \
270  field_index++;
272 #undef _
273 
274  /* Add packetTotalCount manually */
275  {
276  u64 packets = clib_host_to_net_u64 (v->hits);
277  clib_memcpy_fast (b0->data + next_offset, &packets,
278  sizeof (packets));
279  next_offset += sizeof (packets);
280  }
281  records_this_buffer++;
282  stream->sequence_number++;
283 
284  /* Next record will have the same size as this record */
285  u32 next_record_size = next_offset - record_offset;
286  record_offset = next_offset;
287 
288  if (next_offset + next_record_size > frm->path_mtu)
289  {
291  next_offset -
292  (sizeof (*ip) +
293  sizeof (*udp) +
294  sizeof (*h)));
295  h->version_length =
296  version_length (next_offset -
297  (sizeof (*ip) + sizeof (*udp)));
298  b0->current_length = next_offset;
299  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
300 
301  tp = vlib_buffer_get_current (b0);
302  ip = (ip4_header_t *) & tp->ip4;
303  udp = (udp_header_t *) (ip + 1);
304 
305  sum0 = ip->checksum;
306  old_l0 = ip->length;
307  new_l0 = clib_host_to_net_u16 ((u16) next_offset);
308 
309  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
310  length /* changed member */ );
311 
312  ip->checksum = ip_csum_fold (sum0);
313  ip->length = new_l0;
314  udp->length =
315  clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
316 
317  if (frm->udp_checksum)
318  {
319  /* RFC 7011 section 10.3.2. */
320  udp->checksum =
321  ip4_tcp_udp_compute_checksum (vm, b0, ip);
322  if (udp->checksum == 0)
323  udp->checksum = 0xffff;
324  }
325 
327 
328  to_next[0] = bi0;
329  f->n_vectors++;
330  to_next++;
331 
332  if (f->n_vectors == VLIB_FRAME_SIZE)
333  {
334  vlib_put_frame_to_node (vm, node_index, f);
335  f = vlib_get_frame_to_node (vm, node_index);
336  f->n_vectors = 0;
337  to_next = vlib_frame_vector_args (f);
338  }
339  b0 = 0;
340  bi0 = ~0;
341  }
342  }
343  }
344  }
345 
346 flush:
347  if (b0)
348  {
350  next_offset -
351  (sizeof (*ip) + sizeof (*udp) +
352  sizeof (*h)));
353  h->version_length = version_length (next_offset -
354  (sizeof (*ip) + sizeof (*udp)));
355  b0->current_length = next_offset;
356  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
357 
358  tp = vlib_buffer_get_current (b0);
359  ip = (ip4_header_t *) & tp->ip4;
360  udp = (udp_header_t *) (ip + 1);
361 
362  sum0 = ip->checksum;
363  old_l0 = ip->length;
364  new_l0 = clib_host_to_net_u16 ((u16) next_offset);
365 
366  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
367  length /* changed member */ );
368 
369  ip->checksum = ip_csum_fold (sum0);
370  ip->length = new_l0;
371  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
372 
373  if (frm->udp_checksum)
374  {
375  /* RFC 7011 section 10.3.2. */
376  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
377  if (udp->checksum == 0)
378  udp->checksum = 0xffff;
379  }
380 
382 
383  to_next[0] = bi0;
384  f->n_vectors++;
385 
386  b0 = 0;
387  bi0 = ~0;
388  }
389 
391  return f;
392 }
393 
394 static clib_error_t *
396  unformat_input_t * input,
397  vlib_cli_command_t * cmd)
398 {
402  ipfix_classify_table_t *table;
403  int rv;
404  int is_add = -1;
406  u8 ip_version = 0;
407  u8 transport_protocol = 255;
408  clib_error_t *error = 0;
409 
410  if (fcm->src_port == 0)
411  clib_error_return (0, "call 'set ipfix classify stream' first");
412 
413  clib_memset (&args, 0, sizeof (args));
414 
416  {
417  if (unformat (input, "add"))
418  is_add = 1;
419  else if (unformat (input, "del"))
420  is_add = 0;
421  else if (unformat (input, "%d", &classify_table_index))
422  ;
423  else if (unformat (input, "ip4"))
424  ip_version = 4;
425  else if (unformat (input, "ip6"))
426  ip_version = 6;
427  else if (unformat (input, "tcp"))
428  transport_protocol = 6;
429  else if (unformat (input, "udp"))
430  transport_protocol = 17;
431  else
432  return clib_error_return (0, "unknown input `%U'",
433  format_unformat_error, input);
434  }
435 
436  if (is_add == -1)
437  return clib_error_return (0, "expecting: add|del");
438  if (classify_table_index == ~0)
439  return clib_error_return (0, "classifier table not specified");
440  if (ip_version == 0)
441  return clib_error_return (0, "IP version not specified");
442 
443  table = 0;
444  int i;
445  for (i = 0; i < vec_len (fcm->tables); i++)
447  if (fcm->tables[i].classify_table_index == classify_table_index)
448  {
449  table = &fcm->tables[i];
450  break;
451  }
452 
453  if (is_add)
454  {
455  if (table)
456  return clib_error_return (0,
457  "Specified classifier table already used");
458  table = ipfix_classify_add_table ();
460  }
461  else
462  {
463  if (!table)
464  return clib_error_return (0,
465  "Specified classifier table not registered");
466  }
467 
468  table->ip_version = ip_version;
469  table->transport_protocol = transport_protocol;
470 
471  args.opaque.as_uword = table - fcm->tables;
474  args.is_add = is_add;
475  args.domain_id = fcm->domain_id;
476  args.src_port = fcm->src_port;
477 
478  rv = vnet_flow_report_add_del (frm, &args, NULL);
479 
481 
482  /* If deleting, or add failed */
483  if (is_add == 0 || (rv && is_add))
484  ipfix_classify_delete_table (table - fcm->tables);
485 
486  return error;
487 }
488 
489 /* *INDENT-OFF* */
490 VLIB_CLI_COMMAND (ipfix_classify_table_add_del_command, static) = {
491  .path = "ipfix classify table",
492  .short_help = "ipfix classify table add|del <table-index>",
494 };
495 /* *INDENT-ON* */
496 
497 static clib_error_t *
499  unformat_input_t * input,
500  vlib_cli_command_t * cmd)
501 {
504  u32 domain_id = 1;
505  u32 src_port = UDP_DST_PORT_ipfix;
506 
508  {
509  if (unformat (input, "domain %d", &domain_id))
510  ;
511  else if (unformat (input, "src-port %d", &src_port))
512  ;
513  else
514  return clib_error_return (0, "unknown input `%U'",
515  format_unformat_error, input);
516  }
517 
518  if (fcm->src_port != 0 &&
519  (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
520  {
521  int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
522  domain_id, (u16) src_port);
523  ASSERT (rv == 0);
524  }
525 
526  fcm->domain_id = domain_id;
527  fcm->src_port = (u16) src_port;
528 
529  return 0;
530 }
531 
532 /* *INDENT-OFF* */
533 VLIB_CLI_COMMAND (set_ipfix_classify_stream_command, static) = {
534  .path = "set ipfix classify stream",
535  .short_help = "set ipfix classify stream"
536  "[domain <domain-id>] [src-port <src-port>]",
538 };
539 /* *INDENT-ON* */
540 
541 static clib_error_t *
543 {
545 
546  if ((error = vlib_call_init_function (vm, flow_report_init)))
547  return error;
548 
549  return 0;
550 }
551 
553 
554 /*
555  * fd.io coding-style-patch-verification: ON
556  *
557  * Local Variables:
558  * eval: (c-set-style "gnu")
559  * End:
560  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
clib_error_t * flow_report_add_del_error_to_clib_error(int error)
Definition: flow_report.c:415
units packets
Definition: map.api:366
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
ip4_address_t src_address
Definition: ip4_packet.h:125
static_always_inline void ipfix_classify_delete_table(u32 index)
uword as_uword
Definition: flow_report.h:74
static_always_inline u8 ipfix_classify_table_index_valid(u32 index)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
static u32 ipfix_e_id_length(int e, u16 id, u16 length)
Definition: ipfix_packet.h:77
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
u32 stream_index
Definition: flow_report.h:91
int vnet_flow_report_add_del(flow_report_main_t *frm, vnet_flow_report_add_del_args_t *a, u16 *template_id)
Definition: flow_report.c:335
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
opaque_t opaque
Definition: flow_report.h:99
uword ip_csum_t
Definition: ip_packet.h:246
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:520
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
flow_report_stream_t * streams
Definition: flow_report.h:114
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
Definition: ip4_packet.h:384
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
clib_spinlock_t writer_lock
vl_api_ip6_address_t ip6
Definition: one.api:424
ip4_address_t dst_address
Definition: ip4_packet.h:125
vnet_flow_rewrite_callback_t * rewrite_callback
Definition: flow_report.h:149
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
const cJSON *const b
Definition: cJSON.h:255
unsigned int u32
Definition: types.h:88
#define vlib_call_init_function(vm, x)
Definition: init.h:270
#define VLIB_FRAME_SIZE
Definition: node.h:378
static int vnet_classify_entry_is_free(vnet_classify_entry_t *e)
Definition: cJSON.c:84
flow_report_main_t flow_report_main
Definition: flow_report.c:22
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
flow_report_classify_main_t flow_report_classify_main
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
u8 * rewrite
Definition: flow_report.h:89
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define PREDICT_FALSE(x)
Definition: clib.h:121
vl_api_address_union_t src_address
Definition: ip_types.api:122
static u32 version_length(u16 length)
Definition: ipfix_packet.h:33
static vnet_classify_entry_t * vnet_classify_entry_at_index(vnet_classify_table_t *t, vnet_classify_entry_t *e, u32 index)
u32 classify_table_index
Definition: fib_types.api:68
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
ipfix_classify_table_t * tables
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:397
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static u32 ipfix_id_count(u16 id, u16 count)
Definition: ipfix_packet.h:184
u8 data[]
Packet data.
Definition: buffer.h:181
static clib_error_t * ipfix_classify_table_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static_always_inline ipfix_classify_table_t * ipfix_classify_add_table(void)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:56
#define ASSERT(truth)
static clib_error_t * set_ipfix_classify_stream_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_main_t * vlib_main
Definition: flow_report.h:136
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1328
u16 template_id
Definition: flow_report.h:90
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:32
char const int length
Definition: cJSON.h:163
#define foreach_ipfix_field
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:121
Definition: defs.h:47
vl_api_address_t ip
Definition: l2.api:501
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vnet_classify_bucket_t * buckets
int vnet_stream_change(flow_report_main_t *frm, u32 old_domain_id, u16 old_src_port, u32 new_domain_id, u16 new_src_port)
Definition: flow_report.c:468
VLIB buffer representation.
Definition: buffer.h:102
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:296
vnet_flow_data_callback_t * flow_data_callback
Definition: flow_report.h:148
#define vnet_buffer(b)
Definition: buffer.h:417
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static clib_error_t * flow_report_classify_init(vlib_main_t *vm)
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
vlib_frame_t * ipfix_classify_send_flows(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
static clib_error_t * flow_report_init(vlib_main_t *vm)
Definition: flow_report.c:599
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:302
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
static vnet_classify_entry_t * vnet_classify_get_entry(vnet_classify_table_t *t, uword offset)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
u8 * ipfix_classify_template_rewrite(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)