aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/flowprobe/node.c
diff options
context:
space:
mode:
authorAlexander Chernavin <achernavin@netgate.com>2022-05-06 11:35:59 +0000
committerOle Tr�an <otroan@employees.org>2022-05-13 07:34:41 +0000
commit6f5ddf3461906bbc88f679882744afc74a81cae1 (patch)
tree27a3f0686ddf0fb7efdfd3ac1aa2cefb5fa86153 /src/plugins/flowprobe/node.c
parent0891b6aa449cca525b61d0cc23759b2efcd158dc (diff)
flowprobe: add support for reporting on inbound packets
Type: feature Currently, the plugin supports only IPFIX flow record generation for outbound packets. With this change: - add a new API message for enabling the feature on an interface that accepts direction (rx, tx, both); - update existing debug command for feature enabling to accept direction; - update existing debug command for showing currently enabled feature on interfaces to display direction; - update templates to include a direction field; - generate flow records on the specified direction and data path; - report direction in flow data; - update tests to use the new API; - add tests for inbound flows. Change-Id: I121fd904b38408641036ebeea848df7a4e5e0b30 Signed-off-by: Alexander Chernavin <achernavin@netgate.com>
Diffstat (limited to 'src/plugins/flowprobe/node.c')
-rw-r--r--src/plugins/flowprobe/node.c172
1 files changed, 125 insertions, 47 deletions
diff --git a/src/plugins/flowprobe/node.c b/src/plugins/flowprobe/node.c
index 928d75225d8..e9fa4b89665 100644
--- a/src/plugins/flowprobe/node.c
+++ b/src/plugins/flowprobe/node.c
@@ -99,9 +99,12 @@ format_flowprobe_trace (u8 * s, va_list * args)
return s;
}
-vlib_node_registration_t flowprobe_ip4_node;
-vlib_node_registration_t flowprobe_ip6_node;
-vlib_node_registration_t flowprobe_l2_node;
+vlib_node_registration_t flowprobe_input_ip4_node;
+vlib_node_registration_t flowprobe_input_ip6_node;
+vlib_node_registration_t flowprobe_input_l2_node;
+vlib_node_registration_t flowprobe_output_ip4_node;
+vlib_node_registration_t flowprobe_output_ip6_node;
+vlib_node_registration_t flowprobe_output_l2_node;
/* No counters at the moment */
#define foreach_flowprobe_error \
@@ -167,6 +170,11 @@ flowprobe_common_add (vlib_buffer_t * to_b, flowprobe_entry_t * e, u16 offset)
clib_memcpy_fast (to_b->data + offset, &tx_if, sizeof (tx_if));
offset += sizeof (tx_if);
+ /* Flow direction
+ 0x00: ingress flow
+ 0x01: egress flow */
+ to_b->data[offset++] = (e->key.direction == FLOW_DIRECTION_TX);
+
/* packet delta count */
u64 packetdelta = clib_host_to_net_u64 (e->packetcount);
clib_memcpy_fast (to_b->data + offset, &packetdelta, sizeof (u64));
@@ -358,22 +366,27 @@ flowprobe_create (u32 my_cpu_number, flowprobe_key_t * k, u32 * poolindex)
}
static inline void
-add_to_flow_record_state (vlib_main_t * vm, vlib_node_runtime_t * node,
- flowprobe_main_t * fm, vlib_buffer_t * b,
+add_to_flow_record_state (vlib_main_t *vm, vlib_node_runtime_t *node,
+ flowprobe_main_t *fm, vlib_buffer_t *b,
timestamp_nsec_t timestamp, u16 length,
- flowprobe_variant_t which, flowprobe_trace_t * t)
+ flowprobe_variant_t which,
+ flowprobe_direction_t direction,
+ flowprobe_trace_t *t)
{
if (fm->disabled)
return;
+ ASSERT (direction == FLOW_DIRECTION_RX || direction == FLOW_DIRECTION_TX);
+
u32 my_cpu_number = vm->thread_index;
u16 octets = 0;
flowprobe_record_t flags = fm->context[which].flags;
bool collect_ip4 = false, collect_ip6 = false;
ASSERT (b);
- ethernet_header_t *eth = vlib_buffer_get_current (b);
+ ethernet_header_t *eth = ethernet_buffer_get_header (b);
u16 ethertype = clib_net_to_host_u16 (eth->type);
+ u16 l2_hdr_sz = sizeof (ethernet_header_t);
/* *INDENT-OFF* */
flowprobe_key_t k = {};
/* *INDENT-ON* */
@@ -393,6 +406,7 @@ add_to_flow_record_state (vlib_main_t * vm, vlib_node_runtime_t * node,
k.tx_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
k.which = which;
+ k.direction = direction;
if (flags & FLOW_RECORD_L2)
{
@@ -409,12 +423,13 @@ add_to_flow_record_state (vlib_main_t * vm, vlib_node_runtime_t * node,
while (clib_net_to_host_u16 (ethv->type) == ETHERNET_TYPE_VLAN)
{
ethv++;
+ l2_hdr_sz += sizeof (ethernet_vlan_header_tv_t);
}
k.ethertype = ethertype = clib_net_to_host_u16 ((ethv)->type);
}
if (collect_ip6 && ethertype == ETHERNET_TYPE_IP6)
{
- ip6 = (ip6_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset);
+ ip6 = (ip6_header_t *) (b->data + l2_hdr_sz);
if (flags & FLOW_RECORD_L3)
{
k.src_address.as_u64[0] = ip6->src_address.as_u64[0];
@@ -433,7 +448,7 @@ add_to_flow_record_state (vlib_main_t * vm, vlib_node_runtime_t * node,
}
if (collect_ip4 && ethertype == ETHERNET_TYPE_IP4)
{
- ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset);
+ ip4 = (ip4_header_t *) (b->data + l2_hdr_sz);
if (flags & FLOW_RECORD_L3)
{
k.src_address.ip4.as_u32 = ip4->src_address.as_u32;
@@ -630,7 +645,7 @@ flowprobe_export_send (vlib_main_t * vm, vlib_buffer_t * b0,
}
vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
- vlib_node_increment_counter (vm, flowprobe_l2_node.index,
+ vlib_node_increment_counter (vm, flowprobe_output_l2_node.index,
FLOWPROBE_ERROR_EXPORTED_PACKETS, 1);
fm->context[which].frames_per_worker[my_cpu_number] = 0;
@@ -656,7 +671,7 @@ flowprobe_get_buffer (vlib_main_t * vm, flowprobe_variant_t which)
{
if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
{
- vlib_node_increment_counter (vm, flowprobe_l2_node.index,
+ vlib_node_increment_counter (vm, flowprobe_output_l2_node.index,
FLOWPROBE_ERROR_BUFFER, 1);
return 0;
}
@@ -730,9 +745,9 @@ flowprobe_export_entry (vlib_main_t * vm, flowprobe_entry_t * e)
}
uword
-flowprobe_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame,
- flowprobe_variant_t which)
+flowprobe_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, flowprobe_variant_t which,
+ flowprobe_direction_t direction)
{
u32 n_left_from, *from, *to_next;
flowprobe_next_t next_index;
@@ -792,20 +807,22 @@ flowprobe_node_fn (vlib_main_t * vm,
u16 ethertype0 = clib_net_to_host_u16 (eh0->type);
if (PREDICT_TRUE ((b0->flags & VNET_BUFFER_F_FLOW_REPORT) == 0))
- add_to_flow_record_state (vm, node, fm, b0, timestamp, len0,
- flowprobe_get_variant
- (which, fm->context[which].flags,
- ethertype0), 0);
+ add_to_flow_record_state (
+ vm, node, fm, b0, timestamp, len0,
+ flowprobe_get_variant (which, fm->context[which].flags,
+ ethertype0),
+ direction, 0);
len1 = vlib_buffer_length_in_chain (vm, b1);
ethernet_header_t *eh1 = vlib_buffer_get_current (b1);
u16 ethertype1 = clib_net_to_host_u16 (eh1->type);
if (PREDICT_TRUE ((b1->flags & VNET_BUFFER_F_FLOW_REPORT) == 0))
- add_to_flow_record_state (vm, node, fm, b1, timestamp, len1,
- flowprobe_get_variant
- (which, fm->context[which].flags,
- ethertype1), 0);
+ add_to_flow_record_state (
+ vm, node, fm, b1, timestamp, len1,
+ flowprobe_get_variant (which, fm->context[which].flags,
+ ethertype1),
+ direction, 0);
/* verify speculative enqueues, maybe switch current next frame */
vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -843,10 +860,11 @@ flowprobe_node_fn (vlib_main_t * vm,
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
t = vlib_add_trace (vm, node, b0, sizeof (*t));
- add_to_flow_record_state (vm, node, fm, b0, timestamp, len0,
- flowprobe_get_variant
- (which, fm->context[which].flags,
- ethertype0), t);
+ add_to_flow_record_state (
+ vm, node, fm, b0, timestamp, len0,
+ flowprobe_get_variant (which, fm->context[which].flags,
+ ethertype0),
+ direction, t);
}
/* verify speculative enqueue, maybe switch current next frame */
@@ -861,24 +879,51 @@ flowprobe_node_fn (vlib_main_t * vm,
}
static uword
-flowprobe_ip4_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+flowprobe_input_ip4_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP4,
+ FLOW_DIRECTION_RX);
+}
+
+static uword
+flowprobe_input_ip6_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP6,
+ FLOW_DIRECTION_RX);
+}
+
+static uword
+flowprobe_input_l2_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_L2,
+ FLOW_DIRECTION_RX);
+}
+
+static uword
+flowprobe_output_ip4_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
{
- return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP4);
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP4,
+ FLOW_DIRECTION_TX);
}
static uword
-flowprobe_ip6_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+flowprobe_output_ip6_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
{
- return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP6);
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_IP6,
+ FLOW_DIRECTION_TX);
}
static uword
-flowprobe_l2_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+flowprobe_output_l2_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
{
- return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_L2);
+ return flowprobe_node_fn (vm, node, frame, FLOW_VARIANT_L2,
+ FLOW_DIRECTION_TX);
}
static inline void
@@ -1012,35 +1057,68 @@ flowprobe_walker_process (vlib_main_t * vm,
}
/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (flowprobe_ip4_node) = {
- .function = flowprobe_ip4_node_fn,
- .name = "flowprobe-ip4",
+VLIB_REGISTER_NODE (flowprobe_input_ip4_node) = {
+ .function = flowprobe_input_ip4_node_fn,
+ .name = "flowprobe-input-ip4",
+ .vector_size = sizeof (u32),
+ .format_trace = format_flowprobe_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
+ .error_strings = flowprobe_error_strings,
+ .n_next_nodes = FLOWPROBE_N_NEXT,
+ .next_nodes = FLOWPROBE_NEXT_NODES,
+};
+VLIB_REGISTER_NODE (flowprobe_input_ip6_node) = {
+ .function = flowprobe_input_ip6_node_fn,
+ .name = "flowprobe-input-ip6",
+ .vector_size = sizeof (u32),
+ .format_trace = format_flowprobe_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
+ .error_strings = flowprobe_error_strings,
+ .n_next_nodes = FLOWPROBE_N_NEXT,
+ .next_nodes = FLOWPROBE_NEXT_NODES,
+};
+VLIB_REGISTER_NODE (flowprobe_input_l2_node) = {
+ .function = flowprobe_input_l2_node_fn,
+ .name = "flowprobe-input-l2",
+ .vector_size = sizeof (u32),
+ .format_trace = format_flowprobe_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
+ .error_strings = flowprobe_error_strings,
+ .n_next_nodes = FLOWPROBE_N_NEXT,
+ .next_nodes = FLOWPROBE_NEXT_NODES,
+};
+VLIB_REGISTER_NODE (flowprobe_output_ip4_node) = {
+ .function = flowprobe_output_ip4_node_fn,
+ .name = "flowprobe-output-ip4",
.vector_size = sizeof (u32),
.format_trace = format_flowprobe_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(flowprobe_error_strings),
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
.error_strings = flowprobe_error_strings,
.n_next_nodes = FLOWPROBE_N_NEXT,
.next_nodes = FLOWPROBE_NEXT_NODES,
};
-VLIB_REGISTER_NODE (flowprobe_ip6_node) = {
- .function = flowprobe_ip6_node_fn,
- .name = "flowprobe-ip6",
+VLIB_REGISTER_NODE (flowprobe_output_ip6_node) = {
+ .function = flowprobe_output_ip6_node_fn,
+ .name = "flowprobe-output-ip6",
.vector_size = sizeof (u32),
.format_trace = format_flowprobe_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(flowprobe_error_strings),
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
.error_strings = flowprobe_error_strings,
.n_next_nodes = FLOWPROBE_N_NEXT,
.next_nodes = FLOWPROBE_NEXT_NODES,
};
-VLIB_REGISTER_NODE (flowprobe_l2_node) = {
- .function = flowprobe_l2_node_fn,
- .name = "flowprobe-l2",
+VLIB_REGISTER_NODE (flowprobe_output_l2_node) = {
+ .function = flowprobe_output_l2_node_fn,
+ .name = "flowprobe-output-l2",
.vector_size = sizeof (u32),
.format_trace = format_flowprobe_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(flowprobe_error_strings),
+ .n_errors = ARRAY_LEN (flowprobe_error_strings),
.error_strings = flowprobe_error_strings,
.n_next_nodes = FLOWPROBE_N_NEXT,
.next_nodes = FLOWPROBE_NEXT_NODES,