summaryrefslogtreecommitdiffstats
path: root/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2016-12-20 17:59:27 -0500
committerDamjan Marion <dmarion.lists@gmail.com>2016-12-22 19:04:16 +0000
commit504b83009a00d70c777c04014967494642074d52 (patch)
tree8159edc93c0027b0dac200875edf1f07481bbbff /plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
parentabea9664983b723023e692d77fd4fe3ca29c1e34 (diff)
Add L2 flow-record generation
Change-Id: I32a9513f2b66d35e0abe2aeb6eb86a4729ba7f74 Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c')
-rw-r--r--plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c299
1 files changed, 226 insertions, 73 deletions
diff --git a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
index 96c930ae599..fb71d5b0ffc 100644
--- a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
+++ b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
@@ -57,13 +57,21 @@ flowperpkt_main_t flowperpkt_main;
#include <flowperpkt/flowperpkt_all_api_h.h>
#undef vl_api_version
-/* Define the per-interface configurable feature */
+/* Define the per-interface configurable features */
/* *INDENT-OFF* */
-VNET_FEATURE_INIT (flow_perpacket, static) = {
+VNET_FEATURE_INIT (flow_perpacket_ipv4, static) =
+{
.arc_name = "ip4-output",
- .node_name = "flowperpkt",
+ .node_name = "flowperpkt-ipv4",
.runs_before = VNET_FEATURES ("interface-output"),
};
+
+VNET_FEATURE_INIT (flow_perpacket_l2, static) =
+{
+ .arc_name = "interface-output",
+ .node_name = "flowperpkt-l2",
+ .runs_before = VNET_FEATURES ("interface-tx"),
+};
/* *INDENT-ON* */
/*
@@ -120,11 +128,12 @@ bad_sw_if_index: \
* @param collector_port u16 the collector port we should use, host byte order
* @returns u8 * vector containing the indicated IPFIX template packet
*/
-u8 *
-flowperpkt_template_rewrite (flow_report_main_t * frm,
- flow_report_t * fr,
- ip4_address_t * collector_address,
- ip4_address_t * src_address, u16 collector_port)
+static inline u8 *
+flowperpkt_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, int variant)
{
ip4_header_t *ip;
udp_header_t *udp;
@@ -137,32 +146,64 @@ flowperpkt_template_rewrite (flow_report_main_t * frm,
ip4_ipfix_template_packet_t *tp;
u32 field_count = 0;
flow_report_stream_t *stream;
+ flowperpkt_main_t *fm = &flowperpkt_main;
stream = &frm->streams[fr->stream_index];
- /*
- * Supported Fields:
- *
- * ingressInterface, TLV type 10, u32
- * egressInterface, TLV type 14, u32
- * sourceIpv4Address, TLV type 8, u32
- * destinationIPv4Address, TLV type 12, u32
- * ipClassOfService, TLV type 5, u8
- * flowStartNanoseconds, TLV type 156, dateTimeNanoseconds (f64)
- * Implementation: f64 nanoseconds since VPP started
- * warning: wireshark doesn't really understand this TLV
- * dataLinkFrameSize, TLV type 312, u16
- * warning: wireshark doesn't understand this TLV at all
- */
-
- /* Currently 7 fields */
- field_count += 7;
-
- /* allocate rewrite space */
- vec_validate_aligned (rewrite,
- sizeof (ip4_ipfix_template_packet_t)
- + field_count * sizeof (ipfix_field_specifier_t) - 1,
- CLIB_CACHE_LINE_BYTES);
+ if (variant == FLOW_VARIANT_IPV4)
+ {
+ /*
+ * ip4 Supported Fields:
+ *
+ * ingressInterface, TLV type 10, u32
+ * egressInterface, TLV type 14, u32
+ * sourceIpv4Address, TLV type 8, u32
+ * destinationIPv4Address, TLV type 12, u32
+ * ipClassOfService, TLV type 5, u8
+ * flowStartNanoseconds, TLV type 156, dateTimeNanoseconds (f64)
+ * Implementation: f64 nanoseconds since VPP started
+ * warning: wireshark doesn't really understand this TLV
+ * dataLinkFrameSize, TLV type 312, u16
+ * warning: wireshark doesn't understand this TLV at all
+ */
+
+ /* Currently 7 fields */
+ field_count += 7;
+
+ /* allocate rewrite space */
+ vec_validate_aligned
+ (rewrite,
+ sizeof (ip4_ipfix_template_packet_t)
+ + field_count * sizeof (ipfix_field_specifier_t) - 1,
+ CLIB_CACHE_LINE_BYTES);
+ }
+ else if (variant == FLOW_VARIANT_L2)
+ {
+ /*
+ * L2 Supported Fields:
+ *
+ * ingressInterface, TLV type 10, u32
+ * egressInterface, TLV type 14, u32
+ * sourceMacAddress, TLV type 56, u8[6] we hope
+ * destinationMacAddress, TLV type 57, u8[6] we hope
+ * ethernetType, TLV type 256, u16
+ * flowStartNanoseconds, TLV type 156, dateTimeNanoseconds (f64)
+ * Implementation: f64 nanoseconds since VPP started
+ * warning: wireshark doesn't really understand this TLV
+ * dataLinkFrameSize, TLV type 312, u16
+ * warning: wireshark doesn't understand this TLV at all
+ */
+
+ /* Currently 7 fields */
+ field_count += 7;
+
+ /* allocate rewrite space */
+ vec_validate_aligned
+ (rewrite,
+ sizeof (ip4_ipfix_template_packet_t)
+ + field_count * sizeof (ipfix_field_specifier_t) - 1,
+ CLIB_CACHE_LINE_BYTES);
+ }
tp = (ip4_ipfix_template_packet_t *) rewrite;
ip = (ip4_header_t *) & tp->ip4;
@@ -186,28 +227,66 @@ flowperpkt_template_rewrite (flow_report_main_t * frm,
h->domain_id = clib_host_to_net_u32 (stream->domain_id);
/* Add TLVs to the template */
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , ingressInterface,
- 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , egressInterface,
- 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , sourceIPv4Address,
- 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ ,
- destinationIPv4Address, 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , ipClassOfService,
- 1);
- f++;
- f->e_id_length =
- ipfix_e_id_length (0 /* enterprise */ , flowStartNanoseconds,
- 8);
- f++;
- f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , dataLinkFrameSize,
- 2);
- f++;
+ if (variant == FLOW_VARIANT_IPV4)
+ {
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , ingressInterface,
+ 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , egressInterface,
+ 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , sourceIPv4Address,
+ 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , destinationIPv4Address, 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , ipClassOfService,
+ 1);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , flowStartNanoseconds,
+ 8);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , dataLinkFrameSize,
+ 2);
+ f++;
+ }
+ else if (variant == FLOW_VARIANT_L2)
+ {
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , ingressInterface,
+ 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , egressInterface,
+ 4);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , sourceMacAddress,
+ 6);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , destinationMacAddress, 6);
+ f++;
+ f->e_id_length = ipfix_e_id_length (0 /* enterprise */ , ethernetType,
+ 2);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , flowStartNanoseconds,
+ 8);
+ f++;
+ f->e_id_length =
+ ipfix_e_id_length (0 /* enterprise */ , dataLinkFrameSize,
+ 2);
+ f++;
+ }
+
/* Extend in the obvious way, right here... */
/* Back to the template packet... */
@@ -218,6 +297,11 @@ flowperpkt_template_rewrite (flow_report_main_t * frm,
/* Field count in this template */
t->id_count = ipfix_id_count (fr->template_id, f - first_field);
+ if (variant == FLOW_VARIANT_IPV4)
+ fm->ipv4_report_id = fr->template_id;
+ else if (variant == FLOW_VARIANT_L2)
+ fm->l2_report_id = fr->template_id;
+
/* set length in octets */
s->set_id_length =
ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
@@ -231,6 +315,31 @@ flowperpkt_template_rewrite (flow_report_main_t * frm,
return rewrite;
}
+u8 *
+flowperpkt_template_rewrite_ipv4 (flow_report_main_t * frm,
+ flow_report_t * fr,
+ ip4_address_t * collector_address,
+ ip4_address_t * src_address,
+ u16 collector_port)
+{
+ return flowperpkt_template_rewrite_inline
+ (frm, fr, collector_address, src_address, collector_port,
+ FLOW_VARIANT_IPV4);
+}
+
+u8 *
+flowperpkt_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)
+{
+ return flowperpkt_template_rewrite_inline
+ (frm, fr, collector_address, src_address, collector_port,
+ FLOW_VARIANT_L2);
+}
+
+
/**
* @brief Flush accumulated data
* @param frm flow_report_main_t *
@@ -242,11 +351,21 @@ flowperpkt_template_rewrite (flow_report_main_t * frm,
* will be sent.
*/
vlib_frame_t *
-flowperpkt_data_callback (flow_report_main_t * frm,
- flow_report_t * fr,
- vlib_frame_t * f, u32 * to_next, u32 node_index)
+flowperpkt_data_callback_ipv4 (flow_report_main_t * frm,
+ flow_report_t * fr,
+ vlib_frame_t * f, u32 * to_next,
+ u32 node_index)
+{
+ flowperpkt_flush_callback_ipv4 ();
+ return f;
+}
+
+vlib_frame_t *
+flowperpkt_data_callback_l2 (flow_report_main_t * frm,
+ flow_report_t * fr,
+ vlib_frame_t * f, u32 * to_next, u32 node_index)
{
- flowperpkt_flush_callback ();
+ flowperpkt_flush_callback_l2 ();
return f;
}
@@ -259,21 +378,21 @@ flowperpkt_data_callback (flow_report_main_t * frm,
*/
static int flowperpkt_tx_interface_add_del_feature
- (flowperpkt_main_t * fm, u32 sw_if_index, int is_add)
+ (flowperpkt_main_t * fm, u32 sw_if_index, int which, int is_add)
{
flow_report_main_t *frm = &flow_report_main;
vnet_flow_report_add_del_args_t _a, *a = &_a;
int rv;
- if (!fm->report_created)
+ if (which == FLOW_VARIANT_IPV4 && !fm->ipv4_report_created)
{
memset (a, 0, sizeof (*a));
- a->rewrite_callback = flowperpkt_template_rewrite;
- a->flow_data_callback = flowperpkt_data_callback;
+ a->rewrite_callback = flowperpkt_template_rewrite_ipv4;
+ a->flow_data_callback = flowperpkt_data_callback_ipv4;
a->is_add = 1;
a->domain_id = 1; /*$$$$ config parameter */
a->src_port = 4739; /*$$$$ config parameter */
- fm->report_created = 1;
+ fm->ipv4_report_created = 1;
rv = vnet_flow_report_add_del (frm, a);
if (rv)
@@ -282,9 +401,30 @@ static int flowperpkt_tx_interface_add_del_feature
return -1;
}
}
+ else if (which == FLOW_VARIANT_L2 && !fm->l2_report_created)
+ {
+ memset (a, 0, sizeof (*a));
+ a->rewrite_callback = flowperpkt_template_rewrite_l2;
+ a->flow_data_callback = flowperpkt_data_callback_l2;
+ a->is_add = 1;
+ a->domain_id = 1; /*$$$$ config parameter */
+ a->src_port = 4739; /*$$$$ config parameter */
+ fm->l2_report_created = 1;
- vnet_feature_enable_disable ("ip4-output", "flowperpkt", sw_if_index,
- is_add, 0, 0);
+ rv = vnet_flow_report_add_del (frm, a);
+ if (rv)
+ {
+ clib_warning ("vnet_flow_report_add_del returned %d", rv);
+ return -1;
+ }
+ }
+
+ if (which == FLOW_VARIANT_IPV4)
+ vnet_feature_enable_disable ("ip4-output", "flowperpkt-ipv4",
+ sw_if_index, is_add, 0, 0);
+ else if (which == FLOW_VARIANT_L2)
+ vnet_feature_enable_disable ("interface-output", "flowperpkt-l2",
+ sw_if_index, is_add, 0, 0);
return 0;
}
@@ -303,8 +443,15 @@ void vl_api_flowperpkt_tx_interface_add_del_t_handler
VALIDATE_SW_IF_INDEX (mp);
- rv = flowperpkt_tx_interface_add_del_feature (fm, sw_if_index, mp->is_add);
+ if (mp->which != FLOW_VARIANT_IPV4 && mp->which != FLOW_VARIANT_L2)
+ {
+ rv = VNET_API_ERROR_UNIMPLEMENTED;
+ goto out;
+ }
+ rv = flowperpkt_tx_interface_add_del_feature (fm, sw_if_index, mp->which,
+ mp->is_add);
+out:
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_FLOWPERPKT_TX_INTERFACE_ADD_DEL_REPLY);
@@ -322,9 +469,9 @@ static void *vl_api_flowperpkt_tx_interface_add_del_t_print
u8 *s;
s = format (0, "SCRIPT: flowperpkt_tx_interface_add_del ");
- s = format (s, "sw_if_index %d is_add %d is_ipv6 %d ",
+ 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->is_ipv6);
+ (int) mp->is_add, (int) mp->which);
FINISH;
}
@@ -365,6 +512,7 @@ flowperpkt_tx_interface_add_del_feature_command_fn (vlib_main_t * vm,
flowperpkt_main_t *fm = &flowperpkt_main;
u32 sw_if_index = ~0;
int is_add = 1;
+ u8 which = FLOW_VARIANT_IPV4;
int rv;
@@ -373,8 +521,9 @@ flowperpkt_tx_interface_add_del_feature_command_fn (vlib_main_t * vm,
if (unformat (input, "disable"))
is_add = 0;
else if (unformat (input, "%U", unformat_vnet_sw_interface,
- fm->vnet_main, &sw_if_index))
- ;
+ fm->vnet_main, &sw_if_index));
+ else if (unformat (input, "l2"))
+ which = FLOW_VARIANT_L2;
else
break;
}
@@ -382,7 +531,8 @@ flowperpkt_tx_interface_add_del_feature_command_fn (vlib_main_t * vm,
if (sw_if_index == ~0)
return clib_error_return (0, "Please specify an interface...");
- rv = flowperpkt_tx_interface_add_del_feature (fm, sw_if_index, is_add);
+ rv =
+ flowperpkt_tx_interface_add_del_feature (fm, sw_if_index, which, is_add);
switch (rv)
{
case 0:
@@ -496,9 +646,12 @@ flowperpkt_init (vlib_main_t * vm)
num_threads = 1 /* main thread */ + tm->n_eal_threads;
/* Allocate per worker thread vectors */
- vec_validate (fm->buffers_per_worker, num_threads - 1);
- vec_validate (fm->frames_per_worker, num_threads - 1);
- vec_validate (fm->next_record_offset_per_worker, num_threads - 1);
+ vec_validate (fm->ipv4_buffers_per_worker, num_threads - 1);
+ vec_validate (fm->l2_buffers_per_worker, num_threads - 1);
+ vec_validate (fm->ipv4_frames_per_worker, num_threads - 1);
+ vec_validate (fm->l2_frames_per_worker, num_threads - 1);
+ vec_validate (fm->ipv4_next_record_offset_per_worker, num_threads - 1);
+ vec_validate (fm->l2_next_record_offset_per_worker, num_threads - 1);
/* Set up time reference pair */
fm->vlib_time_0 = vlib_time_now (vm);