diff options
-rw-r--r-- | vnet/vnet/config.c | 1 | ||||
-rw-r--r-- | vnet/vnet/interface.c | 26 | ||||
-rw-r--r-- | vnet/vnet/interface.h | 2 | ||||
-rw-r--r-- | vnet/vnet/interface_output.c | 99 |
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, ¤t_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, |