From 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Dec 2016 23:05:39 +0100 Subject: Reorganize source tree to use single autotools instance Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion --- src/vnet/l2/l2_input_vtr.c | 401 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 src/vnet/l2/l2_input_vtr.c (limited to 'src/vnet/l2/l2_input_vtr.c') diff --git a/src/vnet/l2/l2_input_vtr.c b/src/vnet/l2/l2_input_vtr.c new file mode 100644 index 00000000..60a39631 --- /dev/null +++ b/src/vnet/l2/l2_input_vtr.c @@ -0,0 +1,401 @@ +/* + * l2_input_vtr.c : layer 2 input vlan tag rewrite processing + * + * Copyright (c) 2013 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +typedef struct +{ + /* per-pkt trace data */ + u8 src[6]; + u8 dst[6]; + u8 raw[12]; /* raw data (vlans) */ + u32 sw_if_index; +} l2_invtr_trace_t; + +/* packet trace format function */ +static u8 * +format_l2_invtr_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + l2_invtr_trace_t *t = va_arg (*args, l2_invtr_trace_t *); + + s = format (s, "l2-input-vtr: sw_if_index %d dst %U src %U data " + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + t->sw_if_index, + format_ethernet_address, t->dst, + format_ethernet_address, t->src, + t->raw[0], t->raw[1], t->raw[2], t->raw[3], t->raw[4], + t->raw[5], t->raw[6], t->raw[7], t->raw[8], t->raw[9], + t->raw[10], t->raw[11]); + return s; +} + +l2_invtr_main_t l2_invtr_main; + +static vlib_node_registration_t l2_invtr_node; + +#define foreach_l2_invtr_error \ +_(L2_INVTR, "L2 inverter packets") \ +_(DROP, "L2 input tag rewrite drops") + +typedef enum +{ +#define _(sym,str) L2_INVTR_ERROR_##sym, + foreach_l2_invtr_error +#undef _ + L2_INVTR_N_ERROR, +} l2_invtr_error_t; + +static char *l2_invtr_error_strings[] = { +#define _(sym,string) string, + foreach_l2_invtr_error +#undef _ +}; + +typedef enum +{ + L2_INVTR_NEXT_DROP, + L2_INVTR_N_NEXT, +} l2_invtr_next_t; + + +static uword +l2_invtr_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next; + l2_invtr_next_t next_index; + l2_invtr_main_t *msm = &l2_invtr_main; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; /* number of packets to process */ + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + /* get space to enqueue frame to graph node "next_index" */ + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from >= 6 && n_left_to_next >= 2) + { + u32 bi0, bi1; + vlib_buffer_t *b0, *b1; + u32 next0, next1; + u32 sw_if_index0, sw_if_index1; + u32 feature_bitmap0, feature_bitmap1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3, *p4, *p5; + u32 sw_if_index2, sw_if_index3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + p4 = vlib_get_buffer (vm, from[4]); + p5 = vlib_get_buffer (vm, from[5]); + + /* Prefetch the buffer header and packet for the N+2 loop iteration */ + vlib_prefetch_buffer_header (p4, LOAD); + vlib_prefetch_buffer_header (p5, LOAD); + + CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE); + + /* + * Prefetch the input config for the N+1 loop iteration + * This depends on the buffer header above + */ + sw_if_index2 = vnet_buffer (p2)->sw_if_index[VLIB_RX]; + sw_if_index3 = vnet_buffer (p3)->sw_if_index[VLIB_RX]; + CLIB_PREFETCH (vec_elt_at_index + (l2output_main.configs, sw_if_index2), + CLIB_CACHE_LINE_BYTES, LOAD); + CLIB_PREFETCH (vec_elt_at_index + (l2output_main.configs, sw_if_index3), + CLIB_CACHE_LINE_BYTES, LOAD); + } + + /* speculatively enqueue b0 and b1 to the current next frame */ + /* bi is "buffer index", b is pointer to the buffer */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + /* RX interface handles */ + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; + + /* process 2 packets */ + + /* Remove ourself from the feature bitmap */ + feature_bitmap0 = + vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; + feature_bitmap1 = + vnet_buffer (b1)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; + + /* save for next feature graph nodes */ + vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; + vnet_buffer (b1)->l2.feature_bitmap = feature_bitmap1; + + /* Determine the next node */ + next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, + feature_bitmap0); + next1 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, + feature_bitmap1); + + l2_output_config_t *config0; + l2_output_config_t *config1; + config0 = vec_elt_at_index (l2output_main.configs, sw_if_index0); + config1 = vec_elt_at_index (l2output_main.configs, sw_if_index1); + + if (PREDICT_FALSE (config0->out_vtr_flag)) + { + if (config0->output_vtr.push_and_pop_bytes) + { + /* perform the tag rewrite on two packets */ + if (l2_vtr_process + (b0, + &(vec_elt_at_index + (l2output_main.configs, sw_if_index0)->input_vtr))) + { + /* Drop packet */ + next0 = L2_INVTR_NEXT_DROP; + b0->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + else if (config0->output_pbb_vtr.push_and_pop_bytes) + { + if (l2_pbb_process (b0, &(config0->input_pbb_vtr))) + { + /* Drop packet */ + next0 = L2_INVTR_NEXT_DROP; + b0->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + } + if (PREDICT_FALSE (config1->out_vtr_flag)) + { + if (config1->output_vtr.push_and_pop_bytes) + { + if (l2_vtr_process + (b1, + &(vec_elt_at_index + (l2output_main.configs, sw_if_index1)->input_vtr))) + { + /* Drop packet */ + next1 = L2_INVTR_NEXT_DROP; + b1->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + else if (config1->output_pbb_vtr.push_and_pop_bytes) + { + if (l2_pbb_process (b1, &(config1->input_pbb_vtr))) + { + /* Drop packet */ + next1 = L2_INVTR_NEXT_DROP; + b1->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + } + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + l2_invtr_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + ethernet_header_t *h0 = vlib_buffer_get_current (b0); + t->sw_if_index = sw_if_index0; + clib_memcpy (t->src, h0->src_address, 6); + clib_memcpy (t->dst, h0->dst_address, 6); + clib_memcpy (t->raw, &h0->type, sizeof (t->raw)); + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + l2_invtr_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + ethernet_header_t *h1 = vlib_buffer_get_current (b1); + t->sw_if_index = sw_if_index0; + clib_memcpy (t->src, h1->src_address, 6); + clib_memcpy (t->dst, h1->dst_address, 6); + clib_memcpy (t->raw, &h1->type, sizeof (t->raw)); + } + } + + /* verify speculative enqueues, maybe switch current next frame */ + /* if next0==next1==next_index then nothing special needs to be done */ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, + to_next, n_left_to_next, + bi0, bi1, next0, next1); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t *b0; + u32 next0; + u32 sw_if_index0; + u32 feature_bitmap0; + + /* speculatively enqueue b0 to the current next frame */ + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + + /* process 1 packet */ + + /* Remove ourself from the feature bitmap */ + feature_bitmap0 = + vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; + + /* save for next feature graph nodes */ + vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; + + /* Determine the next node */ + next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, + feature_bitmap0); + + l2_output_config_t *config0; + config0 = vec_elt_at_index (l2output_main.configs, sw_if_index0); + + if (PREDICT_FALSE (config0->out_vtr_flag)) + { + if (config0->output_vtr.push_and_pop_bytes) + { + /* perform the tag rewrite on one packet */ + if (l2_vtr_process + (b0, + &(vec_elt_at_index + (l2output_main.configs, sw_if_index0)->input_vtr))) + { + /* Drop packet */ + next0 = L2_INVTR_NEXT_DROP; + b0->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + else if (config0->output_pbb_vtr.push_and_pop_bytes) + { + if (l2_pbb_process (b0, &(config0->input_pbb_vtr))) + { + /* Drop packet */ + next0 = L2_INVTR_NEXT_DROP; + b0->error = node->errors[L2_INVTR_ERROR_DROP]; + } + } + } + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) + && (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + l2_invtr_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + ethernet_header_t *h0 = vlib_buffer_get_current (b0); + t->sw_if_index = sw_if_index0; + clib_memcpy (t->src, h0->src_address, 6); + clib_memcpy (t->dst, h0->dst_address, 6); + clib_memcpy (t->raw, &h0->type, sizeof (t->raw)); + } + + /* verify speculative enqueue, maybe switch current next frame */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return frame->n_vectors; +} + + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (l2_invtr_node,static) = { + .function = l2_invtr_node_fn, + .name = "l2-input-vtr", + .vector_size = sizeof (u32), + .format_trace = format_l2_invtr_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(l2_invtr_error_strings), + .error_strings = l2_invtr_error_strings, + + .n_next_nodes = L2_INVTR_N_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [L2_INVTR_NEXT_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +VLIB_NODE_FUNCTION_MULTIARCH (l2_invtr_node, l2_invtr_node_fn) + clib_error_t *l2_invtr_init (vlib_main_t * vm) +{ + l2_invtr_main_t *mp = &l2_invtr_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main (); + + /* Initialize the feature next-node indexes */ + feat_bitmap_init_next_nodes (vm, + l2_invtr_node.index, + L2INPUT_N_FEAT, + l2input_get_feat_names (), + mp->feat_next_node_index); + + return 0; +} + +VLIB_INIT_FUNCTION (l2_invtr_init); + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From 6f7ebf900e6c65b73f8bb8f60ab5190cc2c893bc Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Tue, 13 Jun 2017 12:09:37 +0300 Subject: ETH:fix l2_len/vlan count mismatch for > 2 tags l2_len was not updated for the third tag as the ethernet node retracts by the vlan count after parse_header (using ethernet_buffer_header_size) it ends up pointing before the ethernet header + some minor cleanups Change-Id: I4ccaedd33928912e5d837376f146503b27071741 Signed-off-by: Eyal Bari --- src/vnet/ethernet/node.c | 5 ++++- src/vnet/l2/l2_input_vtr.c | 15 +++------------ src/vnet/l2/l2_vtr.c | 3 --- 3 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src/vnet/l2/l2_input_vtr.c') diff --git a/src/vnet/ethernet/node.c b/src/vnet/ethernet/node.c index 8967cebe..4529ca6a 100755 --- a/src/vnet/ethernet/node.c +++ b/src/vnet/ethernet/node.c @@ -165,11 +165,12 @@ parse_header (ethernet_input_variant_t variant, vlib_buffer_advance (b0, sizeof (h0[0])); vlan_count = 2; - if (*type == ETHERNET_TYPE_VLAN) { // More than double tagged packet *match_flags = SUBINT_CONFIG_VALID | SUBINT_CONFIG_MATCH_3_TAG; + + vlib_buffer_advance (b0, sizeof (h0[0])); vlan_count = 3; // "unknown" number, aka, 3-or-more } } @@ -239,6 +240,8 @@ determine_next_node (ethernet_main_t * em, // record the L2 len and reset the buffer so the L2 header is preserved u32 eth_start = vnet_buffer (b0)->ethernet.start_of_ethernet_header; vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start; + ASSERT (vnet_buffer (b0)->l2.l2_len == + ethernet_buffer_header_size (b0)); vlib_buffer_advance (b0, -ethernet_buffer_header_size (b0)); // check for common IP/MPLS ethertypes diff --git a/src/vnet/l2/l2_input_vtr.c b/src/vnet/l2/l2_input_vtr.c index 60a39631..ded23095 100644 --- a/src/vnet/l2/l2_input_vtr.c +++ b/src/vnet/l2/l2_input_vtr.c @@ -188,10 +188,7 @@ l2_invtr_node_fn (vlib_main_t * vm, if (config0->output_vtr.push_and_pop_bytes) { /* perform the tag rewrite on two packets */ - if (l2_vtr_process - (b0, - &(vec_elt_at_index - (l2output_main.configs, sw_if_index0)->input_vtr))) + if (l2_vtr_process (b0, &config0->input_vtr)) { /* Drop packet */ next0 = L2_INVTR_NEXT_DROP; @@ -212,10 +209,7 @@ l2_invtr_node_fn (vlib_main_t * vm, { if (config1->output_vtr.push_and_pop_bytes) { - if (l2_vtr_process - (b1, - &(vec_elt_at_index - (l2output_main.configs, sw_if_index1)->input_vtr))) + if (l2_vtr_process (b1, &config1->input_vtr)) { /* Drop packet */ next1 = L2_INVTR_NEXT_DROP; @@ -305,10 +299,7 @@ l2_invtr_node_fn (vlib_main_t * vm, if (config0->output_vtr.push_and_pop_bytes) { /* perform the tag rewrite on one packet */ - if (l2_vtr_process - (b0, - &(vec_elt_at_index - (l2output_main.configs, sw_if_index0)->input_vtr))) + if (l2_vtr_process (b0, &config0->input_vtr)) { /* Drop packet */ next0 = L2_INVTR_NEXT_DROP; diff --git a/src/vnet/l2/l2_vtr.c b/src/vnet/l2/l2_vtr.c index 3c5365f9..02a68991 100644 --- a/src/vnet/l2/l2_vtr.c +++ b/src/vnet/l2/l2_vtr.c @@ -229,9 +229,6 @@ l2vtr_configure (vlib_main_t * vlib_main, vnet_main_t * vnet_main, u32 sw_if_ind } in_config->pop_bytes = 8; in_config->push_bytes = 0; - - out_config->push_bytes = in_config->pop_bytes; - out_config->pop_bytes = in_config->push_bytes; break; case L2_VTR_PUSH_1: -- cgit 1.2.3-korg From beb0b2e346c63e21ffe892ae0e04b67bb10fba5e Mon Sep 17 00:00:00 2001 From: John Lo Date: Sat, 22 Jul 2017 00:21:36 -0400 Subject: Improve L2 Input/Output Feature Infrastructure and Usage Simplify L2 output feature infra to unify with L2 input feature infra using the newly improved feature bitmap mechanism. Updated all L2 features to use the more efficient infra functions. Change-Id: If8f463826b0af0717129befe92a27ea8cfc40449 Signed-off-by: John Lo --- src/plugins/acl/fa_node.c | 7 +-- src/vnet/ethernet/arp.c | 8 +-- src/vnet/l2/feat_bitmap.h | 18 +++++- src/vnet/l2/l2_classify.h | 8 +-- src/vnet/l2/l2_efp_filter.c | 54 +++--------------- src/vnet/l2/l2_input.c | 37 ++++++------- src/vnet/l2/l2_input_acl.c | 9 +-- src/vnet/l2/l2_input_classify.c | 22 +++----- src/vnet/l2/l2_input_vtr.c | 35 ++---------- src/vnet/l2/l2_learn.c | 14 +---- src/vnet/l2/l2_output.c | 115 +++++++++++++++++++++++---------------- src/vnet/l2/l2_output.h | 80 +-------------------------- src/vnet/l2/l2_output_acl.c | 24 ++------ src/vnet/l2/l2_output_classify.c | 30 +++------- src/vnet/l2/l2_rw.c | 27 +++------ src/vnet/policer/node_funcs.c | 11 +--- 16 files changed, 160 insertions(+), 339 deletions(-) (limited to 'src/vnet/l2/l2_input_vtr.c') diff --git a/src/plugins/acl/fa_node.c b/src/plugins/acl/fa_node.c index 0bbc7423..c483044d 100644 --- a/src/plugins/acl/fa_node.c +++ b/src/plugins/acl/fa_node.c @@ -931,7 +931,6 @@ acl_fa_node_fn (vlib_main_t * vm, u32 pkts_acl_permit = 0; u32 pkts_restart_session_timer = 0; u32 trace_bitmap = 0; - u32 feature_bitmap0; acl_main_t *am = &acl_main; fa_5tuple_t fa_5tuple, kv_sess; clib_bihash_kv_40_8_t value_sess; @@ -977,8 +976,6 @@ acl_fa_node_fn (vlib_main_t * vm, sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; else sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX]; - if (is_l2_path) - feature_bitmap0 = vnet_buffer (b0)->l2.feature_bitmap; /* * Extract the L3/L4 matching info into a 5-tuple structure, @@ -1089,9 +1086,7 @@ acl_fa_node_fn (vlib_main_t * vm, if (action > 0) { if (is_l2_path) - next0 = - feat_bitmap_get_next_node_index (l2_feat_next_node_index, - feature_bitmap0); + next0 = vnet_l2_feature_next (b0, l2_feat_next_node_index, 0); else vnet_feature_next (sw_if_index0, &next0, b0); } diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index df681750..1bce3328 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -2291,12 +2291,8 @@ arp_term_l2bd (vlib_main_t * vm, next_l2_feature: { - u32 feature_bitmap0 = - vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM; - vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0; - next0 = - feat_bitmap_get_next_node_index (arp_term_next_node_index, - feature_bitmap0); + next0 = vnet_l2_feature_next (p0, arp_term_next_node_index, + L2INPUT_FEAT_ARP_TERM); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, pi0, next0); diff --git a/src/vnet/l2/feat_bitmap.h b/src/vnet/l2/feat_bitmap.h index c6e02ecc..5940ff7e 100644 --- a/src/vnet/l2/feat_bitmap.h +++ b/src/vnet/l2/feat_bitmap.h @@ -75,8 +75,8 @@ feat_bitmap_init_next_nodes (vlib_main_t * vm, u32 node_index, /* the current gr Return the graph node index for the feature corresponding to the first set bit in the bitmap. */ -always_inline - u32 feat_bitmap_get_next_node_index (u32 * next_nodes, u32 bitmap) +always_inline u32 +feat_bitmap_get_next_node_index (u32 * next_nodes, u32 bitmap) { u32 first_bit; @@ -85,6 +85,20 @@ always_inline return next_nodes[first_bit]; } +/** + Return the graph node index for the feature corresponding to the next + set bit after clearing the current feature bit in the feature_bitmap + of the current packet. +*/ +always_inline u32 +vnet_l2_feature_next (vlib_buffer_t * b, u32 * next_nodes, u32 feat_bit) +{ + vnet_buffer (b)->l2.feature_bitmap &= ~feat_bit; + u32 fb = vnet_buffer (b)->l2.feature_bitmap; + ASSERT (fb != 0); + return feat_bitmap_get_next_node_index (next_nodes, fb); +} + #endif /* included_vnet_l2_feat_bitmap_h */ /* diff --git a/src/vnet/l2/l2_classify.h b/src/vnet/l2/l2_classify.h index 184187ff..100c584a 100644 --- a/src/vnet/l2/l2_classify.h +++ b/src/vnet/l2/l2_classify.h @@ -68,15 +68,13 @@ typedef enum typedef struct _l2_classify_main { - /* Next nodes for each feature */ - u32 feat_next_node_index[32]; + /* Next nodes for L2 input and output features */ + u32 l2_inp_feat_next[32]; + u32 l2_out_feat_next[32]; /* Per-address-family classifier table vectors */ u32 *classify_table_index_by_sw_if_index[L2_INPUT_CLASSIFY_N_TABLES]; - /* Next nodes for features and output interfaces */ - l2_output_next_nodes_st next_nodes; - /* convenience variables */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; diff --git a/src/vnet/l2/l2_efp_filter.c b/src/vnet/l2/l2_efp_filter.c index f9ba8f2f..faf78153 100644 --- a/src/vnet/l2/l2_efp_filter.c +++ b/src/vnet/l2/l2_efp_filter.c @@ -43,9 +43,8 @@ */ typedef struct { - - /* Next nodes for features and output interfaces */ - l2_output_next_nodes_st next_nodes; + /* Next nodes for L2 output features */ + u32 l2_out_feat_next[32]; /* convenience variables */ vlib_main_t *vlib_main; @@ -180,11 +179,6 @@ l2_efp_filter_node_fn (vlib_main_t * vm, vlib_node_t *n = vlib_get_node (vm, l2_efp_filter_node.index); u32 node_counter_base_index = n->error_heap_index; vlib_error_main_t *em = &vm->error_main; - u32 cached_sw_if_index = ~0; - u32 cached_next_index = ~0; - - /* invalidate cache to begin with */ - cached_sw_if_index = ~0; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* number of packets to process */ @@ -203,7 +197,6 @@ l2_efp_filter_node_fn (vlib_main_t * vm, vlib_buffer_t *b0, *b1; u32 next0, next1; u32 sw_if_index0, sw_if_index1; - u32 feature_bitmap0, feature_bitmap1; u16 first_ethertype0, first_ethertype1; u16 outer_id0, inner_id0, outer_id1, inner_id1; u32 match_flags0, match_flags1; @@ -267,29 +260,11 @@ l2_efp_filter_node_fn (vlib_main_t * vm, em->counters[node_counter_base_index + L2_EFP_FILTER_ERROR_L2_EFP_FILTER] += 2; - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2OUTPUT_FEAT_EFP_FILTER; - feature_bitmap1 = - vnet_buffer (b1)->l2.feature_bitmap & ~L2OUTPUT_FEAT_EFP_FILTER; - /* Determine next node */ - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2_efp_filter_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2_efp_filter_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b1, sw_if_index1, feature_bitmap1, &next1); + next0 = vnet_l2_feature_next (b0, msm->l2_out_feat_next, + L2OUTPUT_FEAT_EFP_FILTER); + next1 = vnet_l2_feature_next (b1, msm->l2_out_feat_next, + L2OUTPUT_FEAT_EFP_FILTER); /* perform the efp filter check on two packets */ @@ -394,7 +369,6 @@ l2_efp_filter_node_fn (vlib_main_t * vm, vlib_buffer_t *b0; u32 next0; u32 sw_if_index0; - u32 feature_bitmap0; u16 first_ethertype0; u16 outer_id0, inner_id0; u32 match_flags0; @@ -422,19 +396,9 @@ l2_efp_filter_node_fn (vlib_main_t * vm, em->counters[node_counter_base_index + L2_EFP_FILTER_ERROR_L2_EFP_FILTER] += 1; - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2OUTPUT_FEAT_EFP_FILTER; - /* Determine next node */ - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2_efp_filter_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); + next0 = vnet_l2_feature_next (b0, msm->l2_out_feat_next, + L2OUTPUT_FEAT_EFP_FILTER); /* perform the efp filter check on one packet */ @@ -528,7 +492,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (l2_efp_filter_node, l2_efp_filter_node_fn) l2_efp_filter_node.index, L2OUTPUT_N_FEAT, l2output_get_feat_names (), - mp->next_nodes.feat_next_node_index); + mp->l2_out_feat_next); return 0; } diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index aa156213..26c832ad 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -115,10 +115,7 @@ typedef enum static_always_inline void -classify_and_dispatch (vlib_main_t * vm, - vlib_node_runtime_t * node, - u32 thread_index, - l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0) +classify_and_dispatch (l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0) { /* * Load L2 input feature struct @@ -187,12 +184,7 @@ classify_and_dispatch (vlib_main_t * vm, } - if (config->xconnect) - { - /* Set the output interface */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = config->output_sw_if_index; - } - else + if (config->bridge) { /* Do bridge-domain processing */ bd_index0 = config->bd_index; @@ -220,6 +212,13 @@ classify_and_dispatch (vlib_main_t * vm, */ feat_mask = feat_mask & bd_config->feature_bitmap; } + else if (config->xconnect) + { + /* Set the output interface */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = config->output_sw_if_index; + } + else + feat_mask = L2INPUT_FEAT_DROP; /* mask out features from bitmap using packet type and bd config */ feature_bitmap = config->feature_bitmap & feat_mask; @@ -240,7 +239,6 @@ l2input_node_inline (vlib_main_t * vm, u32 n_left_from, *from, *to_next; l2input_next_t next_index; l2input_main_t *msm = &l2input_main; - u32 thread_index = vlib_get_thread_index (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* number of packets to process */ @@ -353,10 +351,10 @@ l2input_node_inline (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 4); - classify_and_dispatch (vm, node, thread_index, msm, b0, &next0); - classify_and_dispatch (vm, node, thread_index, msm, b1, &next1); - classify_and_dispatch (vm, node, thread_index, msm, b2, &next2); - classify_and_dispatch (vm, node, thread_index, msm, b3, &next3); + classify_and_dispatch (msm, b0, &next0); + classify_and_dispatch (msm, b1, &next1); + classify_and_dispatch (msm, b2, &next2); + classify_and_dispatch (msm, b3, &next3); /* verify speculative enqueues, maybe switch current next frame */ /* if next0==next1==next_index then nothing special needs to be done */ @@ -396,7 +394,7 @@ l2input_node_inline (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 1); - classify_and_dispatch (vm, node, thread_index, msm, b0, &next0); + classify_and_dispatch (msm, b0, &next0); /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, @@ -574,8 +572,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ } /* Make sure vector is big enough */ - vec_validate_init_empty (l2om->next_nodes.output_node_index_vec, - sw_if_index, L2OUTPUT_NEXT_DROP); + vec_validate_init_empty (l2om->output_node_index_vec, sw_if_index, + L2OUTPUT_NEXT_DROP); /* Initialize the l2-input configuration for the interface */ if (mode == MODE_L3) @@ -594,8 +592,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ /* Make sure any L2-output packet to this interface now in L3 mode is * dropped. This may happen if L2 FIB MAC entry is stale */ - l2om->next_nodes.output_node_index_vec[sw_if_index] = - L2OUTPUT_NEXT_BAD_INTF; + l2om->output_node_index_vec[sw_if_index] = L2OUTPUT_NEXT_BAD_INTF; } else { diff --git a/src/vnet/l2/l2_input_acl.c b/src/vnet/l2/l2_input_acl.c index 104fcd15..84030888 100644 --- a/src/vnet/l2/l2_input_acl.c +++ b/src/vnet/l2/l2_input_acl.c @@ -269,14 +269,11 @@ l2_inacl_node_fn (vlib_main_t * vm, e0 = 0; t0 = 0; - /* Feature bitmap update */ - vnet_buffer (b0)->l2.feature_bitmap &= ~L2INPUT_FEAT_ACL; - vnet_buffer (b0)->l2_classify.opaque_index = ~0; + /* Determine the next node */ - next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, - vnet_buffer (b0)-> - l2.feature_bitmap); + next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index, + L2INPUT_FEAT_ACL); if (PREDICT_TRUE (table_index0 != ~0)) { diff --git a/src/vnet/l2/l2_input_classify.c b/src/vnet/l2/l2_input_classify.c index 485b9abd..ee8042a0 100644 --- a/src/vnet/l2/l2_input_classify.c +++ b/src/vnet/l2/l2_input_classify.c @@ -152,7 +152,6 @@ l2_input_classify_node_fn (vlib_main_t * vm, vnet_classify_main_t *vcm = cm->vnet_classify_main; l2_input_classify_runtime_t *rt = (l2_input_classify_runtime_t *) node->runtime_data; - u32 feature_bitmap; u32 hits = 0; u32 misses = 0; u32 chain_hits = 0; @@ -354,13 +353,6 @@ l2_input_classify_node_fn (vlib_main_t * vm, e0 = 0; vnet_buffer (b0)->l2_classify.opaque_index = ~0; - /* Remove ourself from the feature bitmap */ - feature_bitmap = vnet_buffer (b0)->l2.feature_bitmap - & ~L2INPUT_FEAT_INPUT_CLASSIFY; - - /* save for next feature graph nodes */ - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap; - if (PREDICT_TRUE (table_index0 != ~0)) { hash0 = vnet_buffer (b0)->l2_classify.hash; @@ -412,13 +404,13 @@ l2_input_classify_node_fn (vlib_main_t * vm, if (PREDICT_FALSE (next0 == 0)) b0->error = node->errors[L2_INPUT_CLASSIFY_ERROR_DROP]; + /* Determine the next node and remove ourself from bitmap */ if (PREDICT_TRUE (next0 == ~0)) - { - // Determine the next node - next0 = - feat_bitmap_get_next_node_index (cm->feat_next_node_index, - feature_bitmap); - } + next0 = vnet_l2_feature_next (b0, cm->l2_inp_feat_next, + L2INPUT_FEAT_INPUT_CLASSIFY); + else + vnet_buffer (b0)->l2.feature_bitmap &= + ~L2INPUT_FEAT_INPUT_CLASSIFY; if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) @@ -496,7 +488,7 @@ l2_input_classify_init (vlib_main_t * vm) l2_input_classify_node.index, L2INPUT_N_FEAT, l2input_get_feat_names (), - cm->feat_next_node_index); + cm->l2_inp_feat_next); rt->l2cm = cm; rt->vcm = cm->vnet_classify_main; diff --git a/src/vnet/l2/l2_input_vtr.c b/src/vnet/l2/l2_input_vtr.c index ded23095..9470752f 100644 --- a/src/vnet/l2/l2_input_vtr.c +++ b/src/vnet/l2/l2_input_vtr.c @@ -111,7 +111,6 @@ l2_invtr_node_fn (vlib_main_t * vm, vlib_buffer_t *b0, *b1; u32 next0, next1; u32 sw_if_index0, sw_if_index1; - u32 feature_bitmap0, feature_bitmap1; /* Prefetch next iteration. */ { @@ -160,23 +159,11 @@ l2_invtr_node_fn (vlib_main_t * vm, sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - /* process 2 packets */ - - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; - feature_bitmap1 = - vnet_buffer (b1)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; - - /* save for next feature graph nodes */ - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; - vnet_buffer (b1)->l2.feature_bitmap = feature_bitmap1; - /* Determine the next node */ - next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, - feature_bitmap0); - next1 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, - feature_bitmap1); + next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index, + L2INPUT_FEAT_VTR); + next1 = vnet_l2_feature_next (b1, msm->feat_next_node_index, + L2INPUT_FEAT_VTR); l2_output_config_t *config0; l2_output_config_t *config1; @@ -264,7 +251,6 @@ l2_invtr_node_fn (vlib_main_t * vm, vlib_buffer_t *b0; u32 next0; u32 sw_if_index0; - u32 feature_bitmap0; /* speculatively enqueue b0 to the current next frame */ bi0 = from[0]; @@ -278,18 +264,9 @@ l2_invtr_node_fn (vlib_main_t * vm, sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - /* process 1 packet */ - - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_VTR; - - /* save for next feature graph nodes */ - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; - /* Determine the next node */ - next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, - feature_bitmap0); + next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index, + L2INPUT_FEAT_VTR); l2_output_config_t *config0; config0 = vec_elt_at_index (l2output_main.configs, sw_if_index0); diff --git a/src/vnet/l2/l2_learn.c b/src/vnet/l2/l2_learn.c index b9904d3e..65406292 100644 --- a/src/vnet/l2/l2_learn.c +++ b/src/vnet/l2/l2_learn.c @@ -116,19 +116,9 @@ l2learn_process (vlib_node_runtime_t * node, u32 * bucket0, l2fib_entry_result_t * result0, u32 * next0, u8 timestamp) { - u32 feature_bitmap; - /* Set up the default next node (typically L2FWD) */ - - /* Remove ourself from the feature bitmap */ - feature_bitmap = vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_LEARN; - - /* Save for next feature graph nodes */ - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap; - - /* Determine the next node */ - *next0 = feat_bitmap_get_next_node_index (msm->feat_next_node_index, - feature_bitmap); + *next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index, + L2INPUT_FEAT_LEARN); /* Check mac table lookup result */ if (PREDICT_TRUE (result0->fields.sw_if_index == sw_if_index0)) diff --git a/src/vnet/l2/l2_output.c b/src/vnet/l2/l2_output.c index 51d5e145..b3537a35 100644 --- a/src/vnet/l2/l2_output.c +++ b/src/vnet/l2/l2_output.c @@ -98,6 +98,57 @@ split_horizon_violation (u8 shg1, u8 shg2) } } +/** Determine the next L2 node based on the output feature bitmap */ +static_always_inline void +l2_output_dispatch (vlib_buffer_t * b0, vlib_node_runtime_t * node, + u32 * cached_sw_if_index, u32 * cached_next_index, + u32 sw_if_index, u32 feature_bitmap, u32 * next0) +{ + /* + * The output feature bitmap always have at least the L2 output bit set + * for a normal L2 interface (or 0 if the interface is changed from L2 + * to L3 mode). So if the feature bitmap is 0 or just have L2 output bits set, + * we know there is no more feature and will just output packets on interface. + * Otherwise, get the index of the next feature node. + */ + if (PREDICT_FALSE ((feature_bitmap & ~L2OUTPUT_FEAT_OUTPUT) != 0)) + { + /* Save bitmap for the next feature graph nodes */ + vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap; + + /* Determine the next node */ + *next0 = + feat_bitmap_get_next_node_index (l2output_main.l2_out_feat_next, + feature_bitmap); + } + else + { + /* + * There are no features. Send packet to TX node for sw_if_index0 + * This is a little tricky in that the output interface next node indexes + * are not precomputed at init time. + */ + + if (sw_if_index == *cached_sw_if_index) + { + /* We hit in the one-entry cache. Use it. */ + *next0 = *cached_next_index; + } + else + { + /* Look up the output TX node for the sw_if_index */ + *next0 = vec_elt (l2output_main.output_node_index_vec, sw_if_index); + + if (PREDICT_FALSE (*next0 == L2OUTPUT_NEXT_DROP)) + b0->error = node->errors[L2OUTPUT_ERROR_MAPPING_DROP]; + + /* Update the one-entry cache */ + *cached_sw_if_index = sw_if_index; + *cached_next_index = *next0; + } + } +} + static_always_inline void l2output_vtr (vlib_node_runtime_t * node, l2_output_config_t * config, u32 feature_bitmap, vlib_buffer_t * b, u32 * next) @@ -239,41 +290,18 @@ l2output_node_inline (vlib_main_t * vm, vlib_node_runtime_t * node, feature_bitmap3 = config3->feature_bitmap; /* Determine next node */ - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2output_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); - - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2output_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b1, sw_if_index1, feature_bitmap1, &next1); - - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2output_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b2, sw_if_index2, feature_bitmap2, &next2); - - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2output_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b3, sw_if_index3, feature_bitmap3, &next3); + l2_output_dispatch (b0, node, &cached_sw_if_index, + &cached_next_index, sw_if_index0, + feature_bitmap0, &next0); + l2_output_dispatch (b1, node, &cached_sw_if_index, + &cached_next_index, sw_if_index1, + feature_bitmap1, &next1); + l2_output_dispatch (b2, node, &cached_sw_if_index, + &cached_next_index, sw_if_index2, + feature_bitmap2, &next2); + l2_output_dispatch (b3, node, &cached_sw_if_index, + &cached_next_index, sw_if_index3, + feature_bitmap3, &next3); l2output_vtr (node, config0, feature_bitmap0, b0, &next0); l2output_vtr (node, config1, feature_bitmap1, b1, &next1); @@ -401,14 +429,9 @@ l2output_node_inline (vlib_main_t * vm, vlib_node_runtime_t * node, feature_bitmap0 = config0->feature_bitmap; /* Determine next node */ - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2output_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); + l2_output_dispatch (b0, node, &cached_sw_if_index, + &cached_next_index, sw_if_index0, + feature_bitmap0, &next0); l2output_vtr (node, config0, feature_bitmap0, b0, &next0); @@ -598,10 +621,10 @@ VLIB_NODE_FUNCTION_MULTIARCH (l2output_node, l2output_node_fn) l2output_node.index, L2OUTPUT_N_FEAT, l2output_get_feat_names (), - mp->next_nodes.feat_next_node_index); + mp->l2_out_feat_next); /* Initialize the output node mapping table */ - vec_validate_init_empty (mp->next_nodes.output_node_index_vec, 100, + vec_validate_init_empty (mp->output_node_index_vec, 100, L2OUTPUT_NEXT_DROP); return 0; @@ -621,7 +644,7 @@ l2output_create_output_node_mapping (vlib_main_t * vlib_main, /* dynamically create graph node arc */ u32 next = vlib_node_add_next (vlib_main, l2output_node.index, hw0->output_node_index); - l2output_main.next_nodes.output_node_index_vec[sw_if_index] = next; + l2output_main.output_node_index_vec[sw_if_index] = next; } /* Get a pointer to the config for the given interface */ diff --git a/src/vnet/l2/l2_output.h b/src/vnet/l2/l2_output.h index 82cefd2c..6da3e303 100644 --- a/src/vnet/l2/l2_output.h +++ b/src/vnet/l2/l2_output.h @@ -52,11 +52,6 @@ typedef struct } l2_output_config_t; - -/* - * The set of next nodes for features and interface output. - * Each output feature node should include this. - */ typedef struct { /* @@ -70,15 +65,7 @@ typedef struct * array of next node index for each output feature, indexed * by l2output_feat_t. Used to determine next feature node. */ - u32 feat_next_node_index[32]; - -} l2_output_next_nodes_st; - - -typedef struct -{ - /* Next nodes for features and output interfaces */ - l2_output_next_nodes_st next_nodes; + u32 l2_out_feat_next[32]; /* config vector indexed by sw_if_index */ l2_output_config_t *configs; @@ -163,71 +150,6 @@ void l2output_create_output_node_mapping (vlib_main_t * vlib_main, vnet_main_t * vnet_main, u32 sw_if_index); -/** Determine the next L2 node based on the output feature bitmap */ -always_inline void -l2_output_dispatch (vlib_main_t * vlib_main, - vnet_main_t * vnet_main, - vlib_node_runtime_t * node, - u32 node_index, - u32 * cached_sw_if_index, - u32 * cached_next_index, - l2_output_next_nodes_st * next_nodes, - vlib_buffer_t * b0, - u32 sw_if_index, u32 feature_bitmap, u32 * next0) -{ - /* - * 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; - - /* Determine the next node */ - *next0 = - feat_bitmap_get_next_node_index (next_nodes->feat_next_node_index, - feature_bitmap); - } - else - { - /* - * There are no features. Send packet to TX node for sw_if_index0 - * This is a little tricky in that the output interface next node indexes - * are not precomputed at init time. - */ - - if (sw_if_index == *cached_sw_if_index) - { - /* We hit in the one-entry cache. Use it. */ - *next0 = *cached_next_index; - } - else - { - /* Look up the output TX node for the sw_if_index */ - *next0 = vec_elt (l2output_main.next_nodes.output_node_index_vec, - sw_if_index); - - if (*next0 == L2OUTPUT_NEXT_DROP) - b0->error = node->errors[L2OUTPUT_ERROR_MAPPING_DROP]; - - /* Update the one-entry cache */ - *cached_sw_if_index = sw_if_index; - *cached_next_index = *next0; - } - } -} - /** Get a pointer to the config for the given interface */ l2_output_config_t *l2output_intf_config (u32 sw_if_index); diff --git a/src/vnet/l2/l2_output_acl.c b/src/vnet/l2/l2_output_acl.c index 1d1971a5..7d051326 100644 --- a/src/vnet/l2/l2_output_acl.c +++ b/src/vnet/l2/l2_output_acl.c @@ -34,8 +34,8 @@ typedef struct { - /* Next nodes for features and output interfaces */ - l2_output_next_nodes_st next_nodes; + /* Next nodes for L2 output features */ + u32 l2_out_feat_next[32]; /* convenience variables */ vlib_main_t *vlib_main; @@ -108,8 +108,6 @@ l2_outacl_node_fn (vlib_main_t * vm, vlib_node_t *n = vlib_get_node (vm, l2_outacl_node.index); u32 node_counter_base_index = n->error_heap_index; vlib_error_main_t *em = &vm->error_main; - u32 cached_sw_if_index = (u32) ~ 0; - u32 cached_next_index = (u32) ~ 0; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* number of packets to process */ @@ -201,7 +199,6 @@ l2_outacl_node_fn (vlib_main_t * vm, u32 next0; u32 sw_if_index0; ethernet_header_t *h0; - u32 feature_bitmap0; /* speculatively enqueue b0 to the current next frame */ bi0 = from[0]; @@ -234,20 +231,9 @@ l2_outacl_node_fn (vlib_main_t * vm, * Dummy for now, just go to next feature node */ - - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2OUTPUT_FEAT_ACL; - /* Determine next node */ - l2_output_dispatch (msm->vlib_main, - msm->vnet_main, - node, - l2_outacl_node.index, - &cached_sw_if_index, - &cached_next_index, - &msm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); + next0 = vnet_l2_feature_next (b0, msm->l2_out_feat_next, + L2OUTPUT_FEAT_ACL); /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, @@ -295,7 +281,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (l2_outacl_node, l2_outacl_node_fn) l2_outacl_node.index, L2OUTPUT_N_FEAT, l2output_get_feat_names (), - mp->next_nodes.feat_next_node_index); + mp->l2_out_feat_next); return 0; } diff --git a/src/vnet/l2/l2_output_classify.c b/src/vnet/l2/l2_output_classify.c index 869b0656..a49abec2 100644 --- a/src/vnet/l2/l2_output_classify.c +++ b/src/vnet/l2/l2_output_classify.c @@ -144,14 +144,11 @@ l2_output_classify_node_fn (vlib_main_t * vm, vnet_classify_main_t *vcm = cm->vnet_classify_main; l2_output_classify_runtime_t *rt = (l2_output_classify_runtime_t *) node->runtime_data; - u32 feature_bitmap0; u32 hits = 0; u32 misses = 0; u32 chain_hits = 0; f64 now; u32 n_next_nodes; - u32 cached_sw_if_index = (u32) ~ 0; - u32 cached_next_index = (u32) ~ 0; u32 sw_if_index0; n_next_nodes = node->n_next_nodes; @@ -347,12 +344,6 @@ l2_output_classify_node_fn (vlib_main_t * vm, table_index0 = vnet_buffer (b0)->l2_classify.table_index; e0 = 0; vnet_buffer (b0)->l2_classify.opaque_index = ~0; - /* Remove ourself from the feature bitmap */ - feature_bitmap0 = vnet_buffer (b0)->l2.feature_bitmap - & ~L2OUTPUT_FEAT_OUTPUT_CLASSIFY; - - /* save for next feature graph nodes */ - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; if (PREDICT_TRUE (table_index0 != ~0)) { @@ -405,20 +396,13 @@ l2_output_classify_node_fn (vlib_main_t * vm, if (PREDICT_FALSE (next0 == 0)) b0->error = node->errors[L2_OUTPUT_CLASSIFY_ERROR_DROP]; + /* Determine the next node and remove ourself from bitmap */ if (PREDICT_FALSE (next0 == ~0)) - { - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX]; - - /* Determine next node */ - l2_output_dispatch (cm->vlib_main, - cm->vnet_main, - node, - l2_output_classify_node.index, - &cached_sw_if_index, - &cached_next_index, - &cm->next_nodes, - b0, sw_if_index0, feature_bitmap0, &next0); - } + next0 = vnet_l2_feature_next (b0, cm->l2_out_feat_next, + L2OUTPUT_FEAT_OUTPUT_CLASSIFY); + else + vnet_buffer (b0)->l2.feature_bitmap &= + ~L2OUTPUT_FEAT_OUTPUT_CLASSIFY; if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) @@ -493,7 +477,7 @@ l2_output_classify_init (vlib_main_t * vm) l2_output_classify_node.index, L2OUTPUT_N_FEAT, l2output_get_feat_names (), - cm->next_nodes.feat_next_node_index); + cm->l2_out_feat_next); rt->l2cm = cm; rt->vcm = cm->vnet_classify_main; diff --git a/src/vnet/l2/l2_rw.c b/src/vnet/l2/l2_rw.c index c54509d0..fec04774 100644 --- a/src/vnet/l2/l2_rw.c +++ b/src/vnet/l2/l2_rw.c @@ -179,8 +179,8 @@ l2_rw_node_fn (vlib_main_t * vm, while (n_left_from >= 4 && n_left_to_next >= 2) { - u32 bi0, next0, sw_if_index0, feature_bitmap0, rwe_index0; - u32 bi1, next1, sw_if_index1, feature_bitmap1, rwe_index1; + u32 bi0, next0, sw_if_index0, rwe_index0; + u32 bi1, next1, sw_if_index1, rwe_index1; vlib_buffer_t *b0, *b1; ethernet_header_t *h0, *h1; l2_rw_config_t *config0, *config1; @@ -273,16 +273,10 @@ l2_rw_node_fn (vlib_main_t * vm, } /* Update feature bitmap and get next feature index */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_RW; - feature_bitmap1 = - vnet_buffer (b1)->l2.feature_bitmap & ~L2INPUT_FEAT_RW; - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; - vnet_buffer (b1)->l2.feature_bitmap = feature_bitmap1; - next0 = feat_bitmap_get_next_node_index (rw->feat_next_node_index, - feature_bitmap0); - next1 = feat_bitmap_get_next_node_index (rw->feat_next_node_index, - feature_bitmap1); + next0 = vnet_l2_feature_next (b0, rw->feat_next_node_index, + L2INPUT_FEAT_RW); + next1 = vnet_l2_feature_next (b1, rw->feat_next_node_index, + L2INPUT_FEAT_RW); vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, @@ -291,7 +285,7 @@ l2_rw_node_fn (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, next0, sw_if_index0, feature_bitmap0, rwe_index0; + u32 bi0, next0, sw_if_index0, rwe_index0; vlib_buffer_t *b0; ethernet_header_t *h0; l2_rw_config_t *config0; @@ -341,11 +335,8 @@ l2_rw_node_fn (vlib_main_t * vm, } /* Update feature bitmap and get next feature index */ - feature_bitmap0 = - vnet_buffer (b0)->l2.feature_bitmap & ~L2INPUT_FEAT_RW; - vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap0; - next0 = feat_bitmap_get_next_node_index (rw->feat_next_node_index, - feature_bitmap0); + next0 = vnet_l2_feature_next (b0, rw->feat_next_node_index, + L2INPUT_FEAT_RW); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, diff --git a/src/vnet/policer/node_funcs.c b/src/vnet/policer/node_funcs.c index 457dd09f..fd031d02 100644 --- a/src/vnet/policer/node_funcs.c +++ b/src/vnet/policer/node_funcs.c @@ -736,14 +736,9 @@ policer_classify_inline (vlib_main_t * vm, if (tid == POLICER_CLASSIFY_TABLE_L2) { - /* Feature bitmap update */ - vnet_buffer (b0)->l2.feature_bitmap &= - ~L2INPUT_FEAT_POLICER_CLAS; - /* Determine the next node */ - next0 = - feat_bitmap_get_next_node_index (pcm->feat_next_node_index, - vnet_buffer (b0)-> - l2.feature_bitmap); + /* Feature bitmap update and determine the next node */ + next0 = vnet_l2_feature_next (b0, pcm->feat_next_node_index, + L2INPUT_FEAT_POLICER_CLAS); } else vnet_get_config_data (pcm->vnet_config_main[tid], -- cgit 1.2.3-korg