summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/buffer.h2
-rw-r--r--vnet/vnet/interface_output.c59
2 files changed, 42 insertions, 19 deletions
diff --git a/vnet/vnet/buffer.h b/vnet/vnet/buffer.h
index 7153f3541b1..050642276b5 100644
--- a/vnet/vnet/buffer.h
+++ b/vnet/vnet/buffer.h
@@ -61,6 +61,8 @@
#define ETH_BUFFER_VLAN_BITS (ETH_BUFFER_VLAN_1_DEEP | \
ETH_BUFFER_VLAN_2_DEEP)
+#define LOG2_BUFFER_OUTPUT_FEAT_DONE LOG2_VLIB_BUFFER_FLAG_USER(5)
+#define BUFFER_OUTPUT_FEAT_DONE (1 << LOG2_BUFFER_OUTPUT_FEAT_DONE)
#define foreach_buffer_opaque_union_subtype \
_(ethernet) \
diff --git a/vnet/vnet/interface_output.c b/vnet/vnet/interface_output.c
index a8dd451fe82..92c1380a6fc 100644
--- a/vnet/vnet/interface_output.c
+++ b/vnet/vnet/interface_output.c
@@ -393,11 +393,11 @@ 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)
+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 +465,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,19 +494,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 &&
- vnet_buffer(b0)->output_features.bitmap != (1 << INTF_OUTPUT_FEAT_DONE)))
+ 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))
@@ -520,18 +518,16 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
}
}
- if (PREDICT_FALSE(si->output_feature_bitmap &&
- vnet_buffer(b1)->output_features.bitmap != (1 << INTF_OUTPUT_FEAT_DONE)))
+ 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 */
@@ -546,7 +542,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)
@@ -572,10 +570,10 @@ 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 &&
- vnet_buffer(b0)->output_features.bitmap != (1 << INTF_OUTPUT_FEAT_DONE)))
+ 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);
@@ -613,6 +611,29 @@ 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);
+}
/* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
static uword