diff options
-rw-r--r-- | vnet/vnet/interface.c | 4 | ||||
-rw-r--r-- | vnet/vnet/interface_funcs.h | 10 | ||||
-rw-r--r-- | vnet/vnet/interface_output.c | 62 |
3 files changed, 47 insertions, 29 deletions
diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c index d36f7811d90..2fb93748b1e 100644 --- a/vnet/vnet/interface.c +++ b/vnet/vnet/interface.c @@ -689,8 +689,8 @@ vnet_register_interface (vnet_main_t * vnm, r.flags = 0; r.name = output_node_name; r.function = dev_class->no_flatten_output_chains ? - vnet_interface_output_node_no_flatten : - vnet_interface_output_node; + vnet_interface_output_node_no_flatten_multiarch_select() : + vnet_interface_output_node_multiarch_select() ; r.format_trace = format_vnet_interface_output_trace; { diff --git a/vnet/vnet/interface_funcs.h b/vnet/vnet/interface_funcs.h index 9d6fe48e23c..7832afcc7c4 100644 --- a/vnet/vnet/interface_funcs.h +++ b/vnet/vnet/interface_funcs.h @@ -179,14 +179,8 @@ typedef struct { } vnet_interface_output_runtime_t; /* Interface output functions. */ -uword -vnet_interface_output_node (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame); -uword -vnet_interface_output_node_no_flatten (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame); +void * vnet_interface_output_node_multiarch_select (void); +void * vnet_interface_output_node_no_flatten_multiarch_select (void); word vnet_sw_interface_compare (vnet_main_t * vnm, uword sw_if_index0, uword sw_if_index1); word vnet_hw_interface_compare (vnet_main_t * vnm, uword hw_if_index0, uword hw_if_index1); diff --git a/vnet/vnet/interface_output.c b/vnet/vnet/interface_output.c index 9f9fb707297..b19ca7c50c3 100644 --- a/vnet/vnet/interface_output.c +++ b/vnet/vnet/interface_output.c @@ -393,11 +393,14 @@ vnet_interface_output_node (vlib_main_t * vm, return n_buffers; } - -uword -vnet_interface_output_node_no_flatten (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node) +CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node) + +always_inline uword +vnet_interface_output_node_no_flatten_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, + int with_features) { vnet_main_t * vnm = vnet_get_main(); vnet_interface_output_runtime_t * rt = (void *) node->runtime_data; @@ -465,6 +468,7 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, u32 bi0, bi1; vlib_buffer_t * b0, * b1; u32 tx_swif0, tx_swif1; + u32 next0, next1; /* Prefetch next iteration. */ vlib_prefetch_buffer_with_index (vm, from[2], LOAD); @@ -493,20 +497,16 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, n_bytes += n_bytes_b0 + n_bytes_b1; n_packets += 2; - - if (PREDICT_FALSE(si->output_feature_bitmap && - ((b0->flags & BUFFER_OUTPUT_FEAT_DONE) == 0))) + if (with_features) { - u32 next0; b0->flags |= BUFFER_OUTPUT_FEAT_DONE; vnet_buffer(b0)->output_features.bitmap = si->output_feature_bitmap; count_trailing_zeros(next0, vnet_buffer(b0)->output_features.bitmap); vnet_buffer(b0)->output_features.bitmap &= ~(1 << next0); - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_tx, - n_left_to_tx, bi0, next0); } else { + next0 = VNET_INTERFACE_OUTPUT_NEXT_TX; vnet_buffer(b0)->output_features.bitmap = 0; if (PREDICT_FALSE(tx_swif0 != rt->sw_if_index)) @@ -521,19 +521,16 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, } } - if (PREDICT_FALSE(si->output_feature_bitmap && - ((b1->flags & BUFFER_OUTPUT_FEAT_DONE) == 0))) + if (with_features) { - u32 next1; b1->flags |= BUFFER_OUTPUT_FEAT_DONE; vnet_buffer(b1)->output_features.bitmap = si->output_feature_bitmap; count_trailing_zeros(next1, vnet_buffer(b1)->output_features.bitmap); vnet_buffer(b1)->output_features.bitmap &= ~(1 << next1); - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_tx, - n_left_to_tx, bi1, next1); } else { + next1 = VNET_INTERFACE_OUTPUT_NEXT_TX; vnet_buffer(b1)->output_features.bitmap = 0; /* update vlan subif tx counts, if required */ @@ -548,7 +545,9 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, n_bytes_b1); } } - + if (with_features) + vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_tx, + n_left_to_tx, bi0, bi1, next0, next1); } while (from + 1 <= from_end && n_left_to_tx >= 1) @@ -574,8 +573,7 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, n_bytes += n_bytes_b0; n_packets += 1; - if (PREDICT_FALSE(si->output_feature_bitmap && - ((b0->flags & BUFFER_OUTPUT_FEAT_DONE) == 0))) + if (with_features) { u32 next0; b0->flags |= BUFFER_OUTPUT_FEAT_DONE; @@ -616,6 +614,32 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm, return n_buffers; } +uword +vnet_interface_output_node_no_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; + vnet_sw_interface_t * si; + si = vnet_get_sw_interface (vnm, rt->sw_if_index); + + if (PREDICT_FALSE(si->output_feature_bitmap)) + { + /* if first pakcet in the frame have BUFFER_OUTPUT_FEAT_DONE flag set + then whole frame is arriving from feature node */ + + u32 * from = vlib_frame_args (frame); + vlib_buffer_t * b = vlib_get_buffer (vm, from[0]); + + if ((b->flags & BUFFER_OUTPUT_FEAT_DONE) == 0) + return vnet_interface_output_node_no_flatten_inline (vm, node, frame, 1); + } + return vnet_interface_output_node_no_flatten_inline (vm, node, frame, 0); +} + +VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node_no_flatten) +CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node_no_flatten) /* Use buffer's sw_if_index[VNET_TX] to choose output interface. */ static uword |