LCOV - code coverage report
Current view: top level - vnet/l2 - l2_in_out_feat_arc.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 186 189 98.4 %
Date: 2023-10-26 01:39:38 Functions: 70 82 85.4 %

          Line data    Source code
       1             : /*
       2             :  * l2_in_out_feat_arc.c : layer 2 input/output acl processing
       3             :  *
       4             :  * Copyright (c) 2013,2018 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vlib/vlib.h>
      19             : #include <vnet/ethernet/ethernet.h>
      20             : #include <vnet/ip/ip_packet.h>
      21             : #include <vnet/l2/l2_input.h>
      22             : #include <vnet/l2/l2_output.h>
      23             : #include <vnet/l2/l2_in_out_feat_arc.h>
      24             : 
      25             : #include <vppinfra/error.h>
      26             : #include <vppinfra/hash.h>
      27             : #include <vppinfra/cache.h>
      28             : 
      29             : 
      30             : typedef struct
      31             : {
      32             : 
      33             :   /* Next nodes for each feature */
      34             :   u32 feat_next_node_index[IN_OUT_FEAT_ARC_N_TABLE_GROUPS][32];
      35             :   u8 ip4_feat_arc_index[IN_OUT_FEAT_ARC_N_TABLE_GROUPS];
      36             :   u8 ip6_feat_arc_index[IN_OUT_FEAT_ARC_N_TABLE_GROUPS];
      37             :   u8 nonip_feat_arc_index[IN_OUT_FEAT_ARC_N_TABLE_GROUPS];
      38             :   u32 next_slot[IN_OUT_FEAT_ARC_N_TABLE_GROUPS];
      39             : } l2_in_out_feat_arc_main_t __attribute__ ((aligned (CLIB_CACHE_LINE_BYTES)));
      40             : 
      41             : typedef struct
      42             : {
      43             :   u32 sw_if_index;
      44             :   u32 next_index;
      45             :   u32 feature_bitmap;
      46             :   u16 ethertype;
      47             :   u8 arc_head;
      48             : } l2_in_out_feat_arc_trace_t;
      49             : 
      50             : /* packet trace format function */
      51             : static u8 *
      52        3878 : format_l2_in_out_feat_arc_trace (u8 * s, u32 is_output, va_list * args)
      53             : {
      54        3878 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      55        3878 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      56        3878 :   l2_in_out_feat_arc_trace_t *t =
      57             :     va_arg (*args, l2_in_out_feat_arc_trace_t *);
      58             : 
      59             :   s =
      60        3878 :     format (s,
      61             :             "%s: head %d feature_bitmap %x ethertype %x sw_if_index %d, next_index %d",
      62        3878 :             is_output ? "OUT-FEAT-ARC" : "IN-FEAT-ARC", t->arc_head,
      63        3878 :             t->feature_bitmap, t->ethertype, t->sw_if_index, t->next_index);
      64        3878 :   return s;
      65             : }
      66             : 
      67             : static u8 *
      68        3562 : format_l2_in_feat_arc_trace (u8 * s, va_list * args)
      69             : {
      70        3562 :   return format_l2_in_out_feat_arc_trace (s,
      71             :                                           IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP,
      72             :                                           args);
      73             : }
      74             : 
      75             : static u8 *
      76         316 : format_l2_out_feat_arc_trace (u8 * s, va_list * args)
      77             : {
      78         316 :   return format_l2_in_out_feat_arc_trace (s,
      79             :                                           IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP,
      80             :                                           args);
      81             : }
      82             : 
      83             : 
      84             : #define foreach_l2_in_feat_arc_error                   \
      85             : _(DEFAULT, "in default")                         \
      86             : 
      87             : 
      88             : #define foreach_l2_out_feat_arc_error                   \
      89             : _(DEFAULT, "out default")                         \
      90             : 
      91             : 
      92             : typedef enum
      93             : {
      94             : #define _(sym,str) L2_IN_FEAT_ARC_ERROR_##sym,
      95             :   foreach_l2_in_feat_arc_error
      96             : #undef _
      97             :     L2_IN_FEAT_ARC_N_ERROR,
      98             : } l2_in_feat_arc_error_t;
      99             : 
     100             : static char *l2_in_feat_arc_error_strings[] = {
     101             : #define _(sym,string) string,
     102             :   foreach_l2_in_feat_arc_error
     103             : #undef _
     104             : };
     105             : 
     106             : typedef enum
     107             : {
     108             : #define _(sym,str) L2_OUT_FEAT_ARC_ERROR_##sym,
     109             :   foreach_l2_out_feat_arc_error
     110             : #undef _
     111             :     L2_OUT_FEAT_ARC_N_ERROR,
     112             : } l2_out_feat_arc_error_t;
     113             : 
     114             : static char *l2_out_feat_arc_error_strings[] = {
     115             : #define _(sym,string) string,
     116             :   foreach_l2_out_feat_arc_error
     117             : #undef _
     118             : };
     119             : 
     120             : extern l2_in_out_feat_arc_main_t l2_in_out_feat_arc_main;
     121             : 
     122             : #ifndef CLIB_MARCH_VARIANT
     123             : l2_in_out_feat_arc_main_t l2_in_out_feat_arc_main;
     124             : #endif /* CLIB_MARCH_VARIANT */
     125             : 
     126             : #define get_u16(addr) ( *((u16 *)(addr)) )
     127             : #define L2_FEAT_ARC_VEC_SIZE 2
     128             : 
     129             : static_always_inline void
     130    22556100 : buffer_prefetch_xN (int vector_sz, vlib_buffer_t ** b)
     131             : {
     132             :   int ii;
     133    67668400 :   for (ii = 0; ii < vector_sz; ii++)
     134    45112200 :     clib_prefetch_store (b[ii]);
     135    22556100 : }
     136             : 
     137             : static_always_inline void
     138    13302700 : get_sw_if_index_xN (int vector_sz, int is_output, vlib_buffer_t ** b,
     139             :                     u32 * out_sw_if_index)
     140             : {
     141             :   int ii;
     142    37039200 :   for (ii = 0; ii < vector_sz; ii++)
     143    23736500 :     if (is_output)
     144    23734200 :       out_sw_if_index[ii] = vnet_buffer (b[ii])->sw_if_index[VLIB_TX];
     145             :     else
     146        2311 :       out_sw_if_index[ii] = vnet_buffer (b[ii])->sw_if_index[VLIB_RX];
     147    13302700 : }
     148             : 
     149             : static_always_inline void
     150    13302700 : get_ethertype_xN (int vector_sz, int is_output, vlib_buffer_t ** b,
     151             :                   u16 * out_ethertype)
     152             : {
     153             :   int ii;
     154    37039200 :   for (ii = 0; ii < vector_sz; ii++)
     155             :     {
     156    23736500 :       ethernet_header_t *h0 = vlib_buffer_get_current (b[ii]);
     157    23736500 :       u8 *l3h0 = (u8 *) h0 + vnet_buffer (b[ii])->l2.l2_len;
     158    23736500 :       out_ethertype[ii] = clib_net_to_host_u16 (get_u16 (l3h0 - 2));
     159             :     }
     160    13302700 : }
     161             : 
     162             : 
     163             : static_always_inline void
     164    13302700 : set_next_in_arc_head_xN (int vector_sz, int is_output, u32 * next_nodes,
     165             :                          vlib_buffer_t ** b, u32 * sw_if_index,
     166             :                          u16 * ethertype, u8 ip4_arc, u8 ip6_arc,
     167             :                          u8 nonip_arc, u16 * out_next)
     168             : {
     169             :   int ii;
     170    37039200 :   for (ii = 0; ii < vector_sz; ii++)
     171             :     {
     172    23736500 :       u32 next_index = 0;
     173             :       u8 feature_arc;
     174    23736500 :       switch (ethertype[ii])
     175             :         {
     176    13349800 :         case ETHERNET_TYPE_IP4:
     177    13349800 :           feature_arc = ip4_arc;
     178    13349800 :           break;
     179    10386300 :         case ETHERNET_TYPE_IP6:
     180    10386300 :           feature_arc = ip6_arc;
     181    10386300 :           break;
     182         349 :         default:
     183         349 :           feature_arc = nonip_arc;
     184             :         }
     185    23736500 :       if (PREDICT_TRUE (vnet_have_features (feature_arc, sw_if_index[ii])))
     186    23661500 :         vnet_feature_arc_start (feature_arc,
     187    23661500 :                                 sw_if_index[ii], &next_index, b[ii]);
     188             :       else
     189       75029 :         next_index =
     190       75029 :           vnet_l2_feature_next (b[ii], next_nodes,
     191             :                                 is_output ? L2OUTPUT_FEAT_OUTPUT_FEAT_ARC :
     192             :                                 L2INPUT_FEAT_INPUT_FEAT_ARC);
     193             : 
     194    23736500 :       out_next[ii] = next_index;
     195             :     }
     196    13302700 : }
     197             : 
     198             : static_always_inline void
     199    15210800 : set_next_in_arc_tail_xN (int vector_sz, int is_output, u32 * next_nodes,
     200             :                          vlib_buffer_t ** b, u16 * out_next)
     201             : {
     202             :   int ii;
     203    42543900 :   for (ii = 0; ii < vector_sz; ii++)
     204             :     {
     205    27333100 :       out_next[ii] =
     206    27333100 :         vnet_l2_feature_next (b[ii], next_nodes,
     207             :                               is_output ? L2OUTPUT_FEAT_OUTPUT_FEAT_ARC :
     208             :                               L2INPUT_FEAT_INPUT_FEAT_ARC);
     209             :     }
     210             : 
     211    15210800 : }
     212             : 
     213             : 
     214             : static_always_inline void
     215        2618 : maybe_trace_xN (int vector_sz, int arc_head, vlib_main_t * vm,
     216             :                 vlib_node_runtime_t * node, vlib_buffer_t ** b,
     217             :                 u32 * sw_if_index, u16 * ethertype, u16 * next)
     218             : {
     219             :   int ii;
     220        6818 :   for (ii = 0; ii < vector_sz; ii++)
     221        4200 :     if (PREDICT_FALSE (b[ii]->flags & VLIB_BUFFER_IS_TRACED))
     222             :       {
     223             :         l2_in_out_feat_arc_trace_t *t =
     224        4200 :           vlib_add_trace (vm, node, b[ii], sizeof (*t));
     225        4200 :         t->arc_head = arc_head;
     226        4200 :         t->sw_if_index = arc_head ? sw_if_index[ii] : ~0;
     227        4200 :         t->feature_bitmap = vnet_buffer (b[ii])->l2.feature_bitmap;
     228        4200 :         t->ethertype = arc_head ? ethertype[ii] : 0;
     229        4200 :         t->next_index = next[ii];
     230             :       }
     231        2618 : }
     232             : 
     233             : always_inline uword
     234     1238060 : l2_in_out_feat_arc_node_fn (vlib_main_t * vm,
     235             :                             vlib_node_runtime_t * node, vlib_frame_t * frame,
     236             :                             int is_output, vlib_node_registration_t * fa_node,
     237             :                             int arc_head, int do_trace)
     238             : {
     239             :   u32 n_left, *from;
     240             :   u16 nexts[VLIB_FRAME_SIZE], *next;
     241             :   u16 ethertypes[VLIB_FRAME_SIZE], *ethertype;
     242             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
     243             :   u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index;
     244     1238060 :   l2_in_out_feat_arc_main_t *fam = &l2_in_out_feat_arc_main;
     245             : 
     246     1238060 :   u8 ip4_arc_index = fam->ip4_feat_arc_index[is_output];
     247     1238060 :   u8 ip6_arc_index = fam->ip6_feat_arc_index[is_output];
     248     1238060 :   u8 nonip_arc_index = fam->nonip_feat_arc_index[is_output];
     249     1238060 :   u32 *next_node_indices = fam->feat_next_node_index[is_output];
     250             : 
     251     1238060 :   from = vlib_frame_vector_args (frame);
     252     1238060 :   vlib_get_buffers (vm, from, bufs, frame->n_vectors);
     253             :   /* set the initial values for the current buffer the next pointers */
     254     1238060 :   b = bufs;
     255     1238060 :   next = nexts;
     256     1238060 :   ethertype = ethertypes;
     257     1238060 :   sw_if_index = sw_if_indices;
     258     1238060 :   n_left = frame->n_vectors;
     259             : 
     260     1238060 :   CLIB_PREFETCH (next_node_indices,
     261             :                  sizeof (fam->feat_next_node_index[is_output]), LOAD);
     262             : 
     263    23794200 :   while (n_left > 3 * L2_FEAT_ARC_VEC_SIZE)
     264             :     {
     265    22556100 :       const int vec_sz = L2_FEAT_ARC_VEC_SIZE;
     266             :       /* prefetch next N buffers */
     267    22556100 :       buffer_prefetch_xN (vec_sz, b + 2 * vec_sz);
     268             : 
     269    22556100 :       if (arc_head)
     270             :         {
     271    10433800 :           get_sw_if_index_xN (vec_sz, is_output, b, sw_if_index);
     272    10433800 :           get_ethertype_xN (vec_sz, is_output, b, ethertype);
     273    10433800 :           set_next_in_arc_head_xN (vec_sz, is_output, next_node_indices, b,
     274             :                                    sw_if_index, ethertype, ip4_arc_index,
     275             :                                    ip6_arc_index, nonip_arc_index, next);
     276             :         }
     277             :       else
     278             :         {
     279    12122300 :           set_next_in_arc_tail_xN (vec_sz, is_output, next_node_indices, b,
     280             :                                    next);
     281             :         }
     282    22556100 :       if (do_trace)
     283        1582 :         maybe_trace_xN (vec_sz, arc_head, vm, node, b, sw_if_index, ethertype,
     284             :                         next);
     285             : 
     286    22556100 :       next += vec_sz;
     287    22556100 :       b += vec_sz;
     288    22556100 :       sw_if_index += vec_sz;
     289    22556100 :       ethertype += vec_sz;
     290             : 
     291    22556100 :       n_left -= vec_sz;
     292             :     }
     293             : 
     294     7195430 :   while (n_left > 0)
     295             :     {
     296     5957370 :       const int vec_sz = 1;
     297             : 
     298     5957370 :       if (arc_head)
     299             :         {
     300     2868950 :           get_sw_if_index_xN (vec_sz, is_output, b, sw_if_index);
     301     2868950 :           get_ethertype_xN (vec_sz, is_output, b, ethertype);
     302     2868950 :           set_next_in_arc_head_xN (vec_sz, is_output, next_node_indices, b,
     303             :                                    sw_if_index, ethertype, ip4_arc_index,
     304             :                                    ip6_arc_index, nonip_arc_index, next);
     305             :         }
     306             :       else
     307             :         {
     308     3088420 :           set_next_in_arc_tail_xN (vec_sz, is_output, next_node_indices, b,
     309             :                                    next);
     310             :         }
     311     5957370 :       if (do_trace)
     312        1036 :         maybe_trace_xN (vec_sz, arc_head, vm, node, b, sw_if_index, ethertype,
     313             :                         next);
     314             : 
     315     5957370 :       next += vec_sz;
     316     5957370 :       b += vec_sz;
     317     5957370 :       sw_if_index += vec_sz;
     318     5957370 :       ethertype += vec_sz;
     319             : 
     320     5957370 :       n_left -= vec_sz;
     321             :     }
     322             : 
     323     1238060 :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     324             : 
     325     1238060 :   return frame->n_vectors;
     326             : }
     327             : 
     328        2368 : VLIB_NODE_FN (l2_in_feat_arc_node) (vlib_main_t * vm,
     329             :                                     vlib_node_runtime_t * node,
     330             :                                     vlib_frame_t * frame)
     331             : {
     332          68 :   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
     333          68 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     334             :                                        IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP,
     335             :                                        &l2_in_feat_arc_node, 1, 1);
     336             :   else
     337           0 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     338             :                                        IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP,
     339             :                                        &l2_in_feat_arc_node, 1, 0);
     340             : }
     341             : 
     342      628763 : VLIB_NODE_FN (l2_out_feat_arc_node) (vlib_main_t * vm,
     343             :                                      vlib_node_runtime_t * node,
     344             :                                      vlib_frame_t * frame)
     345             : {
     346      626463 :   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
     347          35 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     348             :                                        IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP,
     349             :                                        &l2_out_feat_arc_node, 1, 1);
     350             :   else
     351      626428 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     352             :                                        IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP,
     353             :                                        &l2_out_feat_arc_node, 1, 0);
     354             : }
     355             : 
     356        2355 : VLIB_NODE_FN (l2_in_feat_arc_end_node) (vlib_main_t * vm,
     357             :                                         vlib_node_runtime_t * node,
     358             :                                         vlib_frame_t * frame)
     359             : {
     360          55 :   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
     361          55 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     362             :                                        IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP,
     363             :                                        &l2_in_feat_arc_end_node, 0, 1);
     364             :   else
     365           0 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     366             :                                        IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP,
     367             :                                        &l2_in_feat_arc_end_node, 0, 0);
     368             : }
     369             : 
     370      613773 : VLIB_NODE_FN (l2_out_feat_arc_end_node) (vlib_main_t * vm,
     371             :                                          vlib_node_runtime_t * node,
     372             :                                          vlib_frame_t * frame)
     373             : {
     374      611473 :   if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
     375          32 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     376             :                                        IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP,
     377             :                                        &l2_out_feat_arc_end_node, 0, 1);
     378             :   else
     379      611441 :     return l2_in_out_feat_arc_node_fn (vm, node, frame,
     380             :                                        IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP,
     381             :                                        &l2_out_feat_arc_end_node, 0, 0);
     382             : }
     383             : 
     384             : 
     385             : #ifndef CLIB_MARCH_VARIANT
     386             : void
     387        1934 : vnet_l2_in_out_feat_arc_enable_disable (u32 sw_if_index, int is_output,
     388             :                                         int enable_disable)
     389             : {
     390        1934 :   if (is_output)
     391        1116 :     l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_OUTPUT_FEAT_ARC,
     392             :                                  (u32) enable_disable);
     393             :   else
     394         818 :     l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_INPUT_FEAT_ARC,
     395             :                                 (u32) enable_disable);
     396        1934 : }
     397             : #endif /* CLIB_MARCH_VARIANT */
     398             : 
     399             : /* *INDENT-OFF* */
     400        1151 : VNET_FEATURE_ARC_INIT (l2_in_ip4_arc, static) =
     401             : {
     402             :   .arc_name  = "l2-input-ip4",
     403             :   .start_nodes = VNET_FEATURES ("l2-input-feat-arc"),
     404             :   .arc_index_ptr = &l2_in_out_feat_arc_main.ip4_feat_arc_index[IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP],
     405             : };
     406             : 
     407        1151 : VNET_FEATURE_ARC_INIT (l2_out_ip4_arc, static) =
     408             : {
     409             :   .arc_name  = "l2-output-ip4",
     410             :   .start_nodes = VNET_FEATURES ("l2-output-feat-arc"),
     411             :   .arc_index_ptr = &l2_in_out_feat_arc_main.ip4_feat_arc_index[IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP],
     412             : };
     413             : 
     414        1151 : VNET_FEATURE_ARC_INIT (l2_out_ip6_arc, static) =
     415             : {
     416             :   .arc_name  = "l2-input-ip6",
     417             :   .start_nodes = VNET_FEATURES ("l2-input-feat-arc"),
     418             :   .arc_index_ptr = &l2_in_out_feat_arc_main.ip6_feat_arc_index[IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP],
     419             : };
     420        1151 : VNET_FEATURE_ARC_INIT (l2_in_ip6_arc, static) =
     421             : {
     422             :   .arc_name  = "l2-output-ip6",
     423             :   .start_nodes = VNET_FEATURES ("l2-output-feat-arc"),
     424             :   .arc_index_ptr = &l2_in_out_feat_arc_main.ip6_feat_arc_index[IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP],
     425             : };
     426             : 
     427        1151 : VNET_FEATURE_ARC_INIT (l2_out_nonip_arc, static) =
     428             : {
     429             :   .arc_name  = "l2-input-nonip",
     430             :   .start_nodes = VNET_FEATURES ("l2-input-feat-arc"),
     431             :   .arc_index_ptr = &l2_in_out_feat_arc_main.nonip_feat_arc_index[IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP],
     432             : };
     433        1151 : VNET_FEATURE_ARC_INIT (l2_in_nonip_arc, static) =
     434             : {
     435             :   .arc_name  = "l2-output-nonip",
     436             :   .start_nodes = VNET_FEATURES ("l2-output-feat-arc"),
     437             :   .arc_index_ptr = &l2_in_out_feat_arc_main.nonip_feat_arc_index[IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP],
     438             : };
     439             : 
     440             : 
     441             : /* *INDENT-ON* */
     442             : 
     443             : 
     444             : /* *INDENT-OFF* */
     445      183788 : VLIB_REGISTER_NODE (l2_in_feat_arc_node) = {
     446             :   .name = "l2-input-feat-arc",
     447             :   .vector_size = sizeof (u32),
     448             :   .format_trace = format_l2_in_feat_arc_trace,
     449             :   .type = VLIB_NODE_TYPE_INTERNAL,
     450             : 
     451             :   .n_errors = ARRAY_LEN(l2_in_feat_arc_error_strings),
     452             :   .error_strings = l2_in_feat_arc_error_strings,
     453             : 
     454             : };
     455             : 
     456      183788 : VLIB_REGISTER_NODE (l2_out_feat_arc_node) = {
     457             :   .name = "l2-output-feat-arc",
     458             :   .vector_size = sizeof (u32),
     459             :   .format_trace = format_l2_out_feat_arc_trace,
     460             :   .type = VLIB_NODE_TYPE_INTERNAL,
     461             : 
     462             :   .n_errors = ARRAY_LEN(l2_out_feat_arc_error_strings),
     463             :   .error_strings = l2_out_feat_arc_error_strings,
     464             : 
     465             : };
     466             : 
     467      183788 : VLIB_REGISTER_NODE (l2_in_feat_arc_end_node) = {
     468             :   .name = "l2-input-feat-arc-end",
     469             :   .vector_size = sizeof (u32),
     470             :   .format_trace = format_l2_in_feat_arc_trace,
     471             :   .sibling_of = "l2-input-feat-arc",
     472             : };
     473             : 
     474      183788 : VLIB_REGISTER_NODE (l2_out_feat_arc_end_node) = {
     475             :   .name = "l2-output-feat-arc-end",
     476             :   .vector_size = sizeof (u32),
     477             :   .format_trace = format_l2_out_feat_arc_trace,
     478             :   .sibling_of = "l2-output-feat-arc",
     479             : };
     480             : 
     481       76635 : VNET_FEATURE_INIT (l2_in_ip4_arc_end, static) =
     482             : {
     483             :   .arc_name = "l2-input-ip4",
     484             :   .node_name = "l2-input-feat-arc-end",
     485             :   .runs_before = 0,     /* not before any other features */
     486             : };
     487             : 
     488       76635 : VNET_FEATURE_INIT (l2_out_ip4_arc_end, static) =
     489             : {
     490             :   .arc_name = "l2-output-ip4",
     491             :   .node_name = "l2-output-feat-arc-end",
     492             :   .runs_before = 0,     /* not before any other features */
     493             : };
     494             : 
     495       76635 : VNET_FEATURE_INIT (l2_in_ip6_arc_end, static) =
     496             : {
     497             :   .arc_name = "l2-input-ip6",
     498             :   .node_name = "l2-input-feat-arc-end",
     499             :   .runs_before = 0,     /* not before any other features */
     500             : };
     501             : 
     502             : 
     503       76635 : VNET_FEATURE_INIT (l2_out_ip6_arc_end, static) =
     504             : {
     505             :   .arc_name = "l2-output-ip6",
     506             :   .node_name = "l2-output-feat-arc-end",
     507             :   .runs_before = 0,     /* not before any other features */
     508             : };
     509             : 
     510       76635 : VNET_FEATURE_INIT (l2_in_nonip_arc_end, static) =
     511             : {
     512             :   .arc_name = "l2-input-nonip",
     513             :   .node_name = "l2-input-feat-arc-end",
     514             :   .runs_before = 0,     /* not before any other features */
     515             : };
     516             : 
     517             : 
     518       76635 : VNET_FEATURE_INIT (l2_out_nonip_arc_end, static) =
     519             : {
     520             :   .arc_name = "l2-output-nonip",
     521             :   .node_name = "l2-output-feat-arc-end",
     522             :   .runs_before = 0,     /* not before any other features */
     523             : };
     524             : /* *INDENT-ON* */
     525             : 
     526             : 
     527             : #ifndef CLIB_MARCH_VARIANT
     528             : clib_error_t *
     529         575 : l2_in_out_feat_arc_init (vlib_main_t * vm)
     530             : {
     531         575 :   l2_in_out_feat_arc_main_t *mp = &l2_in_out_feat_arc_main;
     532             : 
     533             :   /* Initialize the feature next-node indexes */
     534         575 :   feat_bitmap_init_next_nodes (vm,
     535             :                                l2_in_feat_arc_end_node.index,
     536             :                                L2INPUT_N_FEAT,
     537             :                                l2input_get_feat_names (),
     538             :                                mp->feat_next_node_index
     539         575 :                                [IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP]);
     540         575 :   feat_bitmap_init_next_nodes (vm, l2_out_feat_arc_end_node.index,
     541             :                                L2OUTPUT_N_FEAT, l2output_get_feat_names (),
     542             :                                mp->feat_next_node_index
     543         575 :                                [IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP]);
     544         575 :   return 0;
     545             : }
     546             : 
     547             : 
     548             : static int
     549        1934 : l2_has_features (u32 sw_if_index, int is_output)
     550             : {
     551        1934 :   int has_features = 0;
     552        1934 :   l2_in_out_feat_arc_main_t *mp = &l2_in_out_feat_arc_main;
     553        1934 :   has_features +=
     554        1934 :     vnet_have_features (mp->ip4_feat_arc_index[is_output], sw_if_index);
     555        1934 :   has_features +=
     556        1934 :     vnet_have_features (mp->ip6_feat_arc_index[is_output], sw_if_index);
     557        1934 :   has_features +=
     558        1934 :     vnet_have_features (mp->nonip_feat_arc_index[is_output], sw_if_index);
     559        1934 :   return has_features > 0;
     560             : }
     561             : 
     562             : static int
     563        1934 : l2_is_output_arc (u8 arc_index)
     564             : {
     565        1934 :   l2_in_out_feat_arc_main_t *mp = &l2_in_out_feat_arc_main;
     566        1934 :   int idx = IN_OUT_FEAT_ARC_OUTPUT_TABLE_GROUP;
     567        1934 :   return (mp->ip4_feat_arc_index[idx] == arc_index
     568        1376 :           || mp->ip6_feat_arc_index[idx] == arc_index
     569        3310 :           || mp->nonip_feat_arc_index[idx] == arc_index);
     570             : }
     571             : 
     572             : static int
     573        1934 : l2_is_input_arc (u8 arc_index)
     574             : {
     575        1934 :   l2_in_out_feat_arc_main_t *mp = &l2_in_out_feat_arc_main;
     576        1934 :   int idx = IN_OUT_FEAT_ARC_INPUT_TABLE_GROUP;
     577        1934 :   return (mp->ip4_feat_arc_index[idx] == arc_index
     578        1530 :           || mp->ip6_feat_arc_index[idx] == arc_index
     579        3464 :           || mp->nonip_feat_arc_index[idx] == arc_index);
     580             : }
     581             : 
     582             : int
     583        3227 : vnet_l2_feature_enable_disable (const char *arc_name, const char *node_name,
     584             :                                 u32 sw_if_index, int enable_disable,
     585             :                                 void *feature_config,
     586             :                                 u32 n_feature_config_bytes)
     587             : {
     588        3227 :   u8 arc_index = vnet_get_feature_arc_index (arc_name);
     589        3227 :   if (arc_index == (u8) ~ 0)
     590           0 :     return VNET_API_ERROR_INVALID_VALUE;
     591             : 
     592             :   /* check the state before we tried to enable/disable */
     593        3227 :   int had_features = vnet_have_features (arc_index, sw_if_index);
     594             : 
     595        3227 :   int ret = vnet_feature_enable_disable (arc_name, node_name, sw_if_index,
     596             :                                          enable_disable, feature_config,
     597             :                                          n_feature_config_bytes);
     598        3227 :   if (ret)
     599         641 :     return ret;
     600             : 
     601        2586 :   int has_features = vnet_have_features (arc_index, sw_if_index);
     602             : 
     603        2586 :   if (had_features != has_features)
     604             :     {
     605        1934 :       if (l2_is_output_arc (arc_index))
     606             :         {
     607        1116 :           vnet_l2_in_out_feat_arc_enable_disable (sw_if_index, 1,
     608             :                                                   l2_has_features
     609             :                                                   (sw_if_index, 1));
     610             :         }
     611        1934 :       if (l2_is_input_arc (arc_index))
     612             :         {
     613         818 :           vnet_l2_in_out_feat_arc_enable_disable (sw_if_index, 0,
     614             :                                                   l2_has_features
     615             :                                                   (sw_if_index, 0));
     616             :         }
     617             :     }
     618        2586 :   return 0;
     619             : }
     620             : 
     621             : 
     622       23039 : VLIB_INIT_FUNCTION (l2_in_out_feat_arc_init);
     623             : #endif /* CLIB_MARCH_VARIANT */
     624             : 
     625             : /*
     626             :  * fd.io coding-style-patch-verification: ON
     627             :  *
     628             :  * Local Variables:
     629             :  * eval: (c-set-style "gnu")
     630             :  * End:
     631             :  */

Generated by: LCOV version 1.14