X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Finterface_output.c;h=475b0b935af02c78bbfddd8185256bc57ebce67a;hb=3a2a1c47bc1f319d1f46abd2a364b3cf82404405;hp=46e8a98c75d88be07faa77d114678f3e6f4c1e2f;hpb=177bbdcd8fa4e7621c5bdd3afd8c6e74b603e096;p=vpp.git diff --git a/vnet/vnet/interface_output.c b/vnet/vnet/interface_output.c index 46e8a98c75d..475b0b935af 100644 --- a/vnet/vnet/interface_output.c +++ b/vnet/vnet/interface_output.c @@ -38,6 +38,7 @@ */ #include +#include typedef struct { @@ -228,8 +229,9 @@ incr_output_stats (vnet_main_t * vnm, /* Interface output functions. */ uword -vnet_interface_output_node (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) +vnet_interface_output_node_flatten (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { vnet_main_t *vnm = vnet_get_main (); vnet_interface_output_runtime_t *rt = (void *) node->runtime_data; @@ -412,13 +414,12 @@ vnet_interface_output_node (vlib_main_t * vm, return n_buffers; } -VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node); -CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node); +VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node_flatten); +CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node_flatten); uword -vnet_interface_output_node_no_flatten (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +vnet_interface_output_node (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) { vnet_main_t *vnm = vnet_get_main (); vnet_interface_output_runtime_t *rt = (void *) node->runtime_data; @@ -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)) { @@ -576,8 +604,8 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, return n_buffers; } -VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node_no_flatten); -CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node_no_flatten); +VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node); +CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node); /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */ static uword @@ -1134,6 +1162,84 @@ 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), + .end_node = "interface-tx", + .arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index, +}; + +VNET_FEATURE_INIT (span_tx, static) = { + .arc_name = "interface-output", + .node_name = "span-output", + .runs_before = VNET_FEATURES ("interface-tx"), +}; + +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,