#include <vnet/vnet.h>
#include <vpp/app/version.h>
#include <vnet/plugin/plugin.h>
+#include <vnet/udp/udp_local.h>
#include <flowprobe/flowprobe.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
/* define message IDs */
-#include <flowprobe/flowprobe_msg_enum.h>
-
-/* define message structures */
-#define vl_typedefs
-#include <flowprobe/flowprobe_all_api_h.h>
-#undef vl_typedefs
-
-/* define generated endian-swappers */
-#define vl_endianfun
-#include <flowprobe/flowprobe_all_api_h.h>
-#undef vl_endianfun
-
-/* instantiate all the print functions we know about */
-#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
-#define vl_printfun
-#include <flowprobe/flowprobe_all_api_h.h>
-#undef vl_printfun
+#include <flowprobe/flowprobe.api_enum.h>
+#include <flowprobe/flowprobe.api_types.h>
flowprobe_main_t flowprobe_main;
-vlib_node_registration_t flowprobe_walker_node;
static vlib_node_registration_t flowprobe_timer_node;
uword flowprobe_walker_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
vlib_frame_t * f);
-/* Get the API version number */
-#define vl_api_version(n,v) static u32 api_version=(v);
-#include <flowprobe/flowprobe_all_api_h.h>
-#undef vl_api_version
-
#define REPLY_MSG_ID_BASE fm->msg_id_base
#include <vlibapi/api_helper_macros.h>
/* *INDENT-ON* */
/* Macro to finish up custom dump fns */
+#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define FINISH \
vec_add1 (s, 0); \
vl_print (handle, (char *)s); \
VALIDATE_SW_IF_INDEX (mp);
- if (mp->which != FLOW_VARIANT_IP4 && mp->which != FLOW_VARIANT_L2
- && mp->which != FLOW_VARIANT_IP6)
- {
- rv = VNET_API_ERROR_UNIMPLEMENTED;
- goto out;
- }
-
if (fm->record == 0)
{
clib_warning ("Please specify flowprobe params record first...");
REPLY_MACRO (VL_API_FLOWPROBE_TX_INTERFACE_ADD_DEL_REPLY);
}
-/**
- * @brief API message custom-dump function
- * @param mp vl_api_flowprobe_tx_interface_add_del_t * mp the api message
- * @param handle void * print function handle
- * @returns u8 * output string
- */
-static void *vl_api_flowprobe_tx_interface_add_del_t_print
- (vl_api_flowprobe_tx_interface_add_del_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: flowprobe_tx_interface_add_del ");
- s = format (s, "sw_if_index %d is_add %d which %d ",
- clib_host_to_net_u32 (mp->sw_if_index),
- (int) mp->is_add, (int) mp->which);
- FINISH;
-}
-
#define vec_neg_search(v,E) \
({ \
word _v(i) = 0; \
int rv = 0;
rv = flowprobe_params
- (fm, mp->record_l2, mp->record_l3, mp->record_l4,
+ (fm,
+ mp->record_flags & FLOWPROBE_RECORD_FLAG_L2,
+ mp->record_flags & FLOWPROBE_RECORD_FLAG_L3,
+ mp->record_flags & FLOWPROBE_RECORD_FLAG_L4,
clib_net_to_host_u32 (mp->active_timer),
clib_net_to_host_u32 (mp->passive_timer));
REPLY_MACRO (VL_API_FLOWPROBE_PARAMS_REPLY);
}
-/* List of message types that this plugin understands */
-#define foreach_flowprobe_plugin_api_msg \
-_(FLOWPROBE_TX_INTERFACE_ADD_DEL, flowprobe_tx_interface_add_del) \
-_(FLOWPROBE_PARAMS, flowprobe_params)
-
/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
return s;
}
+u8 *
+format_flowprobe_feature (u8 * s, va_list * args)
+{
+ u8 *which = va_arg (*args, u8 *);
+ if (*which == FLOW_VARIANT_IP4)
+ s = format (s, "ip4");
+ else if (*which == FLOW_VARIANT_IP6)
+ s = format (s, "ip6");
+ else if (*which == FLOW_VARIANT_L2)
+ s = format (s, "l2");
+
+ return s;
+}
+
+u8 *
+format_flowprobe_params (u8 * s, va_list * args)
+{
+ flowprobe_record_t flags = va_arg (*args, flowprobe_record_t);
+ u32 active_timer = va_arg (*args, u32);
+ u32 passive_timer = va_arg (*args, u32);
+
+ if (flags & FLOW_RECORD_L2)
+ s = format (s, " l2");
+ if (flags & FLOW_RECORD_L3)
+ s = format (s, " l3");
+ if (flags & FLOW_RECORD_L4)
+ s = format (s, " l4");
+
+ if (active_timer != (u32) ~ 0)
+ s = format (s, " active: %d", active_timer);
+
+ if (passive_timer != (u32) ~ 0)
+ s = format (s, " passive: %d", passive_timer);
+
+ return s;
+}
+
static clib_error_t *
flowprobe_show_table_fn (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cm)
for (i = 0; i < vec_len (fm->pool_per_worker); i++)
{
/* *INDENT-OFF* */
- pool_foreach (e, fm->pool_per_worker[i], (
+ pool_foreach (e, fm->pool_per_worker[i])
{
vlib_cli_output (vm, "%U",
format_flowprobe_entry,
e);
- }));
+ }
/* *INDENT-ON* */
}
return 0;
}
+static clib_error_t *
+flowprobe_show_feature_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ flowprobe_main_t *fm = &flowprobe_main;
+ u8 *which;
+ u32 sw_if_index;
+
+ vec_foreach (which, fm->flow_per_interface)
+ {
+ if (*which == (u8) ~ 0)
+ continue;
+
+ sw_if_index = which - fm->flow_per_interface;
+ vlib_cli_output (vm, " %U %U", format_vnet_sw_if_index_name,
+ vnet_get_main (), sw_if_index, format_flowprobe_feature,
+ which);
+ }
+ return 0;
+}
+
static clib_error_t *
flowprobe_params_command_fn (vlib_main_t * vm,
unformat_input_t * input,
return 0;
}
+static clib_error_t *
+flowprobe_show_params_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ flowprobe_main_t *fm = &flowprobe_main;
+ flowprobe_record_t flags = fm->record;
+ u32 active_timer = fm->active_timer;
+ u32 passive_timer = fm->passive_timer;
+
+ vlib_cli_output (vm, "%U", format_flowprobe_params, flags, active_timer,
+ passive_timer);
+ return 0;
+}
+
/*?
* '<em>flowprobe feature add-del</em>' commands to enable/disable
* per-packet IPFIX flow record generation on an interface
"flowprobe params record <[l2] [l3] [l4]> [active <timer> passive <timer>]",
.function = flowprobe_params_command_fn,
};
+
+VLIB_CLI_COMMAND (flowprobe_show_feature_command, static) = {
+ .path = "show flowprobe feature",
+ .short_help =
+ "show flowprobe feature",
+ .function = flowprobe_show_feature_command_fn,
+};
+VLIB_CLI_COMMAND (flowprobe_show_params_command, static) = {
+ .path = "show flowprobe params",
+ .short_help =
+ "show flowprobe params",
+ .function = flowprobe_show_params_command_fn,
+};
VLIB_CLI_COMMAND (flowprobe_show_table_command, static) = {
.path = "show flowprobe table",
.short_help = "show flowprobe table",
};
/* *INDENT-ON* */
-/**
- * @brief Set up the API message handling tables
- * @param vm vlib_main_t * vlib main data structure pointer
- * @returns 0 to indicate all is well
- */
-static clib_error_t *
-flowprobe_plugin_api_hookup (vlib_main_t * vm)
-{
- flowprobe_main_t *fm = &flowprobe_main;
-#define _(N,n) \
- vl_msg_api_set_handlers((VL_API_##N + fm->msg_id_base), \
- #n, \
- vl_api_##n##_t_handler, \
- vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
- sizeof(vl_api_##n##_t), 1);
- foreach_flowprobe_plugin_api_msg;
-#undef _
-
- return 0;
-}
-
-#define vl_msg_name_crc_list
-#include <flowprobe/flowprobe_all_api_h.h>
-#undef vl_msg_name_crc_list
-
-static void
-setup_message_id_table (flowprobe_main_t * fm, api_main_t * am)
-{
-#define _(id,n,crc) \
- vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + fm->msg_id_base);
- foreach_vl_msg_name_crc_flowprobe;
-#undef _
-}
-
/*
* Main-core process, sending an interrupt to the per worker input
* process that spins the per worker timer wheel.
vec_reset_length (event_data);
int i;
- if (vec_len (vlib_mains) == 0)
+ if (vlib_get_n_threads () == 0)
vec_add1 (worker_vms, vm);
else
{
- for (i = 0; i < vec_len (vlib_mains); i++)
+ for (i = 0; i < vlib_get_n_threads (); i++)
{
- worker_vm = vlib_mains[i];
+ worker_vm = vlib_get_main_by_index (i);
if (worker_vm)
vec_add1 (worker_vms, worker_vm);
}
};
/* *INDENT-ON* */
+#include <flowprobe/flowprobe.api.c>
+
/**
* @brief Set up the API message handling tables
* @param vm vlib_main_t * vlib main data structure pointer
flowprobe_main_t *fm = &flowprobe_main;
vlib_thread_main_t *tm = &vlib_thread_main;
clib_error_t *error = 0;
- u8 *name;
u32 num_threads;
int i;
fm->vnet_main = vnet_get_main ();
- /* Construct the API name */
- name = format (0, "flowprobe_%08x%c", api_version, 0);
-
/* Ask for a correctly-sized block of API message decode slots */
- fm->msg_id_base = vl_msg_api_get_msg_ids
- ((char *) name, VL_MSG_FIRST_AVAILABLE);
-
- /* Hook up message handlers */
- error = flowprobe_plugin_api_hookup (vm);
-
- /* Add our API messages to the global name_crc hash table */
- setup_message_id_table (fm, &api_main);
-
- vec_free (name);
+ fm->msg_id_base = setup_message_id_table ();
/* Set up time reference pair */
fm->vlib_time_0 = vlib_time_now (vm);
fm->nanosecond_time_0 = unix_time_now_nsec ();
- memset (fm->template_reports, 0, sizeof (fm->template_reports));
- memset (fm->template_size, 0, sizeof (fm->template_size));
- memset (fm->template_per_flow, 0, sizeof (fm->template_per_flow));
+ clib_memset (fm->template_reports, 0, sizeof (fm->template_reports));
+ clib_memset (fm->template_size, 0, sizeof (fm->template_size));
+ clib_memset (fm->template_per_flow, 0, sizeof (fm->template_per_flow));
/* Decide how many worker threads we have */
num_threads = 1 /* main thread */ + tm->n_threads;