summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/config.c1
-rw-r--r--vnet/vnet/interface.c26
-rw-r--r--vnet/vnet/interface.h2
-rw-r--r--vnet/vnet/interface_output.c99
4 files changed, 126 insertions, 2 deletions
diff --git a/vnet/vnet/config.c b/vnet/vnet/config.c
index be48df69a84..03189d77cd5 100644
--- a/vnet/vnet/config.c
+++ b/vnet/vnet/config.c
@@ -174,7 +174,6 @@ vnet_config_init (vlib_main_t * vm,
STRUCT_SIZE_OF (vnet_config_t, config_string_vector[0]),
sizeof (uword));
- ASSERT (n_start_node_names >= 1);
ASSERT (n_feature_node_names >= 1);
vec_resize (cm->start_node_indices, n_start_node_names);
diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c
index 6e3d7f291b7..8c19ca7d9a3 100644
--- a/vnet/vnet/interface.c
+++ b/vnet/vnet/interface.c
@@ -687,7 +687,9 @@ vnet_register_interface (vnet_main_t * vnm,
vnet_hw_interface_class_t *hw_class =
vnet_get_hw_interface_class (vnm, hw_class_index);
vlib_main_t *vm = vnm->vlib_main;
- u32 hw_index;
+ vnet_feature_config_main_t *fcm;
+ vnet_config_main_t *cm;
+ u32 hw_index, i;
char *tx_node_name, *output_node_name;
pool_get (im->hw_interfaces, hw);
@@ -832,6 +834,28 @@ vnet_register_interface (vnet_main_t * vnm,
vlib_node_add_next_with_slot (vm, hw->output_node_index,
hw->tx_node_index,
VNET_INTERFACE_OUTPUT_NEXT_TX);
+
+ /* add interface to the list of "output-interface" feature arc start nodes
+ and clone nexts from 1st interface if it exists */
+ fcm = vnet_feature_get_config_main (im->output_feature_arc_index);
+ cm = &fcm->config_main;
+ i = vec_len (cm->start_node_indices);
+ vec_validate (cm->start_node_indices, i);
+ cm->start_node_indices[i] = hw->output_node_index;
+ if (hw_index)
+ {
+ /* copy nexts from 1st interface */
+ vnet_hw_interface_t *first_hw;
+ vlib_node_t *first_node;
+
+ first_hw = vnet_get_hw_interface (vnm, /* hw_if_index */ 0);
+ first_node = vlib_get_node (vm, first_hw->output_node_index);
+
+ /* 1st 2 nexts are already added above */
+ for (i = 2; i < vec_len (first_node->next_nodes); i++)
+ vlib_node_add_next_with_slot (vm, hw->output_node_index,
+ first_node->next_nodes[i], i);
+ }
}
setup_output_node (vm, hw->output_node_index, hw_class);
diff --git a/vnet/vnet/interface.h b/vnet/vnet/interface.h
index 412574d16a2..d3076a55679 100644
--- a/vnet/vnet/interface.h
+++ b/vnet/vnet/interface.h
@@ -621,6 +621,8 @@ typedef struct
u32 pcap_pkts_to_capture;
uword *pcap_drop_filter_hash;
+ /* feature_arc_index */
+ u8 output_feature_arc_index;
} vnet_interface_main_t;
static inline void
diff --git a/vnet/vnet/interface_output.c b/vnet/vnet/interface_output.c
index 46e8a98c75d..502fa7b4dfd 100644
--- a/vnet/vnet/interface_output.c
+++ b/vnet/vnet/interface_output.c
@@ -38,6 +38,7 @@
*/
#include <vnet/vnet.h>
+#include <vnet/feature/feature.h>
typedef struct
{
@@ -430,6 +431,8 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
u32 cpu_index = vm->cpu_index;
vnet_interface_main_t *im = &vnm->interface_main;
u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
+ u32 current_config_index = ~0;
+ u8 arc = im->output_feature_arc_index;
n_buffers = frame->n_vectors;
@@ -472,6 +475,17 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
n_bytes = 0;
n_packets = 0;
+ /* interface-output feature arc handling */
+ if (PREDICT_FALSE (vnet_have_features (arc, rt->sw_if_index)))
+ {
+ vnet_feature_config_main_t *fcm;
+ fcm = vnet_feature_get_config_main (arc);
+ current_config_index = vnet_get_feature_config_index (arc,
+ rt->sw_if_index);
+ vnet_get_config_data (&fcm->config_main, &current_config_index,
+ &next_index, 0);
+ }
+
while (from < from_end)
{
/* Get new next frame since previous incomplete frame may have less
@@ -512,6 +526,14 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
n_bytes += n_bytes_b0 + n_bytes_b1;
n_packets += 2;
+ if (PREDICT_FALSE (current_config_index != ~0))
+ {
+ b0->feature_arc_index = arc;
+ b1->feature_arc_index = arc;
+ b0->current_config_index = current_config_index;
+ b1->current_config_index = current_config_index;
+ }
+
if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
{
/* update vlan subif tx counts, if required */
@@ -555,6 +577,12 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
n_bytes += n_bytes_b0;
n_packets += 1;
+ if (PREDICT_FALSE (current_config_index != ~0))
+ {
+ b0->feature_arc_index = arc;
+ b0->current_config_index = current_config_index;
+ }
+
if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
{
@@ -1134,6 +1162,77 @@ VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node,static) = {
VLIB_NODE_FUNCTION_MULTIARCH (vnet_per_buffer_interface_output_node,
vnet_per_buffer_interface_output);
+static uword
+interface_tx_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ u32 last_sw_if_index = ~0;
+ vlib_frame_t *to_frame = 0;
+ vnet_hw_interface_t *hw = 0;
+ u32 *from, *to_next = 0;
+ u32 n_left_from;
+
+ from = vlib_frame_vector_args (from_frame);
+ n_left_from = from_frame->n_vectors;
+ while (n_left_from > 0)
+ {
+ u32 bi0;
+ vlib_buffer_t *b0;
+ u32 sw_if_index0;
+
+ bi0 = from[0];
+ from++;
+ n_left_from--;
+ b0 = vlib_get_buffer (vm, bi0);
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+
+ if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
+ {
+ if (to_frame)
+ {
+ hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
+ vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
+ }
+ last_sw_if_index = sw_if_index0;
+ hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+ to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
+ to_next = vlib_frame_vector_args (to_frame);
+ }
+
+ to_next[0] = bi0;
+ to_next++;
+ to_frame->n_vectors++;
+ }
+ vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
+ return from_frame->n_vectors;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (interface_tx, static) = {
+ .function = interface_tx_node_fn,
+ .name = "interface-tx",
+ .vector_size = sizeof (u32),
+ .n_next_nodes = 1,
+ .next_nodes = {
+ [0] = "error-drop",
+ },
+};
+
+VNET_FEATURE_ARC_INIT (interface_output, static) =
+{
+ .arc_name = "interface-output",
+ .start_nodes = VNET_FEATURES (0),
+ .arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (interface_tx, static) = {
+ .arc_name = "interface-output",
+ .node_name = "interface-tx",
+ .runs_before = 0,
+};
+/* *INDENT-ON* */
+
clib_error_t *
vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm,
u32 hw_if_index,