LCOV - code coverage report
Current view: top level - vnet/l2 - l2_in_out_acl.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 165 180 91.7 %
Date: 2023-10-26 01:39:38 Functions: 21 27 77.8 %

          Line data    Source code
       1             : /*
       2             :  * l2_in_out_acl.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/vnet.h>
      20             : #include <vnet/ethernet/ethernet.h>
      21             : #include <vnet/ethernet/packet.h>
      22             : #include <vnet/ip/ip_packet.h>
      23             : #include <vnet/ip/ip4_packet.h>
      24             : #include <vnet/ip/ip6_packet.h>
      25             : #include <vlib/cli.h>
      26             : #include <vnet/l2/l2_input.h>
      27             : #include <vnet/l2/l2_output.h>
      28             : #include <vnet/l2/feat_bitmap.h>
      29             : 
      30             : #include <vppinfra/error.h>
      31             : #include <vppinfra/hash.h>
      32             : #include <vppinfra/cache.h>
      33             : 
      34             : #include <vnet/classify/vnet_classify.h>
      35             : #include <vnet/classify/in_out_acl.h>
      36             : 
      37             : typedef struct
      38             : {
      39             : 
      40             :   /* Next nodes for each feature */
      41             :   u32 feat_next_node_index[IN_OUT_ACL_N_TABLE_GROUPS][32];
      42             : 
      43             :   /* convenience variables */
      44             :   vlib_main_t *vlib_main;
      45             :   vnet_main_t *vnet_main;
      46             : } l2_in_out_acl_main_t;
      47             : 
      48             : typedef struct
      49             : {
      50             :   u32 sw_if_index;
      51             :   u32 next_index;
      52             :   u32 table_index;
      53             :   u32 offset;
      54             : } l2_in_out_acl_trace_t;
      55             : 
      56             : /* packet trace format function */
      57             : static u8 *
      58         201 : format_l2_in_out_acl_trace (u8 * s, u32 is_output, va_list * args)
      59             : {
      60         201 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      61         201 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      62         201 :   l2_in_out_acl_trace_t *t = va_arg (*args, l2_in_out_acl_trace_t *);
      63             : 
      64         201 :   s = format (s, "%s: sw_if_index %d, next_index %d, table %d, offset %d",
      65             :               is_output ? "OUTACL" : "INACL",
      66             :               t->sw_if_index, t->next_index, t->table_index, t->offset);
      67         201 :   return s;
      68             : }
      69             : 
      70             : static u8 *
      71         198 : format_l2_inacl_trace (u8 * s, va_list * args)
      72             : {
      73         198 :   return format_l2_in_out_acl_trace (s, IN_OUT_ACL_INPUT_TABLE_GROUP, args);
      74             : }
      75             : 
      76             : static u8 *
      77           3 : format_l2_outacl_trace (u8 * s, va_list * args)
      78             : {
      79           3 :   return format_l2_in_out_acl_trace (s, IN_OUT_ACL_OUTPUT_TABLE_GROUP, args);
      80             : }
      81             : 
      82             : extern l2_in_out_acl_main_t l2_in_out_acl_main;
      83             : 
      84             : #ifndef CLIB_MARCH_VARIANT
      85             : l2_in_out_acl_main_t l2_in_out_acl_main;
      86             : #endif /* CLIB_MARCH_VARIANT */
      87             : 
      88             : extern vlib_node_registration_t l2_inacl_node;
      89             : extern vlib_node_registration_t l2_outacl_node;
      90             : 
      91             : #define foreach_l2_inacl_error                  \
      92             : _(NONE, "valid input ACL packets")              \
      93             : _(MISS, "input ACL misses")                     \
      94             : _(HIT, "input ACL hits")                        \
      95             : _(CHAIN_HIT, "input ACL hits after chain walk") \
      96             : _(TABLE_MISS, "input ACL table-miss drops")     \
      97             : _(SESSION_DENY, "input ACL session deny drops")
      98             : 
      99             : #define foreach_l2_outacl_error                  \
     100             : _(NONE, "valid output ACL packets")              \
     101             : _(MISS, "output ACL misses")                     \
     102             : _(HIT, "output ACL hits")                        \
     103             : _(CHAIN_HIT, "output ACL hits after chain walk") \
     104             : _(TABLE_MISS, "output ACL table-miss drops")     \
     105             : _(SESSION_DENY, "output ACL session deny drops")
     106             : 
     107             : 
     108             : typedef enum
     109             : {
     110             : #define _(sym,str) L2_INACL_ERROR_##sym,
     111             :   foreach_l2_inacl_error
     112             : #undef _
     113             :     L2_INACL_N_ERROR,
     114             : } l2_inacl_error_t;
     115             : 
     116             : static char *l2_inacl_error_strings[] = {
     117             : #define _(sym,string) string,
     118             :   foreach_l2_inacl_error
     119             : #undef _
     120             : };
     121             : 
     122             : typedef enum
     123             : {
     124             : #define _(sym,str) L2_OUTACL_ERROR_##sym,
     125             :   foreach_l2_outacl_error
     126             : #undef _
     127             :     L2_OUTACL_N_ERROR,
     128             : } l2_outacl_error_t;
     129             : 
     130             : static char *l2_outacl_error_strings[] = {
     131             : #define _(sym,string) string,
     132             :   foreach_l2_outacl_error
     133             : #undef _
     134             : };
     135             : 
     136             : 
     137             : static inline uword
     138          33 : l2_in_out_acl_node_fn (vlib_main_t * vm,
     139             :                        vlib_node_runtime_t * node, vlib_frame_t * frame,
     140             :                        int is_output)
     141             : {
     142             :   u32 n_left_from, *from, *to_next;
     143             :   acl_next_index_t next_index;
     144          33 :   l2_in_out_acl_main_t *msm = &l2_in_out_acl_main;
     145          33 :   in_out_acl_main_t *am = &in_out_acl_main;
     146          33 :   vnet_classify_main_t *vcm = am->vnet_classify_main;
     147          33 :   in_out_acl_table_id_t tid = IN_OUT_ACL_TABLE_L2;
     148          33 :   f64 now = vlib_time_now (vm);
     149          33 :   u32 hits = 0;
     150          33 :   u32 misses = 0;
     151          33 :   u32 chain_hits = 0;
     152             : 
     153          33 :   from = vlib_frame_vector_args (frame);
     154          33 :   n_left_from = frame->n_vectors;    /* number of packets to process */
     155          33 :   next_index = node->cached_next_index;
     156             : 
     157             :   /* First pass: compute hashes */
     158         126 :   while (n_left_from > 2)
     159             :     {
     160             :       vlib_buffer_t *b0, *b1;
     161             :       u32 bi0, bi1;
     162             :       u8 *h0, *h1;
     163             :       u32 sw_if_index0, sw_if_index1;
     164             :       u32 table_index0, table_index1;
     165             :       vnet_classify_table_t *t0, *t1;
     166             : 
     167             :       /* prefetch next iteration */
     168             :       {
     169             :         vlib_buffer_t *p1, *p2;
     170             : 
     171          93 :         p1 = vlib_get_buffer (vm, from[1]);
     172          93 :         p2 = vlib_get_buffer (vm, from[2]);
     173             : 
     174          93 :         vlib_prefetch_buffer_header (p1, STORE);
     175          93 :         clib_prefetch_store (p1->data);
     176          93 :         vlib_prefetch_buffer_header (p2, STORE);
     177          93 :         clib_prefetch_store (p2->data);
     178             :       }
     179             : 
     180          93 :       bi0 = from[0];
     181          93 :       b0 = vlib_get_buffer (vm, bi0);
     182             : 
     183          93 :       bi1 = from[1];
     184          93 :       b1 = vlib_get_buffer (vm, bi1);
     185             : 
     186          93 :       sw_if_index0 =
     187          93 :         vnet_buffer (b0)->sw_if_index[is_output ? VLIB_TX : VLIB_RX];
     188          93 :       table_index0 =
     189          93 :         am->classify_table_index_by_sw_if_index[is_output][tid][sw_if_index0];
     190             : 
     191          93 :       sw_if_index1 =
     192          93 :         vnet_buffer (b1)->sw_if_index[is_output ? VLIB_TX : VLIB_RX];
     193          93 :       table_index1 =
     194          93 :         am->classify_table_index_by_sw_if_index[is_output][tid][sw_if_index1];
     195             : 
     196          93 :       t0 = pool_elt_at_index (vcm->tables, table_index0);
     197             : 
     198          93 :       t1 = pool_elt_at_index (vcm->tables, table_index1);
     199             : 
     200          93 :       if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
     201           0 :         h0 = (void *) vlib_buffer_get_current (b0) + t0->current_data_offset;
     202             :       else
     203          93 :         h0 = (void *) vlib_buffer_get_current (b0);
     204             : 
     205         186 :       vnet_buffer (b0)->l2_classify.hash =
     206          93 :         vnet_classify_hash_packet (t0, (u8 *) h0);
     207             : 
     208          93 :       vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
     209             : 
     210          93 :       if (t1->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
     211           0 :         h1 = (void *) vlib_buffer_get_current (b1) + t1->current_data_offset;
     212             :       else
     213          93 :         h1 = (void *) vlib_buffer_get_current (b1);
     214             : 
     215         186 :       vnet_buffer (b1)->l2_classify.hash =
     216          93 :         vnet_classify_hash_packet (t1, (u8 *) h1);
     217             : 
     218          93 :       vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
     219             : 
     220          93 :       vnet_buffer (b0)->l2_classify.table_index = table_index0;
     221             : 
     222          93 :       vnet_buffer (b1)->l2_classify.table_index = table_index1;
     223             : 
     224          93 :       from += 2;
     225          93 :       n_left_from -= 2;
     226             :     }
     227             : 
     228          66 :   while (n_left_from > 0)
     229             :     {
     230             :       vlib_buffer_t *b0;
     231             :       u32 bi0;
     232             :       u8 *h0;
     233             :       u32 sw_if_index0;
     234             :       u32 table_index0;
     235             :       vnet_classify_table_t *t0;
     236             : 
     237          33 :       bi0 = from[0];
     238          33 :       b0 = vlib_get_buffer (vm, bi0);
     239             : 
     240          33 :       sw_if_index0 =
     241          33 :         vnet_buffer (b0)->sw_if_index[is_output ? VLIB_TX : VLIB_RX];
     242          33 :       table_index0 =
     243          33 :         am->classify_table_index_by_sw_if_index[is_output][tid][sw_if_index0];
     244             : 
     245          33 :       t0 = pool_elt_at_index (vcm->tables, table_index0);
     246             : 
     247          33 :       if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
     248           9 :         h0 = (void *) vlib_buffer_get_current (b0) + t0->current_data_offset;
     249             :       else
     250          24 :         h0 = (void *) vlib_buffer_get_current (b0);
     251             : 
     252          66 :       vnet_buffer (b0)->l2_classify.hash =
     253          33 :         vnet_classify_hash_packet (t0, (u8 *) h0);
     254             : 
     255          33 :       vnet_buffer (b0)->l2_classify.table_index = table_index0;
     256          33 :       vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
     257             : 
     258          33 :       from++;
     259          33 :       n_left_from--;
     260             :     }
     261             : 
     262          33 :   next_index = node->cached_next_index;
     263          33 :   from = vlib_frame_vector_args (frame);
     264          33 :   n_left_from = frame->n_vectors;
     265             : 
     266          66 :   while (n_left_from > 0)
     267             :     {
     268             :       u32 n_left_to_next;
     269             : 
     270          33 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     271             : 
     272             :       /* Not enough load/store slots to dual loop... */
     273         252 :       while (n_left_from > 0 && n_left_to_next > 0)
     274             :         {
     275             :           u32 bi0;
     276             :           vlib_buffer_t *b0;
     277         219 :           u32 next0 = ACL_NEXT_INDEX_DENY;
     278             :           u32 table_index0;
     279             :           vnet_classify_table_t *t0;
     280             :           vnet_classify_entry_t *e0;
     281             :           u32 hash0;
     282             :           u8 *h0;
     283             :           u8 error0;
     284             : 
     285             :           /* Stride 3 seems to work best */
     286         219 :           if (PREDICT_TRUE (n_left_from > 3))
     287             :             {
     288         138 :               vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
     289             :               vnet_classify_table_t *tp1;
     290             :               u32 table_index1;
     291             :               u32 phash1;
     292             : 
     293         138 :               table_index1 = vnet_buffer (p1)->l2_classify.table_index;
     294             : 
     295         138 :               if (PREDICT_TRUE (table_index1 != ~0))
     296             :                 {
     297         138 :                   tp1 = pool_elt_at_index (vcm->tables, table_index1);
     298         138 :                   phash1 = vnet_buffer (p1)->l2_classify.hash;
     299         138 :                   vnet_classify_prefetch_entry (tp1, phash1);
     300             :                 }
     301             :             }
     302             : 
     303             :           /* speculatively enqueue b0 to the current next frame */
     304         219 :           bi0 = from[0];
     305         219 :           to_next[0] = bi0;
     306         219 :           from += 1;
     307         219 :           to_next += 1;
     308         219 :           n_left_from -= 1;
     309         219 :           n_left_to_next -= 1;
     310             : 
     311         219 :           b0 = vlib_get_buffer (vm, bi0);
     312             : 
     313         219 :           table_index0 = vnet_buffer (b0)->l2_classify.table_index;
     314         219 :           e0 = 0;
     315         219 :           t0 = 0;
     316             : 
     317         219 :           vnet_buffer (b0)->l2_classify.opaque_index = ~0;
     318             : 
     319             :           /* Determine the next node */
     320             :           next0 =
     321         219 :             vnet_l2_feature_next (b0, msm->feat_next_node_index[is_output],
     322             :                                   is_output ? L2OUTPUT_FEAT_ACL :
     323             :                                   L2INPUT_FEAT_ACL);
     324             : 
     325         219 :           if (PREDICT_TRUE (table_index0 != ~0))
     326             :             {
     327         219 :               hash0 = vnet_buffer (b0)->l2_classify.hash;
     328         219 :               t0 = pool_elt_at_index (vcm->tables, table_index0);
     329             : 
     330         219 :               if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
     331           9 :                 h0 =
     332           9 :                   (void *) vlib_buffer_get_current (b0) +
     333           9 :                   t0->current_data_offset;
     334             :               else
     335         210 :                 h0 = (void *) vlib_buffer_get_current (b0);
     336             : 
     337         219 :               e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
     338         219 :               if (e0)
     339             :                 {
     340          91 :                   vnet_buffer (b0)->l2_classify.opaque_index
     341          91 :                     = e0->opaque_index;
     342          91 :                   vlib_buffer_advance (b0, e0->advance);
     343             : 
     344         182 :                   next0 = (e0->next_index < ACL_NEXT_INDEX_N_NEXT) ?
     345          91 :                     e0->next_index : next0;
     346             : 
     347          91 :                   hits++;
     348             : 
     349          91 :                   if (is_output)
     350           3 :                     error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     351             :                       L2_OUTACL_ERROR_SESSION_DENY : L2_INACL_ERROR_NONE;
     352             :                   else
     353          88 :                     error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     354             :                       L2_OUTACL_ERROR_SESSION_DENY : L2_OUTACL_ERROR_NONE;
     355          91 :                   b0->error = node->errors[error0];
     356             :                 }
     357             :               else
     358             :                 {
     359             :                   while (1)
     360             :                     {
     361         384 :                       if (PREDICT_TRUE (t0->next_table_index != ~0))
     362         384 :                         t0 = pool_elt_at_index (vcm->tables,
     363             :                                                 t0->next_table_index);
     364             :                       else
     365             :                         {
     366           0 :                           next0 =
     367           0 :                             (t0->miss_next_index <
     368           0 :                              ACL_NEXT_INDEX_N_NEXT) ? t0->miss_next_index :
     369             :                             next0;
     370             : 
     371           0 :                           misses++;
     372             : 
     373           0 :                           if (is_output)
     374           0 :                             error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     375             :                               L2_OUTACL_ERROR_TABLE_MISS :
     376             :                               L2_OUTACL_ERROR_NONE;
     377             :                           else
     378           0 :                             error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     379             :                               L2_INACL_ERROR_TABLE_MISS : L2_INACL_ERROR_NONE;
     380           0 :                           b0->error = node->errors[error0];
     381           0 :                           break;
     382             :                         }
     383             : 
     384         384 :                       if (t0->current_data_flag ==
     385             :                           CLASSIFY_FLAG_USE_CURR_DATA)
     386           0 :                         h0 =
     387           0 :                           (void *) vlib_buffer_get_current (b0) +
     388           0 :                           t0->current_data_offset;
     389             :                       else
     390         384 :                         h0 = (void *) vlib_buffer_get_current (b0);
     391             : 
     392         384 :                       hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
     393         384 :                       e0 = vnet_classify_find_entry
     394             :                         (t0, (u8 *) h0, hash0, now);
     395         384 :                       if (e0)
     396             :                         {
     397         128 :                           vlib_buffer_advance (b0, e0->advance);
     398         256 :                           next0 = (e0->next_index < ACL_NEXT_INDEX_N_NEXT) ?
     399         128 :                             e0->next_index : next0;
     400         128 :                           hits++;
     401         128 :                           chain_hits++;
     402             : 
     403         128 :                           if (is_output)
     404           0 :                             error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     405             :                               L2_OUTACL_ERROR_SESSION_DENY :
     406             :                               L2_OUTACL_ERROR_NONE;
     407             :                           else
     408         128 :                             error0 = (next0 == ACL_NEXT_INDEX_DENY) ?
     409             :                               L2_INACL_ERROR_SESSION_DENY :
     410             :                               L2_INACL_ERROR_NONE;
     411         128 :                           b0->error = node->errors[error0];
     412         128 :                           break;
     413             :                         }
     414             :                     }
     415             :                 }
     416             :             }
     417             : 
     418         219 :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
     419             :                              && (b0->flags & VLIB_BUFFER_IS_TRACED)))
     420             :             {
     421             :               l2_in_out_acl_trace_t *t =
     422         219 :                 vlib_add_trace (vm, node, b0, sizeof (*t));
     423         219 :               t->sw_if_index =
     424         219 :                 vnet_buffer (b0)->sw_if_index[is_output ? VLIB_TX : VLIB_RX];
     425         219 :               t->next_index = next0;
     426         219 :               t->table_index = t0 ? t0 - vcm->tables : ~0;
     427         219 :               t->offset = (t0 && e0) ? vnet_classify_get_offset (t0, e0) : ~0;
     428             :             }
     429             : 
     430             :           /* verify speculative enqueue, maybe switch current next frame */
     431         219 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     432             :                                            to_next, n_left_to_next,
     433             :                                            bi0, next0);
     434             :         }
     435             : 
     436          33 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     437             :     }
     438             : 
     439          33 :   vlib_node_increment_counter (vm, node->node_index,
     440             :                                is_output ? L2_OUTACL_ERROR_MISS :
     441             :                                L2_INACL_ERROR_MISS, misses);
     442          33 :   vlib_node_increment_counter (vm, node->node_index,
     443             :                                is_output ? L2_OUTACL_ERROR_HIT :
     444             :                                L2_INACL_ERROR_HIT, hits);
     445          33 :   vlib_node_increment_counter (vm, node->node_index,
     446             :                                is_output ? L2_OUTACL_ERROR_CHAIN_HIT :
     447             :                                L2_INACL_ERROR_CHAIN_HIT, chain_hits);
     448          33 :   return frame->n_vectors;
     449             : }
     450             : 
     451        2330 : VLIB_NODE_FN (l2_inacl_node) (vlib_main_t * vm,
     452             :                               vlib_node_runtime_t * node,
     453             :                               vlib_frame_t * frame)
     454             : {
     455          30 :   return l2_in_out_acl_node_fn (vm, node, frame,
     456             :                                 IN_OUT_ACL_INPUT_TABLE_GROUP);
     457             : }
     458             : 
     459        2303 : VLIB_NODE_FN (l2_outacl_node) (vlib_main_t * vm,
     460             :                                vlib_node_runtime_t * node,
     461             :                                vlib_frame_t * frame)
     462             : {
     463           3 :   return l2_in_out_acl_node_fn (vm, node, frame,
     464             :                                 IN_OUT_ACL_OUTPUT_TABLE_GROUP);
     465             : }
     466             : 
     467             : /* *INDENT-OFF* */
     468      183788 : VLIB_REGISTER_NODE (l2_inacl_node) = {
     469             :   .name = "l2-input-acl",
     470             :   .vector_size = sizeof (u32),
     471             :   .format_trace = format_l2_inacl_trace,
     472             :   .type = VLIB_NODE_TYPE_INTERNAL,
     473             : 
     474             :   .n_errors = ARRAY_LEN(l2_inacl_error_strings),
     475             :   .error_strings = l2_inacl_error_strings,
     476             : 
     477             :   .n_next_nodes = ACL_NEXT_INDEX_N_NEXT,
     478             : 
     479             :   /* edit / add dispositions here */
     480             :   .next_nodes = {
     481             :        [ACL_NEXT_INDEX_DENY]  = "error-drop",
     482             :   },
     483             : };
     484             : 
     485      183788 : VLIB_REGISTER_NODE (l2_outacl_node) = {
     486             :   .name = "l2-output-acl",
     487             :   .vector_size = sizeof (u32),
     488             :   .format_trace = format_l2_outacl_trace,
     489             :   .type = VLIB_NODE_TYPE_INTERNAL,
     490             : 
     491             :   .n_errors = ARRAY_LEN(l2_outacl_error_strings),
     492             :   .error_strings = l2_outacl_error_strings,
     493             : 
     494             :   .n_next_nodes = ACL_NEXT_INDEX_N_NEXT,
     495             : 
     496             :   /* edit / add dispositions here */
     497             :   .next_nodes = {
     498             :        [ACL_NEXT_INDEX_DENY]  = "error-drop",
     499             :   },
     500             : };
     501             : /* *INDENT-ON* */
     502             : 
     503             : 
     504             : #ifndef CLIB_MARCH_VARIANT
     505             : clib_error_t *
     506         575 : l2_in_out_acl_init (vlib_main_t * vm)
     507             : {
     508         575 :   l2_in_out_acl_main_t *mp = &l2_in_out_acl_main;
     509             : 
     510         575 :   mp->vlib_main = vm;
     511         575 :   mp->vnet_main = vnet_get_main ();
     512             : 
     513             :   /* Initialize the feature next-node indexes */
     514         575 :   feat_bitmap_init_next_nodes (vm,
     515             :                                l2_inacl_node.index,
     516             :                                L2INPUT_N_FEAT,
     517             :                                l2input_get_feat_names (),
     518             :                                mp->feat_next_node_index
     519         575 :                                [IN_OUT_ACL_INPUT_TABLE_GROUP]);
     520         575 :   feat_bitmap_init_next_nodes (vm, l2_outacl_node.index, L2OUTPUT_N_FEAT,
     521             :                                l2output_get_feat_names (),
     522             :                                mp->feat_next_node_index
     523         575 :                                [IN_OUT_ACL_OUTPUT_TABLE_GROUP]);
     524             : 
     525         575 :   return 0;
     526             : }
     527             : 
     528       22463 : VLIB_INIT_FUNCTION (l2_in_out_acl_init);
     529             : #endif /* CLIB_MARCH_VARIANT */
     530             : 
     531             : /*
     532             :  * fd.io coding-style-patch-verification: ON
     533             :  *
     534             :  * Local Variables:
     535             :  * eval: (c-set-style "gnu")
     536             :  * End:
     537             :  */

Generated by: LCOV version 1.14