27 #include <vpp/app/version.h> 49 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) 61 #define vl_api_version(n,v) static u32 api_version=(v); 65 #define REPLY_MSG_ID_BASE fm->msg_id_base 72 .arc_name =
"ip4-output",
73 .node_name =
"flowprobe-ip4",
79 .arc_name =
"ip6-output",
80 .node_name =
"flowprobe-ip6",
86 .arc_name =
"interface-output",
87 .node_name =
"flowprobe-l2",
95 vl_print (handle, (char *)s); \ 102 #define flowprobe_template_ip4_field_count() 4 105 sourceIPv4Address, 4);
109 destinationIPv4Address, 4);
113 protocolIdentifier, 1);
125 #define flowprobe_template_ip6_field_count() 4 128 sourceIPv6Address, 16);
132 destinationIPv6Address, 16);
136 protocolIdentifier, 1);
148 #define flowprobe_template_l2_field_count() 3 151 sourceMacAddress, 6);
155 destinationMacAddress, 6);
167 #define flowprobe_template_common_field_count() 3 170 ingressInterface, 4);
180 packetDeltaCount, 8);
189 #define flowprobe_template_l4_field_count() 2 192 sourceTransportPort, 2);
196 destinationTransportPort, 2);
231 bool collect_ip4 =
false, collect_ip6 =
false;
275 udp->
dst_port = clib_host_to_net_u16 (collector_port);
276 udp->
length = clib_host_to_net_u16 (
vec_len (rewrite) -
sizeof (*ip));
285 if (flags & FLOW_RECORD_L2)
291 if (flags & FLOW_RECORD_L4)
311 ip->
length = clib_host_to_net_u16 ((
u8 *) f - (
u8 *) ip);
325 (frm, fr, collector_address, src_address, collector_port,
337 (frm, fr, collector_address, src_address, collector_port,
349 (frm, fr, collector_address, src_address, collector_port,
361 (frm, fr, collector_address, src_address, collector_port,
373 (frm, fr, collector_address, src_address, collector_port,
419 bool is_add,
u16 * template_id)
423 .rewrite_callback = rewrite_callback,
424 .flow_data_callback = flow_data_callback,
426 .domain_id = domain_id,
427 .src_port = src_port,
428 .opaque.as_uword =
flags,
442 for (i = 0; i <
vec_len (expired_timers); i++)
444 poolindex = expired_timers[
i] & 0x7FFFFFFF;
473 for (i = 0; i < num_threads; i++)
480 fm->timers_per_worker[i] =
482 tw_timer_wheel_init_2t_1w_2048sl (fm->timers_per_worker[i],
492 for (i = 0; i < num_threads; i++)
524 u32 sw_if_index,
u8 which,
int is_add)
546 is_add, &template_id);
553 is_add, &template_id);
555 (is_add) ? template_id : 0;
560 is_add, &template_id);
562 (is_add) ? template_id : 0;
577 is_add, &template_id);
582 is_add, &template_id);
584 if (rv && rv != VNET_API_ERROR_VALUE_EXIST)
586 clib_warning (
"vnet_flow_report_add_del returned %d", rv);
590 if (which != (
u8) ~ 0)
598 sw_if_index, is_add, 0, 0);
601 sw_if_index, is_add, 0, 0);
604 sw_if_index, is_add, 0, 0);
625 vl_api_flowprobe_tx_interface_add_del_reply_t *rmp;
634 rv = VNET_API_ERROR_UNIMPLEMENTED;
640 clib_warning (
"Please specify flowprobe params record first...");
641 rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
646 if ((rv == 1 && mp->
is_add == 1) || rv == 0)
648 rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
658 REPLY_MACRO (VL_API_FLOWPROBE_TX_INTERFACE_ADD_DEL_REPLY);
672 s =
format (0,
"SCRIPT: flowprobe_tx_interface_add_del ");
673 s =
format (s,
"sw_if_index %d is_add %d which %d ",
679 #define vec_neg_search(v,E) \ 682 while (_v(i) < vec_len(v) && v[_v(i)] == E) \ 686 if (_v(i) == vec_len(v)) \ 693 u8 record_l3,
u8 record_l4,
694 u32 active_timer,
u32 passive_timer)
725 vl_api_flowprobe_params_reply_t *rmp;
737 #define foreach_flowprobe_plugin_api_msg \ 738 _(FLOWPROBE_TX_INTERFACE_ADD_DEL, flowprobe_tx_interface_add_del) \ 739 _(FLOWPROBE_PARAMS, flowprobe_params) 743 .version = VPP_BUILD_VER,
744 .description =
"Flow per Packet",
752 s =
format (s,
" %d/%d", e->
key.rx_sw_if_index, e->
key.tx_sw_if_index);
756 s =
format (s,
" %U -> %U",
760 s =
format (s,
" %d %d\n", clib_net_to_host_u16 (e->
key.src_port),
761 clib_net_to_host_u16 (e->
key.dst_port));
781 vlib_cli_output (vm,
"%U",
782 format_flowprobe_entry,
816 u32 sw_if_index = ~0;
839 "Please specify flowprobe params record first...");
841 if (sw_if_index == ~0)
849 "Datapath is already enabled for given interface...");
853 "Interface has enable different datapath ...");
862 case VNET_API_ERROR_INVALID_SW_IF_INDEX:
864 (0,
"Invalid interface, only works on physical ports");
867 case VNET_API_ERROR_UNIMPLEMENTED:
884 bool record_l2 =
false, record_l3 =
false, record_l4 =
false;
885 u32 active_timer = ~0;
886 u32 passive_timer = ~0;
890 if (
unformat (input,
"active %d", &active_timer))
892 else if (
unformat (input,
"passive %d", &passive_timer))
894 else if (
unformat (input,
"record"))
910 if (passive_timer > 0 && active_timer > passive_timer)
912 "Passive timer has to be greater than active one...");
915 active_timer, passive_timer))
917 "Couldn't change flowperpacket params when feature is enabled on some interface ...");
937 .path =
"flowprobe feature add-del",
939 "flowprobe feature add-del <interface-name> <l2|ip4|ip6> disable",
943 .path =
"flowprobe params",
945 "flowprobe params record <[l2] [l3] [l4]> [active <timer> passive <timer>]",
949 .path =
"show flowprobe table",
950 .short_help =
"show flowprobe table",
954 .path =
"show flowprobe statistics",
955 .short_help =
"show flowprobe statistics",
970 vl_msg_api_set_handlers((VL_API_##N + fm->msg_id_base), \ 972 vl_api_##n##_t_handler, \ 974 vl_api_##n##_t_endian, \ 975 vl_api_##n##_t_print, \ 976 sizeof(vl_api_##n##_t), 1); 983 #define vl_msg_name_crc_list 985 #undef vl_msg_name_crc_list 990 #define _(id,n,crc) \ 991 vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + fm->msg_id_base); 992 foreach_vl_msg_name_crc_flowprobe;
1003 uword *event_data = 0;
1010 if (event_type != 1)
1011 clib_warning (
"bogus kickoff event received, %d", event_type);
1026 f64 sleep_duration = 0.1;
1031 sleep_duration = 0.1;
1032 for (i = 0; i <
vec_len (worker_vms); i++)
1034 worker_vm = worker_vms[
i];
1038 flowprobe_walker_node.index);
1051 .name =
"flowprobe-timer-process",
1074 name =
format (0,
"flowprobe_%08x%c", api_version, 0);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
uword flowprobe_walker_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
flowprobe_protocol_context_t context[FLOW_N_VARIANTS]
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.
u16 vl_msg_api_get_msg_ids(const char *name, int n)
sll srl srl sll sra u16x4 i
u32 ** expired_passive_per_worker
#define FLOWPROBE_LOG2_HASHSIZE
void flowprobe_flush_callback_ip6(void)
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...
#define FLOWPROBE_TIMER_PASSIVE
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)
static void setup_message_id_table(flowprobe_main_t *fm, api_main_t *am)
static clib_error_t * flowprobe_plugin_api_hookup(vlib_main_t *vm)
Set up the API message handling tables.
vnet_main_t * vnet_get_main(void)
#define pool_alloc(P, N)
Allocate N more free elements to pool (unspecified alignment).
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
static u32 ipfix_e_id_length(int e, u16 id, u16 length)
static f64 vlib_time_now(vlib_main_t *vm)
int vnet_flow_report_add_del(flow_report_main_t *frm, vnet_flow_report_add_del_args_t *a, u16 *template_id)
flowprobe_record_t record
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
struct _vlib_node_registration vlib_node_registration_t
#define flowprobe_template_l2_field_count()
flowprobe_entry_t * stateless_entry
u16 template_reports[FLOW_N_RECORDS]
unformat_function_t unformat_vnet_sw_interface
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
u8 *( vnet_flow_rewrite_callback_t)(struct flow_report_main *, struct flow_report *, ip4_address_t *, ip4_address_t *, u16)
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)
static ipfix_field_specifier_t * flowprobe_template_common_fields(ipfix_field_specifier_t *f)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
flowprobe_entry_t ** pool_per_worker
Enable / disable per-packet IPFIX recording on an interface.
flow_report_stream_t * streams
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
static ipfix_field_specifier_t * flowprobe_template_ip4_fields(ipfix_field_specifier_t *f)
flow-per-packet plugin header file
u8 * format_ethernet_address(u8 *s, va_list *args)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#define VLIB_INIT_FUNCTION(x)
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...
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)
vlib_frame_t ** frames_per_worker
frames containing ipfix buffers, per-worker thread
#define flowprobe_template_l4_field_count()
#define clib_error_return(e, args...)
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
vlib_frame_t *( vnet_flow_data_callback_t)(struct flow_report_main *, struct flow_report *, vlib_frame_t *, u32 *, u32)
void flowprobe_flush_callback_ip4(void)
#define foreach_flowprobe_plugin_api_msg
u64 nanosecond_time_0
Time reference pair.
static int flowprobe_params(flowprobe_main_t *fm, u8 record_l2, u8 record_l3, u8 record_l4, u32 active_timer, u32 passive_timer)
u8 ht_log2len
Per CPU flow-state.
flow_report_main_t flow_report_main
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
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
VNET_FEATURE_INIT(flow_perpacket_ip4, static)
#define flowprobe_template_ip4_field_count()
u16 template_per_flow[FLOW_N_VARIANTS]
static void flowprobe_expired_timer_callback(u32 *expired_timers)
static u32 version_length(u16 length)
vlib_thread_main_t vlib_thread_main
void vl_api_flowprobe_tx_interface_add_del_t_handler(vl_api_flowprobe_tx_interface_add_del_t *mp)
API message handler.
#define BAD_SW_IF_INDEX_LABEL
#define flowprobe_template_ip6_field_count()
static clib_error_t * flowprobe_show_stats_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cm)
#define FLOWPROBE_TIMER_ACTIVE
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)
#define vec_free(V)
Free vector's memory (no header).
vlib_node_registration_t flowprobe_walker_node
vnet_main_t * vnet_main
convenience vnet_main_t pointer
static u32 ipfix_id_count(u16 id, u16 count)
#define clib_warning(format, args...)
#define vec_neg_search(v, E)
static u64 unix_time_now_nsec(void)
static clib_error_t * flowprobe_init(vlib_main_t *vm)
Set up the API message handling tables.
#define VLIB_CLI_COMMAND(x,...)
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)
static ipfix_field_specifier_t * flowprobe_template_ip6_fields(ipfix_field_specifier_t *f)
static void * clib_mem_alloc(uword size)
#define VNET_FEATURES(...)
static vlib_main_t * vlib_get_main(void)
flowprobe_main_t flowprobe_main
static u32 ipfix_set_id_length(u16 set_id, u16 length)
vlib_buffer_t ** buffers_per_worker
ipfix buffers under construction, per-worker thread
#define flowprobe_template_common_field_count()
void flowprobe_flush_callback_l2(void)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
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)
u16 template_size[FLOW_N_RECORDS]
vlib_main_t ** vlib_mains
static ipfix_field_specifier_t * flowprobe_template_l4_fields(ipfix_field_specifier_t *f)
u16 msg_id_base
API message ID base.
void vl_api_flowprobe_params_t_handler(vl_api_flowprobe_params_t *mp)
u8 * format_flowprobe_entry(u8 *s, va_list *args)
#define VLIB_REGISTER_NODE(x,...)
static ipfix_field_specifier_t * flowprobe_template_l2_fields(ipfix_field_specifier_t *f)
static int validate_feature_on_interface(flowprobe_main_t *fm, u32 sw_if_index, u8 which)
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)
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)
u16 * next_record_offset_per_worker
next record offset, per worker thread
static void * vl_api_flowprobe_tx_interface_add_del_t_print(vl_api_flowprobe_tx_interface_add_del_t *mp, void *handle)
API message custom-dump function.
static uword timer_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
#define CLIB_CACHE_LINE_BYTES
static clib_error_t * flowprobe_show_table_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cm)
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)
static clib_error_t * flowprobe_params_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static vlib_node_registration_t flowprobe_timer_node
(constructor) VLIB_REGISTER_NODE (flowprobe_timer_node)
static clib_error_t * flowprobe_create_state_tables(u32 active_timer)
static u16 ip4_header_checksum(ip4_header_t *i)
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)
#define VALIDATE_SW_IF_INDEX(mp)
static uword pool_elts(void *v)
Number of active elements in a pool.