FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
flowprobe.c
Go to the documentation of this file.
1 /*
2  * flowprobe.c - ipfix probe plugin
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
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 
18 /**
19  * @file
20  * @brief Per-packet IPFIX flow record generator plugin
21  *
22  * This file implements vpp plugin registration mechanics,
23  * debug CLI, and binary API handling.
24  */
25 
26 #include <vnet/vnet.h>
27 #include <vpp/app/version.h>
28 #include <vnet/plugin/plugin.h>
29 #include <vnet/udp/udp_local.h>
30 #include <flowprobe/flowprobe.h>
31 
32 #include <vlibapi/api.h>
33 #include <vlibmemory/api.h>
34 
35 /* define message IDs */
36 #include <flowprobe/flowprobe.api_enum.h>
37 #include <flowprobe/flowprobe.api_types.h>
38 
42  vlib_frame_t * f);
43 
44 #define REPLY_MSG_ID_BASE fm->msg_id_base
46 
47 /* Define the per-interface configurable features */
48 /* *INDENT-OFF* */
49 VNET_FEATURE_INIT (flow_perpacket_ip4, static) =
50 {
51  .arc_name = "ip4-output",
52  .node_name = "flowprobe-ip4",
53  .runs_before = VNET_FEATURES ("interface-output"),
54 };
55 
56 VNET_FEATURE_INIT (flow_perpacket_ip6, static) =
57 {
58  .arc_name = "ip6-output",
59  .node_name = "flowprobe-ip6",
60  .runs_before = VNET_FEATURES ("interface-output"),
61 };
62 
63 VNET_FEATURE_INIT (flow_perpacket_l2, static) = {
64  .arc_name = "interface-output",
65  .node_name = "flowprobe-l2",
66  .runs_before = VNET_FEATURES ("interface-output-arc-end"),
67 };
68 /* *INDENT-ON* */
69 
70 /* Macro to finish up custom dump fns */
71 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
72 #define FINISH \
73  vec_add1 (s, 0); \
74  vl_print (handle, (char *)s); \
75  vec_free (s); \
76  return handle;
77 
78 static inline ipfix_field_specifier_t *
80 {
81 #define flowprobe_template_ip4_field_count() 4
82  /* sourceIpv4Address, TLV type 8, u32 */
83  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
84  sourceIPv4Address, 4);
85  f++;
86  /* destinationIPv4Address, TLV type 12, u32 */
87  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
88  destinationIPv4Address, 4);
89  f++;
90  /* protocolIdentifier, TLV type 4, u8 */
91  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
92  protocolIdentifier, 1);
93  f++;
94  /* octetDeltaCount, TLV type 1, u64 */
95  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
96  octetDeltaCount, 8);
97  f++;
98  return f;
99 }
100 
101 static inline ipfix_field_specifier_t *
103 {
104 #define flowprobe_template_ip6_field_count() 4
105  /* sourceIpv6Address, TLV type 27, 16 octets */
106  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
107  sourceIPv6Address, 16);
108  f++;
109  /* destinationIPv6Address, TLV type 28, 16 octets */
110  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
111  destinationIPv6Address, 16);
112  f++;
113  /* protocolIdentifier, TLV type 4, u8 */
114  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
115  protocolIdentifier, 1);
116  f++;
117  /* octetDeltaCount, TLV type 1, u64 */
118  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
119  octetDeltaCount, 8);
120  f++;
121  return f;
122 }
123 
124 static inline ipfix_field_specifier_t *
126 {
127 #define flowprobe_template_l2_field_count() 3
128  /* sourceMacAddress, TLV type 56, u8[6] we hope */
129  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
130  sourceMacAddress, 6);
131  f++;
132  /* destinationMacAddress, TLV type 80, u8[6] we hope */
133  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
134  destinationMacAddress, 6);
135  f++;
136  /* ethernetType, TLV type 256, u16 */
137  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
138  ethernetType, 2);
139  f++;
140  return f;
141 }
142 
143 static inline ipfix_field_specifier_t *
145 {
146 #define flowprobe_template_common_field_count() 5
147  /* ingressInterface, TLV type 10, u32 */
148  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
149  ingressInterface, 4);
150  f++;
151 
152  /* egressInterface, TLV type 14, u32 */
153  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
154  egressInterface, 4);
155  f++;
156 
157  /* packetDeltaCount, TLV type 2, u64 */
158  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
159  packetDeltaCount, 8);
160  f++;
161 
162  /* flowStartNanoseconds, TLV type 156, u64 */
163  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
164  flowStartNanoseconds, 8);
165  f++;
166 
167  /* flowEndNanoseconds, TLV type 157, u64 */
168  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
169  flowEndNanoseconds, 8);
170  f++;
171 
172  return f;
173 }
174 
175 static inline ipfix_field_specifier_t *
177 {
178 #define flowprobe_template_l4_field_count() 3
179  /* sourceTransportPort, TLV type 7, u16 */
180  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
181  sourceTransportPort, 2);
182  f++;
183  /* destinationTransportPort, TLV type 11, u16 */
184  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
185  destinationTransportPort, 2);
186  f++;
187  /* tcpControlBits, TLV type 6, u16 */
188  f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
189  tcpControlBits, 2);
190  f++;
191 
192  return f;
193 }
194 
195 /**
196  * @brief Create an IPFIX template packet rewrite string
197  * @param frm flow_report_main_t *
198  * @param fr flow_report_t *
199  * @param collector_address ip4_address_t * the IPFIX collector address
200  * @param src_address ip4_address_t * the source address we should use
201  * @param collector_port u16 the collector port we should use, host byte order
202  * @returns u8 * vector containing the indicated IPFIX template packet
203  */
204 static inline u8 *
206  flow_report_t * fr,
207  ip4_address_t * collector_address,
209  u16 collector_port,
211 {
212  ip4_header_t *ip;
213  udp_header_t *udp;
218  ipfix_field_specifier_t *first_field;
219  u8 *rewrite = 0;
221  u32 field_count = 0;
222  flow_report_stream_t *stream;
225  bool collect_ip4 = false, collect_ip6 = false;
226 
227  stream = &frm->streams[fr->stream_index];
228 
229  if (flags & FLOW_RECORD_L3)
230  {
231  collect_ip4 = which == FLOW_VARIANT_L2_IP4 || which == FLOW_VARIANT_IP4;
232  collect_ip6 = which == FLOW_VARIANT_L2_IP6 || which == FLOW_VARIANT_IP6;
233  if (which == FLOW_VARIANT_L2_IP4)
235  if (which == FLOW_VARIANT_L2_IP6)
237  }
238 
239  field_count += flowprobe_template_common_field_count ();
240  if (flags & FLOW_RECORD_L2)
241  field_count += flowprobe_template_l2_field_count ();
242  if (collect_ip4)
243  field_count += flowprobe_template_ip4_field_count ();
244  if (collect_ip6)
245  field_count += flowprobe_template_ip6_field_count ();
246  if (flags & FLOW_RECORD_L4)
247  field_count += flowprobe_template_l4_field_count ();
248 
249  /* allocate rewrite space */
252  + field_count * sizeof (ipfix_field_specifier_t) - 1,
254 
256  ip = (ip4_header_t *) & tp->ip4;
257  udp = (udp_header_t *) (ip + 1);
258  h = (ipfix_message_header_t *) (udp + 1);
259  s = (ipfix_set_header_t *) (h + 1);
260  t = (ipfix_template_header_t *) (s + 1);
261  first_field = f = (ipfix_field_specifier_t *) (t + 1);
262 
263  ip->ip_version_and_header_length = 0x45;
264  ip->ttl = 254;
265  ip->protocol = IP_PROTOCOL_UDP;
266  ip->src_address.as_u32 = src_address->as_u32;
267  ip->dst_address.as_u32 = collector_address->as_u32;
268  udp->src_port = clib_host_to_net_u16 (stream->src_port);
269  udp->dst_port = clib_host_to_net_u16 (collector_port);
270  udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
271 
272  /* FIXUP: message header export_time */
273  /* FIXUP: message header sequence_number */
274  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
275 
276  /* Add TLVs to the template */
278 
279  if (flags & FLOW_RECORD_L2)
281  if (collect_ip4)
283  if (collect_ip6)
285  if (flags & FLOW_RECORD_L4)
287 
288  /* Back to the template packet... */
289  ip = (ip4_header_t *) & tp->ip4;
290  udp = (udp_header_t *) (ip + 1);
291 
292  ASSERT (f - first_field);
293  /* Field count in this template */
294  t->id_count = ipfix_id_count (fr->template_id, f - first_field);
295 
296  fm->template_size[flags] = (u8 *) f - (u8 *) s;
297 
298  /* set length in octets */
299  s->set_id_length =
300  ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
301 
302  /* message length in octets */
303  h->version_length = version_length ((u8 *) f - (u8 *) h);
304 
305  ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
306  ip->checksum = ip4_header_checksum (ip);
307 
308  return rewrite;
309 }
310 
311 static u8 *
313  flow_report_t * fr,
314  ip4_address_t * collector_address,
316  u16 collector_port,
317  ipfix_report_element_t * elts,
318  u32 n_elts, u32 * stream_index)
319 {
321  (frm, fr, collector_address, src_address, collector_port,
323 }
324 
325 static u8 *
327  flow_report_t * fr,
328  ip4_address_t * collector_address,
330  u16 collector_port,
331  ipfix_report_element_t * elts,
332  u32 n_elts, u32 * stream_index)
333 {
335  (frm, fr, collector_address, src_address, collector_port,
337 }
338 
339 static u8 *
341  flow_report_t * fr,
342  ip4_address_t * collector_address,
344  u16 collector_port,
345  ipfix_report_element_t * elts,
346  u32 n_elts, u32 * stream_index)
347 {
349  (frm, fr, collector_address, src_address, collector_port,
351 }
352 
353 static u8 *
355  flow_report_t * fr,
356  ip4_address_t * collector_address,
358  u16 collector_port,
359  ipfix_report_element_t * elts,
360  u32 n_elts, u32 * stream_index)
361 {
363  (frm, fr, collector_address, src_address, collector_port,
365 }
366 
367 static u8 *
369  flow_report_t * fr,
370  ip4_address_t * collector_address,
372  u16 collector_port,
373  ipfix_report_element_t * elts,
374  u32 n_elts, u32 * stream_index)
375 {
377  (frm, fr, collector_address, src_address, collector_port,
379 }
380 
381 /**
382  * @brief Flush accumulated data
383  * @param frm flow_report_main_t *
384  * @param fr flow_report_t *
385  * @param f vlib_frame_t *
386  *
387  * <em>Notes:</em>
388  * This function must simply return the incoming frame, or no template packets
389  * will be sent.
390  */
391 vlib_frame_t *
393  flow_report_t * fr,
394  vlib_frame_t * f, u32 * to_next, u32 node_index)
395 {
397  return f;
398 }
399 
400 vlib_frame_t *
402  flow_report_t * fr,
403  vlib_frame_t * f, u32 * to_next, u32 node_index)
404 {
406  return f;
407 }
408 
409 vlib_frame_t *
411  flow_report_t * fr,
412  vlib_frame_t * f, u32 * to_next, u32 node_index)
413 {
415  return f;
416 }
417 
418 static int
421  vnet_flow_data_callback_t * flow_data_callback,
422  vnet_flow_rewrite_callback_t * rewrite_callback,
423  bool is_add, u16 * template_id)
424 {
427  .rewrite_callback = rewrite_callback,
428  .flow_data_callback = flow_data_callback,
429  .is_add = is_add,
430  .domain_id = domain_id,
431  .src_port = src_port,
432  .opaque.as_uword = flags,
433  };
434  return vnet_flow_report_add_del (frm, &a, template_id);
435 }
436 
437 static void
439 {
442  u32 my_cpu_number = vm->thread_index;
443  int i;
444  u32 poolindex;
445 
446  for (i = 0; i < vec_len (expired_timers); i++)
447  {
448  poolindex = expired_timers[i] & 0x7FFFFFFF;
449  vec_add1 (fm->expired_passive_per_worker[my_cpu_number], poolindex);
450  }
451 }
452 
453 static clib_error_t *
455 {
459  clib_error_t *error = 0;
460  u32 num_threads;
461  int i;
462 
463  /* Decide how many worker threads we have */
464  num_threads = 1 /* main thread */ + tm->n_threads;
465 
466  /* Hash table per worker */
467  fm->ht_log2len = FLOWPROBE_LOG2_HASHSIZE;
468 
469  /* Init per worker flow state and timer wheels */
470  if (active_timer)
471  {
472  vec_validate (fm->timers_per_worker, num_threads - 1);
473  vec_validate (fm->expired_passive_per_worker, num_threads - 1);
474  vec_validate (fm->hash_per_worker, num_threads - 1);
475  vec_validate (fm->pool_per_worker, num_threads - 1);
476 
477  for (i = 0; i < num_threads; i++)
478  {
479  int j;
480  pool_alloc (fm->pool_per_worker[i], 1 << fm->ht_log2len);
481  vec_resize (fm->hash_per_worker[i], 1 << fm->ht_log2len);
482  for (j = 0; j < (1 << fm->ht_log2len); j++)
483  fm->hash_per_worker[i][j] = ~0;
484  fm->timers_per_worker[i] =
485  clib_mem_alloc (sizeof (TWT (tw_timer_wheel)));
486  tw_timer_wheel_init_2t_1w_2048sl (fm->timers_per_worker[i],
488  1.0, 1024);
489  }
490  fm->disabled = true;
491  }
492  else
493  {
494  f64 now = vlib_time_now (vm);
495  vec_validate (fm->stateless_entry, num_threads - 1);
496  for (i = 0; i < num_threads; i++)
497  fm->stateless_entry[i].last_exported = now;
498  fm->disabled = false;
499  }
500  fm->initialized = true;
501  return error;
502 }
503 
504 static int
506  u8 which)
507 {
508  vec_validate_init_empty (fm->flow_per_interface, sw_if_index, ~0);
509 
510  if (fm->flow_per_interface[sw_if_index] == (u8) ~ 0)
511  return -1;
512  else if (fm->flow_per_interface[sw_if_index] != which)
513  return 0;
514  else
515  return 1;
516 }
517 
518 /**
519  * @brief configure / deconfigure the IPFIX flow-per-packet
520  * @param fm flowprobe_main_t * fm
521  * @param sw_if_index u32 the desired interface
522  * @param is_add int 1 to enable the feature, 0 to disable it
523  * @returns 0 if successful, non-zero otherwise
524  */
525 
526 static int
528  u32 sw_if_index, u8 which, int is_add)
529 {
531  int rv = 0;
532  u16 template_id = 0;
533  flowprobe_record_t flags = fm->record;
534 
535  fm->flow_per_interface[sw_if_index] = (is_add) ? which : (u8) ~ 0;
536  fm->template_per_flow[which] += (is_add) ? 1 : -1;
537  if (is_add && fm->template_per_flow[which] > 1)
538  template_id = fm->template_reports[flags];
539 
540  if ((is_add && fm->template_per_flow[which] == 1) ||
541  (!is_add && fm->template_per_flow[which] == 0))
542  {
543  if (which == FLOW_VARIANT_L2)
544  {
545  if (fm->record & FLOW_RECORD_L2)
546  {
547  rv = flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
550  is_add, &template_id);
551  }
552  if (fm->record & FLOW_RECORD_L3 || fm->record & FLOW_RECORD_L4)
553  {
554  rv = flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
557  is_add, &template_id);
558  fm->template_reports[flags | FLOW_RECORD_L2_IP4] =
559  (is_add) ? template_id : 0;
560  rv =
561  flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
564  is_add, &template_id);
565  fm->template_reports[flags | FLOW_RECORD_L2_IP6] =
566  (is_add) ? template_id : 0;
567 
568  /* Special case L2 */
569  fm->context[FLOW_VARIANT_L2_IP4].flags =
571  fm->context[FLOW_VARIANT_L2_IP6].flags =
573 
574  fm->template_reports[flags] = template_id;
575  }
576  }
577  else if (which == FLOW_VARIANT_IP4)
578  rv = flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
581  is_add, &template_id);
582  else if (which == FLOW_VARIANT_IP6)
583  rv = flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
586  is_add, &template_id);
587  }
588  if (rv && rv != VNET_API_ERROR_VALUE_EXIST)
589  {
590  clib_warning ("vnet_flow_report_add_del returned %d", rv);
591  return -1;
592  }
593 
594  if (which != (u8) ~ 0)
595  {
596  fm->context[which].flags = fm->record;
597  fm->template_reports[flags] = (is_add) ? template_id : 0;
598  }
599 
600  if (which == FLOW_VARIANT_IP4)
601  vnet_feature_enable_disable ("ip4-output", "flowprobe-ip4",
602  sw_if_index, is_add, 0, 0);
603  else if (which == FLOW_VARIANT_IP6)
604  vnet_feature_enable_disable ("ip6-output", "flowprobe-ip6",
605  sw_if_index, is_add, 0, 0);
606  else if (which == FLOW_VARIANT_L2)
607  vnet_feature_enable_disable ("interface-output", "flowprobe-l2",
608  sw_if_index, is_add, 0, 0);
609 
610  /* Stateful flow collection */
611  if (is_add && !fm->initialized)
612  {
613  flowprobe_create_state_tables (fm->active_timer);
614  if (fm->active_timer)
616  }
617 
618  return 0;
619 }
620 
621 /**
622  * @brief API message handler
623  * @param mp vl_api_flowprobe_tx_interface_add_del_t * mp the api message
624  */
627 {
629  vl_api_flowprobe_tx_interface_add_del_reply_t *rmp;
630  u32 sw_if_index = ntohl (mp->sw_if_index);
631  int rv = 0;
632 
634 
635  if (fm->record == 0)
636  {
637  clib_warning ("Please specify flowprobe params record first...");
638  rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
639  goto out;
640  }
641 
643  if ((rv == 1 && mp->is_add == 1) || rv == 0)
644  {
645  rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
646  goto out;
647  }
648 
650  (fm, sw_if_index, mp->which, mp->is_add);
651 
652 out:
654 
655  REPLY_MACRO (VL_API_FLOWPROBE_TX_INTERFACE_ADD_DEL_REPLY);
656 }
657 
658 #define vec_neg_search(v,E) \
659 ({ \
660  word _v(i) = 0; \
661  while (_v(i) < vec_len(v) && v[_v(i)] == E) \
662  { \
663  _v(i)++; \
664  } \
665  if (_v(i) == vec_len(v)) \
666  _v(i) = ~0; \
667  _v(i); \
668 })
669 
670 static int
672  u8 record_l3, u8 record_l4,
673  u32 active_timer, u32 passive_timer)
674 {
676 
677  if (vec_neg_search (fm->flow_per_interface, (u8) ~ 0) != ~0)
678  return ~0;
679 
680  if (record_l2)
682  if (record_l3)
684  if (record_l4)
686 
687  fm->record = flags;
688 
689  /*
690  * Timers: ~0 is default, 0 is off
691  */
692  fm->active_timer =
693  (active_timer == (u32) ~ 0 ? FLOWPROBE_TIMER_ACTIVE : active_timer);
694  fm->passive_timer =
695  (passive_timer == (u32) ~ 0 ? FLOWPROBE_TIMER_PASSIVE : passive_timer);
696 
697  return 0;
698 }
699 
700 void
702 {
704  vl_api_flowprobe_params_reply_t *rmp;
705  int rv = 0;
706 
708  (fm,
712  clib_net_to_host_u32 (mp->active_timer),
713  clib_net_to_host_u32 (mp->passive_timer));
714 
715  REPLY_MACRO (VL_API_FLOWPROBE_PARAMS_REPLY);
716 }
717 
718 /* *INDENT-OFF* */
720  .version = VPP_BUILD_VER,
721  .description = "Flow per Packet",
722 };
723 /* *INDENT-ON* */
724 
725 u8 *
726 format_flowprobe_entry (u8 * s, va_list * args)
727 {
728  flowprobe_entry_t *e = va_arg (*args, flowprobe_entry_t *);
729  s = format (s, " %d/%d", e->key.rx_sw_if_index, e->key.tx_sw_if_index);
730 
731  s = format (s, " %U %U", format_ethernet_address, &e->key.src_mac,
733  s = format (s, " %U -> %U",
736  s = format (s, " %d", e->key.protocol);
737  s = format (s, " %d %d\n", clib_net_to_host_u16 (e->key.src_port),
738  clib_net_to_host_u16 (e->key.dst_port));
739 
740  return s;
741 }
742 
743 u8 *
744 format_flowprobe_feature (u8 * s, va_list * args)
745 {
746  u8 *which = va_arg (*args, u8 *);
747  if (*which == FLOW_VARIANT_IP4)
748  s = format (s, "ip4");
749  else if (*which == FLOW_VARIANT_IP6)
750  s = format (s, "ip6");
751  else if (*which == FLOW_VARIANT_L2)
752  s = format (s, "l2");
753 
754  return s;
755 }
756 
757 u8 *
758 format_flowprobe_params (u8 * s, va_list * args)
759 {
760  flowprobe_record_t flags = va_arg (*args, flowprobe_record_t);
761  u32 active_timer = va_arg (*args, u32);
762  u32 passive_timer = va_arg (*args, u32);
763 
764  if (flags & FLOW_RECORD_L2)
765  s = format (s, " l2");
766  if (flags & FLOW_RECORD_L3)
767  s = format (s, " l3");
768  if (flags & FLOW_RECORD_L4)
769  s = format (s, " l4");
770 
771  if (active_timer != (u32) ~ 0)
772  s = format (s, " active: %d", active_timer);
773 
774  if (passive_timer != (u32) ~ 0)
775  s = format (s, " passive: %d", passive_timer);
776 
777  return s;
778 }
779 
780 static clib_error_t *
783 {
785  int i;
787 
788  vlib_cli_output (vm, "Dumping IPFIX table");
789 
790  for (i = 0; i < vec_len (fm->pool_per_worker); i++)
791  {
792  /* *INDENT-OFF* */
793  pool_foreach (e, fm->pool_per_worker[i])
794  {
795  vlib_cli_output (vm, "%U",
797  e);
798  }
799  /* *INDENT-ON* */
800 
801  }
802  return 0;
803 }
804 
805 static clib_error_t *
808 {
810  int i;
811 
812  vlib_cli_output (vm, "IPFIX table statistics");
813  vlib_cli_output (vm, "Flow entry size: %d\n", sizeof (flowprobe_entry_t));
814  vlib_cli_output (vm, "Flow pool size per thread: %d\n",
815  0x1 << FLOWPROBE_LOG2_HASHSIZE);
816 
817  for (i = 0; i < vec_len (fm->pool_per_worker); i++)
818  vlib_cli_output (vm, "Pool utilisation thread %d is %d%%\n", i,
819  (100 * pool_elts (fm->pool_per_worker[i])) /
820  (0x1 << FLOWPROBE_LOG2_HASHSIZE));
821  return 0;
822 }
823 
824 static clib_error_t *
826  unformat_input_t * input,
827  vlib_cli_command_t * cmd)
828 {
830  u32 sw_if_index = ~0;
831  int is_add = 1;
833  int rv;
834 
836  {
837  if (unformat (input, "disable"))
838  is_add = 0;
839  else if (unformat (input, "%U", unformat_vnet_sw_interface,
840  fm->vnet_main, &sw_if_index));
841  else if (unformat (input, "ip4"))
843  else if (unformat (input, "ip6"))
845  else if (unformat (input, "l2"))
847  else
848  break;
849  }
850 
851  if (fm->record == 0)
852  return clib_error_return (0,
853  "Please specify flowprobe params record first...");
854 
855  if (sw_if_index == ~0)
856  return clib_error_return (0, "Please specify an interface...");
857 
859  if (rv == 1)
860  {
861  if (is_add)
862  return clib_error_return (0,
863  "Datapath is already enabled for given interface...");
864  }
865  else if (rv == 0)
866  return clib_error_return (0,
867  "Interface has enable different datapath ...");
868 
869  rv =
871  switch (rv)
872  {
873  case 0:
874  break;
875 
876  case VNET_API_ERROR_INVALID_SW_IF_INDEX:
877  return clib_error_return
878  (0, "Invalid interface, only works on physical ports");
879  break;
880 
881  case VNET_API_ERROR_UNIMPLEMENTED:
882  return clib_error_return (0, "ip6 not supported");
883  break;
884 
885  default:
886  return clib_error_return (0, "flowprobe_enable_disable returned %d",
887  rv);
888  }
889  return 0;
890 }
891 
892 static clib_error_t *
894  unformat_input_t * input,
895  vlib_cli_command_t * cmd)
896 {
898  u8 *which;
900 
901  vec_foreach (which, fm->flow_per_interface)
902  {
903  if (*which == (u8) ~ 0)
904  continue;
905 
906  sw_if_index = which - fm->flow_per_interface;
909  which);
910  }
911  return 0;
912 }
913 
914 static clib_error_t *
916  unformat_input_t * input,
917  vlib_cli_command_t * cmd)
918 {
920  bool record_l2 = false, record_l3 = false, record_l4 = false;
921  u32 active_timer = ~0;
922  u32 passive_timer = ~0;
923 
925  {
926  if (unformat (input, "active %d", &active_timer))
927  ;
928  else if (unformat (input, "passive %d", &passive_timer))
929  ;
930  else if (unformat (input, "record"))
932  {
933  if (unformat (input, "l2"))
934  record_l2 = true;
935  else if (unformat (input, "l3"))
936  record_l3 = true;
937  else if (unformat (input, "l4"))
938  record_l4 = true;
939  else
940  break;
941  }
942  else
943  break;
944  }
945 
946  if (passive_timer > 0 && active_timer > passive_timer)
947  return clib_error_return (0,
948  "Passive timer has to be greater than active one...");
949 
950  if (flowprobe_params (fm, record_l2, record_l3, record_l4,
951  active_timer, passive_timer))
952  return clib_error_return (0,
953  "Couldn't change flowperpacket params when feature is enabled on some interface ...");
954  return 0;
955 }
956 
957 static clib_error_t *
959  unformat_input_t * input,
960  vlib_cli_command_t * cmd)
961 {
963  flowprobe_record_t flags = fm->record;
964  u32 active_timer = fm->active_timer;
965  u32 passive_timer = fm->passive_timer;
966 
967  vlib_cli_output (vm, "%U", format_flowprobe_params, flags, active_timer,
968  passive_timer);
969  return 0;
970 }
971 
972 /*?
973  * '<em>flowprobe feature add-del</em>' commands to enable/disable
974  * per-packet IPFIX flow record generation on an interface
975  *
976  * @cliexpar
977  * @parblock
978  * To enable per-packet IPFIX flow-record generation on an interface:
979  * @cliexcmd{flowprobe feature add-del GigabitEthernet2/0/0}
980  *
981  * To disable per-packet IPFIX flow-record generation on an interface:
982  * @cliexcmd{flowprobe feature add-del GigabitEthernet2/0/0 disable}
983  * @cliexend
984  * @endparblock
985 ?*/
986 /* *INDENT-OFF* */
988  .path = "flowprobe feature add-del",
989  .short_help =
990  "flowprobe feature add-del <interface-name> <l2|ip4|ip6> disable",
992 };
994  .path = "flowprobe params",
995  .short_help =
996  "flowprobe params record <[l2] [l3] [l4]> [active <timer> passive <timer>]",
997  .function = flowprobe_params_command_fn,
998 };
999 
1001  .path = "show flowprobe feature",
1002  .short_help =
1003  "show flowprobe feature",
1005 };
1007  .path = "show flowprobe params",
1008  .short_help =
1009  "show flowprobe params",
1011 };
1013  .path = "show flowprobe table",
1014  .short_help = "show flowprobe table",
1015  .function = flowprobe_show_table_fn,
1016 };
1018  .path = "show flowprobe statistics",
1019  .short_help = "show flowprobe statistics",
1020  .function = flowprobe_show_stats_fn,
1021 };
1022 /* *INDENT-ON* */
1023 
1024 /*
1025  * Main-core process, sending an interrupt to the per worker input
1026  * process that spins the per worker timer wheel.
1027  */
1028 static uword
1030 {
1031  uword *event_data = 0;
1032  vlib_main_t **worker_vms = 0, *worker_vm;
1034 
1035  /* Wait for Godot... */
1037  uword event_type = vlib_process_get_events (vm, &event_data);
1038  if (event_type != 1)
1039  clib_warning ("bogus kickoff event received, %d", event_type);
1040  vec_reset_length (event_data);
1041 
1042  int i;
1043  if (vlib_get_n_threads () == 0)
1044  vec_add1 (worker_vms, vm);
1045  else
1046  {
1047  for (i = 0; i < vlib_get_n_threads (); i++)
1048  {
1049  worker_vm = vlib_get_main_by_index (i);
1050  if (worker_vm)
1051  vec_add1 (worker_vms, worker_vm);
1052  }
1053  }
1054  f64 sleep_duration = 0.1;
1055 
1056  while (1)
1057  {
1058  /* Send an interrupt to each timer input node */
1059  sleep_duration = 0.1;
1060  for (i = 0; i < vec_len (worker_vms); i++)
1061  {
1062  worker_vm = worker_vms[i];
1063  if (worker_vm)
1064  {
1066  flowprobe_walker_node.index);
1067  sleep_duration =
1068  (fm->expired_passive_per_worker[i] > 0) ? 1e-4 : 0.1;
1069  }
1070  }
1071  vlib_process_suspend (vm, sleep_duration);
1072  }
1073  return 0; /* or not */
1074 }
1075 
1076 /* *INDENT-OFF* */
1078  .function = timer_process,
1079  .name = "flowprobe-timer-process",
1080  .type = VLIB_NODE_TYPE_PROCESS,
1081 };
1082 /* *INDENT-ON* */
1083 
1084 #include <flowprobe/flowprobe.api.c>
1085 
1086 /**
1087  * @brief Set up the API message handling tables
1088  * @param vm vlib_main_t * vlib main data structure pointer
1089  * @returns 0 to indicate all is well, or a clib_error_t
1090  */
1091 static clib_error_t *
1093 {
1096  clib_error_t *error = 0;
1097  u32 num_threads;
1098  int i;
1099 
1100  fm->vnet_main = vnet_get_main ();
1101 
1102  /* Ask for a correctly-sized block of API message decode slots */
1103  fm->msg_id_base = setup_message_id_table ();
1104 
1105  /* Set up time reference pair */
1106  fm->vlib_time_0 = vlib_time_now (vm);
1107  fm->nanosecond_time_0 = unix_time_now_nsec ();
1108 
1109  clib_memset (fm->template_reports, 0, sizeof (fm->template_reports));
1110  clib_memset (fm->template_size, 0, sizeof (fm->template_size));
1111  clib_memset (fm->template_per_flow, 0, sizeof (fm->template_per_flow));
1112 
1113  /* Decide how many worker threads we have */
1114  num_threads = 1 /* main thread */ + tm->n_threads;
1115 
1116  /* Allocate per worker thread vectors per flavour */
1117  for (i = 0; i < FLOW_N_VARIANTS; i++)
1118  {
1119  vec_validate (fm->context[i].buffers_per_worker, num_threads - 1);
1120  vec_validate (fm->context[i].frames_per_worker, num_threads - 1);
1121  vec_validate (fm->context[i].next_record_offset_per_worker,
1122  num_threads - 1);
1123  }
1124 
1125  fm->active_timer = FLOWPROBE_TIMER_ACTIVE;
1126  fm->passive_timer = FLOWPROBE_TIMER_PASSIVE;
1127 
1128  return error;
1129 }
1130 
1132 
1133 /*
1134  * fd.io coding-style-patch-verification: ON
1135  *
1136  * Local Variables:
1137  * eval: (c-set-style "gnu")
1138  * End:
1139  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
flowprobe_main
flowprobe_main_t flowprobe_main
Definition: flowprobe.c:39
vl_api_flowprobe_tx_interface_add_del_t::which
vl_api_flowprobe_which_flags_t which
Definition: flowprobe.api:43
flowprobe_key_t::dst_mac
u8 dst_mac[6]
Definition: flowprobe.h:80
vl_api_flowprobe_tx_interface_add_del_t::is_add
bool is_add
Definition: flowprobe.api:42
VALIDATE_SW_IF_INDEX
#define VALIDATE_SW_IF_INDEX(mp)
Definition: api_helper_macros.h:281
udp_header_t::src_port
u16 src_port
Definition: udp_packet.h:48
flowprobe_template_rewrite_ip6
static u8 * flowprobe_template_rewrite_ip6(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)
Definition: flowprobe.c:312
udp_header_t::length
u16 length
Definition: udp_packet.h:51
api.h
flow_report_main
flow_report_main_t flow_report_main
Definition: flow_report.c:22
flowprobe_init
static clib_error_t * flowprobe_init(vlib_main_t *vm)
Set up the API message handling tables.
Definition: flowprobe.c:1092
ipfix_e_id_length
static u32 ipfix_e_id_length(int e, u16 id, u16 length)
Definition: ipfix_packet.h:77
flowprobe_template_ip6_fields
static ipfix_field_specifier_t * flowprobe_template_ip6_fields(ipfix_field_specifier_t *f)
Definition: flowprobe.c:102
flowprobe_show_stats_command
static vlib_cli_command_t flowprobe_show_stats_command
(constructor) VLIB_CLI_COMMAND (flowprobe_show_stats_command)
Definition: flowprobe.c:1017
flowprobe_template_l4_fields
static ipfix_field_specifier_t * flowprobe_template_l4_fields(ipfix_field_specifier_t *f)
Definition: flowprobe.c:176
flowprobe_show_table_fn
static clib_error_t * flowprobe_show_table_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cm)
Definition: flowprobe.c:781
flowprobe_key_t::rx_sw_if_index
u32 rx_sw_if_index
Definition: flowprobe.h:77
f
vlib_frame_t * f
Definition: interface_output.c:1098
flowprobe_template_l2_fields
static ipfix_field_specifier_t * flowprobe_template_l2_fields(ipfix_field_specifier_t *f)
Definition: flowprobe.c:125
FLOWPROBE_RECORD_FLAG_L2
@ FLOWPROBE_RECORD_FLAG_L2
Definition: flowprobe.api:21
flowprobe_template_ip4_fields
static ipfix_field_specifier_t * flowprobe_template_ip4_fields(ipfix_field_specifier_t *f)
Definition: flowprobe.c:79
ipfix_set_header_t
Definition: ipfix_packet.h:115
FLOW_N_VARIANTS
@ FLOW_N_VARIANTS
Definition: flowprobe.h:53
format_ethernet_address
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
flow_report::stream_index
u32 stream_index
Definition: flow_report.h:90
flowprobe_tx_interface_add_del_feature
static int flowprobe_tx_interface_add_del_feature(flowprobe_main_t *fm, u32 sw_if_index, u8 which, int is_add)
configure / deconfigure the IPFIX flow-per-packet
Definition: flowprobe.c:527
flowprobe_params_command
static vlib_cli_command_t flowprobe_params_command
(constructor) VLIB_CLI_COMMAND (flowprobe_params_command)
Definition: flowprobe.c:993
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_cli_command_t::path
char * path
Definition: cli.h:96
flowprobe_key_t::src_address
ip46_address_t src_address
Definition: flowprobe.h:82
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
vl_api_flowprobe_tx_interface_add_del_t_handler
void vl_api_flowprobe_tx_interface_add_del_t_handler(vl_api_flowprobe_tx_interface_add_del_t *mp)
API message handler.
Definition: flowprobe.c:626
opaque_t::as_uword
uword as_uword
Definition: flow_report.h:73
flowprobe_template_rewrite_inline
static u8 * flowprobe_template_rewrite_inline(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, flowprobe_variant_t which)
Create an IPFIX template packet rewrite string.
Definition: flowprobe.c:205
flow_report_stream_t::domain_id
u32 domain_id
Definition: flow_report.h:78
flow_report
Definition: flow_report.h:85
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
api.h
fm
vnet_feature_main_t * fm
Definition: nat44_ei_hairpinning.c:592
node_index
node node_index
Definition: interface_output.c:440
flowprobe_show_params_command_fn
static clib_error_t * flowprobe_show_params_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: flowprobe.c:958
flowprobe_walker_node
vlib_node_registration_t flowprobe_walker_node
(constructor) VLIB_REGISTER_NODE (flowprobe_walker_node)
Definition: node.c:1033
flowprobe_key_t::protocol
u8 protocol
Definition: flowprobe.h:84
flowprobe_main_t
Definition: flowprobe.h:120
vnet_flow_rewrite_callback_t
u8 *() vnet_flow_rewrite_callback_t(struct flow_report_main *, struct flow_report *, ip4_address_t *, ip4_address_t *, u16, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
Definition: flow_report.h:56
unformat_input_t
struct _unformat_input_t unformat_input_t
timer_process
static uword timer_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: flowprobe.c:1029
vlib_frame_t
Definition: node.h:372
vlib_process_signal_event
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1019
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
VNET_FEATURE_INIT
VNET_FEATURE_INIT(flow_perpacket_ip4, static)
h
h
Definition: flowhash_template.h:372
error
Definition: cJSON.c:88
ip4_ipfix_template_packet_t
Definition: flow_report.h:41
flowprobe_template_ip4_field_count
#define flowprobe_template_ip4_field_count()
vnet_feature_main_t::vnet_main
vnet_main_t * vnet_main
Definition: feature.h:116
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
flowprobe_template_rewrite_l2_ip4
static u8 * flowprobe_template_rewrite_l2_ip4(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)
Definition: flowprobe.c:354
vlib_process_get_events
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type,...
Definition: node_funcs.h:583
flowprobe_show_params_command
static vlib_cli_command_t flowprobe_show_params_command
(constructor) VLIB_CLI_COMMAND (flowprobe_show_params_command)
Definition: flowprobe.c:1006
flowprobe_expired_timer_callback
static void flowprobe_expired_timer_callback(u32 *expired_timers)
Definition: flowprobe.c:438
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
which
int which
Definition: cJSON.h:234
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
FLOWPROBE_TIMER_PASSIVE
#define FLOWPROBE_TIMER_PASSIVE
Definition: flowprobe.h:32
flowprobe_template_l4_field_count
#define flowprobe_template_l4_field_count()
format_flowprobe_feature
u8 * format_flowprobe_feature(u8 *s, va_list *args)
Definition: flowprobe.c:744
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
flowprobe_key_t::dst_port
u16 dst_port
Definition: flowprobe.h:86
flowprobe_key_t::tx_sw_if_index
u32 tx_sw_if_index
Definition: flowprobe.h:78
flow_report_stream_t::src_port
u16 src_port
Definition: flow_report.h:80
flowprobe_entry_t
Definition: flowprobe.h:97
vl_api_flowprobe_params_t::record_flags
vl_api_flowprobe_record_flags_t record_flags
Definition: flowprobe.api:54
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
flowprobe_key_t::dst_address
ip46_address_t dst_address
Definition: flowprobe.h:83
REPLY_MACRO
#define REPLY_MACRO(t)
Definition: api_helper_macros.h:30
setup_message_id_table
static void setup_message_id_table(api_main_t *am)
Definition: sr_mpls_api.c:174
flowprobe_show_stats_fn
static clib_error_t * flowprobe_show_stats_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cm)
Definition: flowprobe.c:806
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
flowprobe_params
static int flowprobe_params(flowprobe_main_t *fm, u8 record_l2, u8 record_l3, u8 record_l4, u32 active_timer, u32 passive_timer)
Definition: flowprobe.c:671
vec_validate_aligned
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:534
validate_feature_on_interface
static int validate_feature_on_interface(flowprobe_main_t *fm, u32 sw_if_index, u8 which)
Definition: flowprobe.c:505
flowprobe_enable_disable_command
static vlib_cli_command_t flowprobe_enable_disable_command
(constructor) VLIB_CLI_COMMAND (flowprobe_enable_disable_command)
Definition: flowprobe.c:987
flowprobe_template_rewrite_l2_ip6
static u8 * flowprobe_template_rewrite_l2_ip6(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)
Definition: flowprobe.c:368
udp_local.h
flowprobe_flush_callback_l2
void flowprobe_flush_callback_l2(void)
Definition: node.c:892
vnet_flow_data_callback_t
vlib_frame_t *() vnet_flow_data_callback_t(struct flow_report_main *, struct flow_report *, vlib_frame_t *, u32 *, u32)
Definition: flow_report.h:51
unix_time_now_nsec
static u64 unix_time_now_nsec(void)
Definition: time.h:270
uword
u64 uword
Definition: types.h:112
flowprobe_data_callback_ip4
vlib_frame_t * flowprobe_data_callback_ip4(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
Flush accumulated data.
Definition: flowprobe.c:392
vlib_thread_main
vlib_thread_main_t vlib_thread_main
Definition: threads.c:36
ipfix_report_element_t
Definition: flow_report.h:34
format_flowprobe_params
u8 * format_flowprobe_params(u8 *s, va_list *args)
Definition: flowprobe.c:758
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
src_port
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
FLOW_RECORD_L2_IP4
@ FLOW_RECORD_L2_IP4
Definition: flowprobe.h:40
flowprobe_template_ip6_field_count
#define flowprobe_template_ip6_field_count()
f64
double f64
Definition: types.h:142
vl_api_flowprobe_params_t::passive_timer
u32 passive_timer
Definition: flowprobe.api:56
flowprobe_params_command_fn
static clib_error_t * flowprobe_params_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: flowprobe.c:915
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
flowprobe_template_add_del
static int flowprobe_template_add_del(u32 domain_id, u16 src_port, flowprobe_record_t flags, vnet_flow_data_callback_t *flow_data_callback, vnet_flow_rewrite_callback_t *rewrite_callback, bool is_add, u16 *template_id)
Definition: flowprobe.c:419
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
flowprobe_create_state_tables
static clib_error_t * flowprobe_create_state_tables(u32 active_timer)
Definition: flowprobe.c:454
flowprobe_entry_t::key
flowprobe_key_t key
Definition: flowprobe.h:99
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
format_flowprobe_entry
u8 * format_flowprobe_entry(u8 *s, va_list *args)
Definition: flowprobe.c:726
flow_report_main
Definition: flow_report.h:110
ip4_address_t
Definition: ip4_packet.h:50
version_length
static u32 version_length(u16 length)
Definition: ipfix_packet.h:33
flow_report_main::streams
flow_report_stream_t * streams
Definition: flow_report.h:113
flowprobe.h
flow-per-packet plugin header file
vec_neg_search
#define vec_neg_search(v, E)
Definition: flowprobe.c:658
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
ipfix_message_header_t
Definition: ipfix_packet.h:24
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
flowprobe_template_common_fields
static ipfix_field_specifier_t * flowprobe_template_common_fields(ipfix_field_specifier_t *f)
Definition: flowprobe.c:144
flowprobe_flush_callback_ip6
void flowprobe_flush_callback_ip6(void)
Definition: node.c:886
flowprobe_key_t::src_port
u16 src_port
Definition: flowprobe.h:85
flowprobe_tx_interface_add_del_feature_command_fn
static clib_error_t * flowprobe_tx_interface_add_del_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: flowprobe.c:825
BAD_SW_IF_INDEX_LABEL
#define BAD_SW_IF_INDEX_LABEL
Definition: api_helper_macros.h:289
flowprobe_variant_t
flowprobe_variant_t
Definition: flowprobe.h:46
plugin.h
flowprobe_record_t
flowprobe_record_t
Definition: flowprobe.h:35
FLOW_VARIANT_L2
@ FLOW_VARIANT_L2
Definition: flowprobe.h:50
ipfix_id_count
static u32 ipfix_id_count(u16 id, u16 count)
Definition: ipfix_packet.h:184
FLOW_RECORD_L2_IP6
@ FLOW_RECORD_L2_IP6
Definition: flowprobe.h:41
ip4_ipfix_template_packet_t::ip4
ip4_header_t ip4
Definition: flow_report.h:43
flow_report::template_id
u16 template_id
Definition: flow_report.h:89
flowprobe_template_rewrite_ip4
static u8 * flowprobe_template_rewrite_ip4(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)
Definition: flowprobe.c:326
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:458
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:462
vlib_process_wait_for_event_or_clock
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:755
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
vlib_thread_main_t::n_threads
u32 n_threads
Definition: threads.h:271
vl_api_flowprobe_params_t::active_timer
u32 active_timer
Definition: flowprobe.api:55
format_ip46_address
format_function_t format_ip46_address
Definition: ip46_address.h:50
vlib_process_suspend
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:486
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
FLOW_RECORD_L3
@ FLOW_RECORD_L3
Definition: flowprobe.h:38
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
flowprobe_timer_node
static vlib_node_registration_t flowprobe_timer_node
(constructor) VLIB_REGISTER_NODE (flowprobe_timer_node)
Definition: flowprobe.c:40
flow_report_stream_t
Definition: flow_report.h:76
vlib_thread_main_t
Definition: threads.h:243
vlib_node_set_interrupt_pending
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:249
vnet_flow_report_add_del_args_t
Definition: flow_report.h:147
FLOW_VARIANT_L2_IP4
@ FLOW_VARIANT_L2_IP4
Definition: flowprobe.h:51
api_helper_macros.h
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
VLIB_NODE_TYPE_PROCESS
@ VLIB_NODE_TYPE_PROCESS
Definition: node.h:84
vlib_get_main_by_index
static vlib_main_t * vlib_get_main_by_index(u32 thread_index)
Definition: global_funcs.h:29
FLOW_VARIANT_IP6
@ FLOW_VARIANT_IP6
Definition: flowprobe.h:49
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
FLOW_VARIANT_L2_IP6
@ FLOW_VARIANT_L2_IP6
Definition: flowprobe.h:52
FLOWPROBE_RECORD_FLAG_L4
@ FLOWPROBE_RECORD_FLAG_L4
Definition: flowprobe.api:23
flowprobe_show_feature_command
static vlib_cli_command_t flowprobe_show_feature_command
(constructor) VLIB_CLI_COMMAND (flowprobe_show_feature_command)
Definition: flowprobe.c:1000
VLIB_PLUGIN_REGISTER
VLIB_PLUGIN_REGISTER()
vec_resize
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V,...
Definition: vec.h:296
vnet_feature_enable_disable
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: pnat_test_stubs.h:50
flowprobe_show_table_command
static vlib_cli_command_t flowprobe_show_table_command
(constructor) VLIB_CLI_COMMAND (flowprobe_show_table_command)
Definition: flowprobe.c:1012
now
f64 now
Definition: nat44_ei_out2in.c:710
ipfix_template_header_t
Definition: ipfix_packet.h:178
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
flowprobe_flush_callback_ip4
void flowprobe_flush_callback_ip4(void)
Definition: node.c:880
vlib_get_n_threads
static u32 vlib_get_n_threads()
Definition: global_funcs.h:23
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
ipfix_field_specifier_t
Definition: ipfix_packet.h:71
VNET_FEATURES
#define VNET_FEATURES(...)
Definition: feature.h:470
FLOWPROBE_LOG2_HASHSIZE
#define FLOWPROBE_LOG2_HASHSIZE
Definition: flowprobe.h:33
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
a
a
Definition: bitmap.h:525
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:419
ip
vl_api_address_t ip
Definition: l2.api:558
ip4_header_checksum
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
vl_api_flowprobe_params_t_handler
void vl_api_flowprobe_params_t_handler(vl_api_flowprobe_params_t *mp)
Definition: flowprobe.c:701
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
i
int i
Definition: flowhash_template.h:376
ipfix_set_id_length
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:121
FLOW_RECORD_L2
@ FLOW_RECORD_L2
Definition: flowprobe.h:37
vl_api_flowprobe_tx_interface_add_del_t
Enable / disable per-packet IPFIX recording on an interface.
Definition: flowprobe.api:33
flowprobe_template_l2_field_count
#define flowprobe_template_l2_field_count()
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
pool_alloc
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
Definition: pool.h:367
FLOW_VARIANT_IP4
@ FLOW_VARIANT_IP4
Definition: flowprobe.h:48
flowprobe_walker_process
uword flowprobe_walker_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
flowprobe_key_t::src_mac
u8 src_mac[6]
Definition: flowprobe.h:79
rv
int __clib_unused rv
Definition: application.c:491
IP46_TYPE_ANY
@ IP46_TYPE_ANY
Definition: ip46_address.h:24
vnet_flow_report_add_del
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:344
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
FLOWPROBE_TIMER_ACTIVE
#define FLOWPROBE_TIMER_ACTIVE
Definition: flowprobe.h:31
vnet.h
vlib_node_runtime_t
Definition: node.h:454
vl_api_flowprobe_params_t
Definition: flowprobe.api:50
src_address
vl_api_address_union_t src_address
Definition: ip_types.api:122
vlib_cli_command_t
Definition: cli.h:92
TWT
Definition: tw_timer_template.h:118
FLOWPROBE_RECORD_FLAG_L3
@ FLOWPROBE_RECORD_FLAG_L3
Definition: flowprobe.api:22
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
rewrite
rewrite
Definition: pnat.api:158
FLOW_RECORD_L4
@ FLOW_RECORD_L4
Definition: flowprobe.h:39
flowprobe_template_common_field_count
#define flowprobe_template_common_field_count()
ipfix_set_header_t::set_id_length
u32 set_id_length
Definition: ipfix_packet.h:117
flowprobe_data_callback_l2
vlib_frame_t * flowprobe_data_callback_l2(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
Definition: flowprobe.c:410
clib_mem_alloc
static void * clib_mem_alloc(uword size)
Definition: mem.h:256
flowprobe_data_callback_ip6
vlib_frame_t * flowprobe_data_callback_ip6(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
Definition: flowprobe.c:401
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
flow_report::opaque
opaque_t opaque
Definition: flow_report.h:98
vl_api_flowprobe_tx_interface_add_del_t::sw_if_index
vl_api_interface_index_t sw_if_index
Definition: flowprobe.api:46
flowprobe_show_feature_command_fn
static clib_error_t * flowprobe_show_feature_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: flowprobe.c:893
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
ipfix_template_header_t::id_count
u32 id_count
Definition: ipfix_packet.h:180
flowprobe_template_rewrite_l2
static u8 * flowprobe_template_rewrite_l2(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)
Definition: flowprobe.c:340
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105