diff options
author | Andrew Yourtchenko <ayourtch@gmail.com> | 2017-03-03 13:11:30 +0000 |
---|---|---|
committer | John Lo <loj@cisco.com> | 2017-03-03 18:51:16 +0000 |
commit | cc40565b6eb3136d42fd67b57e4f0e01a5970a72 (patch) | |
tree | 25c0d5301f7befbcdcf4898ec63b6c470c6cf403 /src/vnet/l2/l2_output.h | |
parent | dfbee41b16541b51eb8f7f4d8a831ef9407fb419 (diff) |
VPP-651: Ensure sw_if_index to node mapping for L2 output path is only done via l2output_main.next_nodes
Before this commit, several output features that happen to be the
last in the list of features to be executed, send the packets directly
to <interfaceName>-output. To do this, they use l2_output_dispatch,
which builds a list of sw_if_index to next index mappings.
When interfaces are deleted and the new interfaces are created,
these mappings become stale, and cause the packets being sent to wrong
interface output nodes.
This patch (thanks John Lo for the brilliant idea!) adds a feature node "output",
whose sole purpose is dispatching the packets to the correct interface output
nodes. To do that, it uses the l2output_main.next_nodes, which is already
taken care of for the case of the sw_if_index reuse, so this makes the dependent
features all work correctly.
Since this changes the packet path, for the features that were always the last ones
it has triggered a side problem of the output feat_next_node_index not being properly
initalized. These two users are l2-output-classify node and the output nodes belonging
to the acl-plugin.
For the first one the less invasive fix is just to initialize that field.
For the acl-plugin nodes, rewrite the affected part of the code to use
feat_bitmap_get_next_node_index since this is essentially what the conditional
in l2_output_dispatch does, and fix the compiler warnings generated.
This fix was first made in stable/1701 under commit e7dcee4027854b0ad076101471afdfff67eb9011.
Change-Id: I32e876ab1e1d498cf0854c19c6318dcf59a93805
Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
Diffstat (limited to 'src/vnet/l2/l2_output.h')
-rw-r--r-- | src/vnet/l2/l2_output.h | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/src/vnet/l2/l2_output.h b/src/vnet/l2/l2_output.h index c683b1ade73..9597205caed 100644 --- a/src/vnet/l2/l2_output.h +++ b/src/vnet/l2/l2_output.h @@ -94,6 +94,7 @@ l2output_main_t l2output_main; /* Mappings from feature ID to graph node name */ #define foreach_l2output_feat \ + _(OUTPUT, "interface-output") \ _(SPAN, "feature-bitmap-drop") \ _(CFM, "feature-bitmap-drop") \ _(QOS, "feature-bitmap-drop") \ @@ -217,9 +218,21 @@ l2_output_dispatch (vlib_main_t * vlib_main, vlib_buffer_t * b0, u32 sw_if_index, u32 feature_bitmap, u32 * next0) { - if (feature_bitmap) + /* + * The output feature bitmap always have at least the output feature bit set + * for a normal L2 interface (or all 0's if the interface is changed from L2 + * to L3 mode). So if next_nodes specified is that from the l2-output node and + * the bitmap is all clear except output feature bit, we know there is no more + * feature and will fall through to output packet. If next_nodes is from a L2 + * output feature node (and not l2-output), we always want to get the node for + * the next L2 output feature, including the last feature being interface- + * output node to output packet. + */ + if ((next_nodes != &l2output_main.next_nodes) + || ((feature_bitmap & ~L2OUTPUT_FEAT_OUTPUT) != 0)) { /* There are some features to execute */ + ASSERT (feature_bitmap != 0); /* Save bitmap for the next feature graph nodes */ vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap; |