aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/interface.c4
-rw-r--r--vnet/vnet/interface_funcs.h10
-rw-r--r--vnet/vnet/interface_output.c62
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