LCOV - code coverage report
Current view: top level - plugins/abf - abf_itf_attach.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 174 233 74.7 %
Date: 2023-07-05 22:20:52 Functions: 32 36 88.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <plugins/abf/abf_itf_attach.h>
      17             : #include <vnet/fib/fib_path_list.h>
      18             : #include <plugins/acl/exports.h>
      19             : 
      20             : /**
      21             :  * Forward declarations;
      22             :  */
      23             : extern vlib_node_registration_t abf_ip4_node;
      24             : extern vlib_node_registration_t abf_ip6_node;
      25             : 
      26             : /**
      27             :  * FIB node registered type for the bonds
      28             :  */
      29             : static fib_node_type_t abf_itf_attach_fib_node_type;
      30             : 
      31             : /**
      32             :  * Pool of ABF interface attachment objects
      33             :  */
      34             : abf_itf_attach_t *abf_itf_attach_pool;
      35             : 
      36             : /**
      37             :  * A per interface vector of attached policies. used in the data-plane
      38             :  */
      39             : static u32 **abf_per_itf[FIB_PROTOCOL_MAX];
      40             : 
      41             : /**
      42             :  * Per interface values of ACL lookup context IDs. used in the data-plane
      43             :  */
      44             : static u32 *abf_alctx_per_itf[FIB_PROTOCOL_MAX];
      45             : 
      46             : /**
      47             :  * ABF ACL module user id returned during the initialization
      48             :  */
      49             : static u32 abf_acl_user_id;
      50             : /*
      51             :  * ACL plugin method vtable
      52             :  */
      53             : 
      54             : static acl_plugin_methods_t acl_plugin;
      55             : 
      56             : /**
      57             :  * A DB of attachments; key={abf_index,sw_if_index}
      58             :  */
      59             : static uword *abf_itf_attach_db;
      60             : 
      61             : static u64
      62          32 : abf_itf_attach_mk_key (u32 abf_index, u32 sw_if_index)
      63             : {
      64             :   u64 key;
      65             : 
      66          32 :   key = abf_index;
      67          32 :   key = key << 32;
      68          32 :   key |= sw_if_index;
      69             : 
      70          32 :   return (key);
      71             : }
      72             : 
      73             : static abf_itf_attach_t *
      74          16 : abf_itf_attach_db_find (u32 abf_index, u32 sw_if_index)
      75             : {
      76             :   uword *p;
      77             :   u64 key;
      78             : 
      79          16 :   key = abf_itf_attach_mk_key (abf_index, sw_if_index);
      80             : 
      81          16 :   p = hash_get (abf_itf_attach_db, key);
      82             : 
      83          16 :   if (NULL != p)
      84           8 :     return (pool_elt_at_index (abf_itf_attach_pool, p[0]));
      85             : 
      86           8 :   return (NULL);
      87             : }
      88             : 
      89             : static void
      90           8 : abf_itf_attach_db_add (u32 abf_index, u32 sw_if_index, abf_itf_attach_t * aia)
      91             : {
      92             :   u64 key;
      93             : 
      94           8 :   key = abf_itf_attach_mk_key (abf_index, sw_if_index);
      95             : 
      96           8 :   hash_set (abf_itf_attach_db, key, aia - abf_itf_attach_pool);
      97           8 : }
      98             : 
      99             : static void
     100           8 : abf_itf_attach_db_del (u32 abf_index, u32 sw_if_index)
     101             : {
     102             :   u64 key;
     103             : 
     104           8 :   key = abf_itf_attach_mk_key (abf_index, sw_if_index);
     105             : 
     106           8 :   hash_unset (abf_itf_attach_db, key);
     107           8 : }
     108             : 
     109             : static void
     110          28 : abf_itf_attach_stack (abf_itf_attach_t * aia)
     111             : {
     112             :   /*
     113             :    * stack the DPO on the forwarding contributed by the path-list
     114             :    */
     115          28 :   dpo_id_t via_dpo = DPO_INVALID;
     116             :   abf_policy_t *ap;
     117             : 
     118          28 :   ap = abf_policy_get (aia->aia_abf);
     119             : 
     120          28 :   fib_path_list_contribute_forwarding (ap->ap_pl,
     121          28 :                                        (FIB_PROTOCOL_IP4 == aia->aia_proto ?
     122             :                                         FIB_FORW_CHAIN_TYPE_UNICAST_IP4 :
     123             :                                         FIB_FORW_CHAIN_TYPE_UNICAST_IP6),
     124             :                                        FIB_PATH_LIST_FWD_FLAG_COLLAPSE,
     125             :                                        &via_dpo);
     126             : 
     127          28 :   dpo_stack_from_node ((FIB_PROTOCOL_IP4 == aia->aia_proto ?
     128             :                         abf_ip4_node.index :
     129             :                         abf_ip6_node.index), &aia->aia_dpo, &via_dpo);
     130          28 :   dpo_reset (&via_dpo);
     131          28 : }
     132             : 
     133             : static int
     134           8 : abf_cmp_attach_for_sort (void *v1, void *v2)
     135             : {
     136             :   const abf_itf_attach_t *aia1;
     137             :   const abf_itf_attach_t *aia2;
     138             : 
     139           8 :   aia1 = abf_itf_attach_get (*(u32 *) v1);
     140           8 :   aia2 = abf_itf_attach_get (*(u32 *) v2);
     141             : 
     142           8 :   return (aia1->aia_prio - aia2->aia_prio);
     143             : }
     144             : 
     145             : void
     146          16 : abf_setup_acl_lc (fib_protocol_t fproto, u32 sw_if_index)
     147             : {
     148          16 :   u32 *acl_vec = 0;
     149             :   u32 *aiai;
     150             :   abf_itf_attach_t *aia;
     151             : 
     152          16 :   if (~0 == abf_alctx_per_itf[fproto][sw_if_index])
     153           5 :     return;
     154             : 
     155          29 :   vec_foreach (aiai, abf_per_itf[fproto][sw_if_index])
     156             :   {
     157          18 :     aia = abf_itf_attach_get (*aiai);
     158          18 :     vec_add1 (acl_vec, aia->aia_acl);
     159             :   }
     160          11 :   acl_plugin.set_acl_vec_for_context (abf_alctx_per_itf[fproto][sw_if_index],
     161             :                                       acl_vec);
     162          11 :   vec_free (acl_vec);
     163             : }
     164             : 
     165             : int
     166           8 : abf_itf_attach (fib_protocol_t fproto,
     167             :                 u32 policy_id, u32 priority, u32 sw_if_index)
     168             : {
     169             :   abf_itf_attach_t *aia;
     170             :   abf_policy_t *ap;
     171             :   u32 api, aiai;
     172             : 
     173           8 :   api = abf_policy_find (policy_id);
     174             : 
     175           8 :   ASSERT (INDEX_INVALID != api);
     176           8 :   ap = abf_policy_get (api);
     177             : 
     178             :   /*
     179             :    * check this is not a duplicate
     180             :    */
     181           8 :   aia = abf_itf_attach_db_find (policy_id, sw_if_index);
     182             : 
     183           8 :   if (NULL != aia)
     184           0 :     return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS);
     185             : 
     186             :   /*
     187             :    * construct a new attachment object
     188             :    */
     189           8 :   pool_get (abf_itf_attach_pool, aia);
     190             : 
     191           8 :   fib_node_init (&aia->aia_node, abf_itf_attach_fib_node_type);
     192           8 :   aia->aia_prio = priority;
     193           8 :   aia->aia_proto = fproto;
     194           8 :   aia->aia_acl = ap->ap_acl;
     195           8 :   aia->aia_abf = api;
     196           8 :   aia->aia_sw_if_index = sw_if_index;
     197           8 :   aiai = aia - abf_itf_attach_pool;
     198           8 :   abf_itf_attach_db_add (policy_id, sw_if_index, aia);
     199             : 
     200             :   /*
     201             :    * stack the DPO on the forwarding contributed by the path-list
     202             :    */
     203           8 :   abf_itf_attach_stack (aia);
     204             : 
     205             :   /*
     206             :    * Insert the policy on the interfaces list.
     207             :    */
     208          13 :   vec_validate_init_empty (abf_per_itf[fproto], sw_if_index, NULL);
     209           8 :   vec_add1 (abf_per_itf[fproto][sw_if_index], aia - abf_itf_attach_pool);
     210           8 :   if (1 == vec_len (abf_per_itf[fproto][sw_if_index]))
     211             :     {
     212             :       /*
     213             :        * when enabling the first ABF policy on the interface
     214             :        * we need to enable the interface input feature
     215             :        */
     216           5 :       vnet_feature_enable_disable ((FIB_PROTOCOL_IP4 == fproto ?
     217             :                                     "ip4-unicast" :
     218             :                                     "ip6-unicast"),
     219             :                                    (FIB_PROTOCOL_IP4 == fproto ?
     220             :                                     "abf-input-ip4" :
     221             :                                     "abf-input-ip6"),
     222             :                                    sw_if_index, 1, NULL, 0);
     223             : 
     224             :       /* if this is the first ABF policy, we need to acquire an ACL lookup context */
     225          10 :       vec_validate_init_empty (abf_alctx_per_itf[fproto], sw_if_index, ~0);
     226           5 :       abf_alctx_per_itf[fproto][sw_if_index] =
     227           5 :         acl_plugin.get_lookup_context_index (abf_acl_user_id, sw_if_index, 0);
     228             :     }
     229             :   else
     230             :     {
     231           3 :       vec_sort_with_function (abf_per_itf[fproto][sw_if_index],
     232             :                               abf_cmp_attach_for_sort);
     233             :     }
     234             : 
     235             :   /* Prepare and set the list of ACLs for lookup within the context */
     236           8 :   abf_setup_acl_lc (fproto, sw_if_index);
     237             : 
     238             :   /*
     239             :    * become a child of the ABF policy so we are notified when
     240             :    * its forwarding changes.
     241             :    */
     242           8 :   aia->aia_sibling = fib_node_child_add (abf_policy_fib_node_type,
     243             :                                          api,
     244             :                                          abf_itf_attach_fib_node_type, aiai);
     245             : 
     246           8 :   return (0);
     247             : }
     248             : 
     249             : int
     250           8 : abf_itf_detach (fib_protocol_t fproto, u32 policy_id, u32 sw_if_index)
     251             : {
     252             :   abf_itf_attach_t *aia;
     253             :   u32 index;
     254             : 
     255             :   /*
     256             :    * check this is a valid attachment
     257             :    */
     258           8 :   aia = abf_itf_attach_db_find (policy_id, sw_if_index);
     259             : 
     260           8 :   if (NULL == aia)
     261           0 :     return (VNET_API_ERROR_NO_SUCH_ENTRY);
     262             : 
     263             :   /*
     264             :    * first remove from the interface's vector
     265             :    */
     266           8 :   ASSERT (abf_per_itf[fproto]);
     267           8 :   ASSERT (abf_per_itf[fproto][sw_if_index]);
     268             : 
     269           8 :   index = vec_search (abf_per_itf[fproto][sw_if_index],
     270             :                       aia - abf_itf_attach_pool);
     271             : 
     272           8 :   ASSERT (index != ~0);
     273           8 :   vec_del1 (abf_per_itf[fproto][sw_if_index], index);
     274             : 
     275           8 :   if (0 == vec_len (abf_per_itf[fproto][sw_if_index]))
     276             :     {
     277             :       /*
     278             :        * when deleting the last ABF policy on the interface
     279             :        * we need to disable the interface input feature
     280             :        */
     281           5 :       vnet_feature_enable_disable ((FIB_PROTOCOL_IP4 == fproto ?
     282             :                                     "ip4-unicast" :
     283             :                                     "ip6-unicast"),
     284             :                                    (FIB_PROTOCOL_IP4 == fproto ?
     285             :                                     "abf-input-ip4" :
     286             :                                     "abf-input-ip6"),
     287             :                                    sw_if_index, 0, NULL, 0);
     288             : 
     289             :       /* Return the lookup context, invalidate its id in our records */
     290           5 :       acl_plugin.put_lookup_context_index (abf_alctx_per_itf[fproto]
     291           5 :                                            [sw_if_index]);
     292           5 :       abf_alctx_per_itf[fproto][sw_if_index] = ~0;
     293             :     }
     294             :   else
     295             :     {
     296           3 :       vec_sort_with_function (abf_per_itf[fproto][sw_if_index],
     297             :                               abf_cmp_attach_for_sort);
     298             :     }
     299             : 
     300             :   /* Prepare and set the list of ACLs for lookup within the context */
     301           8 :   abf_setup_acl_lc (fproto, sw_if_index);
     302             : 
     303             :   /*
     304             :    * remove the dependency on the policy
     305             :    */
     306           8 :   fib_node_child_remove (abf_policy_fib_node_type,
     307             :                          aia->aia_abf, aia->aia_sibling);
     308             : 
     309             :   /*
     310             :    * remove the attachment from the DB
     311             :    */
     312           8 :   abf_itf_attach_db_del (policy_id, sw_if_index);
     313             : 
     314             :   /*
     315             :    * release our locks on FIB forwarding data
     316             :    */
     317           8 :   dpo_reset (&aia->aia_dpo);
     318             : 
     319             :   /*
     320             :    * return the object
     321             :    */
     322           8 :   pool_put (abf_itf_attach_pool, aia);
     323             : 
     324           8 :   return (0);
     325             : }
     326             : 
     327             : static u8 *
     328           0 : format_abf_intf_attach (u8 * s, va_list * args)
     329             : {
     330           0 :   abf_itf_attach_t *aia = va_arg (*args, abf_itf_attach_t *);
     331             :   abf_policy_t *ap;
     332             : 
     333           0 :   ap = abf_policy_get (aia->aia_abf);
     334           0 :   s = format (s, "abf-interface-attach: policy:%d priority:%d",
     335             :               ap->ap_id, aia->aia_prio);
     336           0 :   s = format (s, "\n  %U", format_dpo_id, &aia->aia_dpo, 2);
     337             : 
     338           0 :   return (s);
     339             : }
     340             : 
     341             : static clib_error_t *
     342           0 : abf_itf_attach_cmd (vlib_main_t * vm,
     343             :                     unformat_input_t * input, vlib_cli_command_t * cmd)
     344             : {
     345             :   u32 policy_id, sw_if_index;
     346             :   fib_protocol_t fproto;
     347             :   u32 is_del, priority;
     348             :   vnet_main_t *vnm;
     349             : 
     350           0 :   is_del = 0;
     351           0 :   sw_if_index = policy_id = ~0;
     352           0 :   vnm = vnet_get_main ();
     353           0 :   fproto = FIB_PROTOCOL_MAX;
     354           0 :   priority = 0;
     355             : 
     356           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     357             :     {
     358           0 :       if (unformat (input, "del"))
     359           0 :         is_del = 1;
     360           0 :       else if (unformat (input, "add"))
     361           0 :         is_del = 0;
     362           0 :       else if (unformat (input, "ip4"))
     363           0 :         fproto = FIB_PROTOCOL_IP4;
     364           0 :       else if (unformat (input, "ip6"))
     365           0 :         fproto = FIB_PROTOCOL_IP6;
     366           0 :       else if (unformat (input, "policy %d", &policy_id))
     367             :         ;
     368           0 :       else if (unformat (input, "priority %d", &priority))
     369             :         ;
     370           0 :       else if (unformat (input, "%U",
     371             :                          unformat_vnet_sw_interface, vnm, &sw_if_index))
     372             :         ;
     373             :       else
     374           0 :         return (clib_error_return (0, "unknown input '%U'",
     375             :                                    format_unformat_error, input));
     376             :     }
     377             : 
     378           0 :   if (~0 == policy_id)
     379             :     {
     380           0 :       return (clib_error_return (0, "invalid policy ID:%d", policy_id));
     381             :     }
     382           0 :   if (~0 == sw_if_index)
     383             :     {
     384           0 :       return (clib_error_return (0, "invalid interface name"));
     385             :     }
     386           0 :   if (FIB_PROTOCOL_MAX == fproto)
     387             :     {
     388           0 :       return (clib_error_return (0, "Specify either ip4 or ip6"));
     389             :     }
     390             : 
     391           0 :   if (~0 == abf_policy_find (policy_id))
     392           0 :     return (clib_error_return (0, "invalid policy ID:%d", policy_id));
     393             : 
     394           0 :   if (is_del)
     395           0 :     abf_itf_detach (fproto, policy_id, sw_if_index);
     396             :   else
     397           0 :     abf_itf_attach (fproto, policy_id, priority, sw_if_index);
     398             : 
     399           0 :   return (NULL);
     400             : }
     401             : 
     402             : /* *INDENT-OFF* */
     403             : /**
     404             :  * Attach an ABF policy to an interface.
     405             :  */
     406      270647 : VLIB_CLI_COMMAND (abf_itf_attach_cmd_node, static) = {
     407             :   .path = "abf attach",
     408             :   .function = abf_itf_attach_cmd,
     409             :   .short_help = "abf attach <ip4|ip6> [del] policy <value> <interface>",
     410             :   // this is not MP safe
     411             : };
     412             : /* *INDENT-ON* */
     413             : 
     414             : static clib_error_t *
     415           0 : abf_show_attach_cmd (vlib_main_t * vm,
     416             :                      unformat_input_t * input, vlib_cli_command_t * cmd)
     417             : {
     418             :   const abf_itf_attach_t *aia;
     419             :   u32 sw_if_index, *aiai;
     420             :   fib_protocol_t fproto;
     421             :   vnet_main_t *vnm;
     422             : 
     423           0 :   sw_if_index = ~0;
     424           0 :   vnm = vnet_get_main ();
     425             : 
     426           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     427             :     {
     428           0 :       if (unformat (input, "%U",
     429             :                     unformat_vnet_sw_interface, vnm, &sw_if_index))
     430             :         ;
     431             :       else
     432           0 :         return (clib_error_return (0, "unknown input '%U'",
     433             :                                    format_unformat_error, input));
     434             :     }
     435             : 
     436           0 :   if (~0 == sw_if_index)
     437             :     {
     438           0 :       vlib_cli_output (vm, "specify an interface");
     439             :     }
     440             : 
     441             :   /* *INDENT-OFF* */
     442           0 :   FOR_EACH_FIB_IP_PROTOCOL(fproto)
     443             :   {
     444           0 :     if (sw_if_index < vec_len(abf_per_itf[fproto]))
     445             :       {
     446           0 :         if (vec_len(abf_per_itf[fproto][sw_if_index]))
     447           0 :           vlib_cli_output(vm, "%U:", format_fib_protocol, fproto);
     448             : 
     449           0 :         vec_foreach(aiai, abf_per_itf[fproto][sw_if_index])
     450             :           {
     451           0 :             aia = pool_elt_at_index(abf_itf_attach_pool, *aiai);
     452           0 :             vlib_cli_output(vm, " %U", format_abf_intf_attach, aia);
     453             :           }
     454             :       }
     455             :   }
     456             :   /* *INDENT-ON* */
     457           0 :   return (NULL);
     458             : }
     459             : 
     460             : /* *INDENT-OFF* */
     461      270647 : VLIB_CLI_COMMAND (abf_show_attach_cmd_node, static) = {
     462             :   .path = "show abf attach",
     463             :   .function = abf_show_attach_cmd,
     464             :   .short_help = "show abf attach <interface>",
     465             :   .is_mp_safe = 1,
     466             : };
     467             : /* *INDENT-ON* */
     468             : 
     469             : void
     470          14 : abf_itf_attach_walk (abf_itf_attach_walk_cb_t cb, void *ctx)
     471             : {
     472             :   u32 aii;
     473             : 
     474             :   /* *INDENT-OFF* */
     475          29 :   pool_foreach_index (aii, abf_itf_attach_pool)
     476             :    {
     477          15 :     if (!cb(aii, ctx))
     478           0 :       break;
     479             :   }
     480             :   /* *INDENT-ON* */
     481          14 : }
     482             : 
     483             : typedef enum abf_next_t_
     484             : {
     485             :   ABF_NEXT_DROP,
     486             :   ABF_N_NEXT,
     487             : } abf_next_t;
     488             : 
     489             : typedef struct abf_input_trace_t_
     490             : {
     491             :   abf_next_t next;
     492             :   index_t index;
     493             : } abf_input_trace_t;
     494             : 
     495             : typedef enum
     496             : {
     497             : #define abf_error(n,s) ABF_ERROR_##n,
     498             : #include "abf_error.def"
     499             : #undef abf_error
     500             :   ABF_N_ERROR,
     501             : } abf_error_t;
     502             : 
     503             : always_inline uword
     504          11 : abf_input_inline (vlib_main_t * vm,
     505             :                   vlib_node_runtime_t * node,
     506             :                   vlib_frame_t * frame, fib_protocol_t fproto)
     507             : {
     508             :   u32 n_left_from, *from, *to_next, next_index, matches, misses;
     509             : 
     510          11 :   from = vlib_frame_vector_args (frame);
     511          11 :   n_left_from = frame->n_vectors;
     512          11 :   next_index = node->cached_next_index;
     513          11 :   matches = misses = 0;
     514             : 
     515          22 :   while (n_left_from > 0)
     516             :     {
     517             :       u32 n_left_to_next;
     518             : 
     519          11 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     520             : 
     521         748 :       while (n_left_from > 0 && n_left_to_next > 0)
     522             :         {
     523             :           const u32 *attachments0;
     524             :           const abf_itf_attach_t *aia0;
     525         737 :           abf_next_t next0 = ABF_NEXT_DROP;
     526             :           vlib_buffer_t *b0;
     527             :           u32 bi0, sw_if_index0;
     528             :           fa_5tuple_opaque_t fa_5tuple0;
     529         737 :           u32 match_acl_index = ~0;
     530         737 :           u32 match_acl_pos = ~0;
     531         737 :           u32 match_rule_index = ~0;
     532         737 :           u32 trace_bitmap = 0;
     533             :           u32 lc_index;
     534             :           u8 action;
     535             : 
     536         737 :           bi0 = from[0];
     537         737 :           to_next[0] = bi0;
     538         737 :           from += 1;
     539         737 :           to_next += 1;
     540         737 :           n_left_from -= 1;
     541         737 :           n_left_to_next -= 1;
     542             : 
     543         737 :           b0 = vlib_get_buffer (vm, bi0);
     544         737 :           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
     545             : 
     546         737 :           ASSERT (vec_len (abf_per_itf[fproto]) > sw_if_index0);
     547         737 :           attachments0 = abf_per_itf[fproto][sw_if_index0];
     548             : 
     549         737 :           ASSERT (vec_len (abf_alctx_per_itf[fproto]) > sw_if_index0);
     550             :           /*
     551             :            * check if any of the policies attached to this interface matches.
     552             :            */
     553         737 :           lc_index = abf_alctx_per_itf[fproto][sw_if_index0];
     554             : 
     555             :           /*
     556             :              A non-inline version looks like this:
     557             : 
     558             :              acl_plugin.fill_5tuple (lc_index, b0, (FIB_PROTOCOL_IP6 == fproto),
     559             :              1, 0, &fa_5tuple0);
     560             :              if (acl_plugin.match_5tuple
     561             :              (lc_index, &fa_5tuple0, (FIB_PROTOCOL_IP6 == fproto), &action,
     562             :              &match_acl_pos, &match_acl_index, &match_rule_index,
     563             :              &trace_bitmap))
     564             :              . . .
     565             :            */
     566         737 :           acl_plugin_fill_5tuple_inline (acl_plugin.p_acl_main, lc_index, b0,
     567             :                                          (FIB_PROTOCOL_IP6 == fproto), 1, 0,
     568             :                                          &fa_5tuple0);
     569             : 
     570         737 :           if (acl_plugin_match_5tuple_inline (
     571             :                 acl_plugin.p_acl_main, lc_index, &fa_5tuple0,
     572             :                 (FIB_PROTOCOL_IP6 == fproto), &action, &match_acl_pos,
     573         737 :                 &match_acl_index, &match_rule_index, &trace_bitmap) &&
     574         737 :               action > 0)
     575             :             {
     576             :               /*
     577             :                * match:
     578             :                *  follow the DPO chain
     579             :                */
     580         603 :               aia0 = abf_itf_attach_get (attachments0[match_acl_pos]);
     581             : 
     582         603 :               next0 = aia0->aia_dpo.dpoi_next_node;
     583         603 :               vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
     584         603 :                 aia0->aia_dpo.dpoi_index;
     585         603 :               matches++;
     586             :             }
     587             :           else
     588             :             {
     589             :               /*
     590             :                * miss:
     591             :                *  move on down the feature arc
     592             :                */
     593         134 :               vnet_feature_next (&next0, b0);
     594         134 :               misses++;
     595             :             }
     596             : 
     597         737 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     598             :             {
     599             :               abf_input_trace_t *tr;
     600             : 
     601         737 :               tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     602         737 :               tr->next = next0;
     603         737 :               tr->index = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
     604             :             }
     605             : 
     606             :           /* verify speculative enqueue, maybe switch current next frame */
     607         737 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     608             :                                            to_next, n_left_to_next, bi0,
     609             :                                            next0);
     610             :         }
     611             : 
     612          11 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     613             :     }
     614             : 
     615          11 :   vlib_node_increment_counter (vm,
     616          11 :                                (fproto = FIB_PROTOCOL_IP6 ?
     617          11 :                                 abf_ip4_node.index :
     618             :                                 abf_ip6_node.index),
     619             :                                ABF_ERROR_MATCHED, matches);
     620          11 :   vlib_node_increment_counter (vm,
     621          11 :                                (fproto = FIB_PROTOCOL_IP6 ?
     622          11 :                                 abf_ip4_node.index :
     623             :                                 abf_ip6_node.index),
     624             :                                ABF_ERROR_MISSED, misses);
     625             : 
     626          11 :   return frame->n_vectors;
     627             : }
     628             : 
     629             : static uword
     630           8 : abf_input_ip4 (vlib_main_t * vm,
     631             :                vlib_node_runtime_t * node, vlib_frame_t * frame)
     632             : {
     633           8 :   return abf_input_inline (vm, node, frame, FIB_PROTOCOL_IP4);
     634             : }
     635             : 
     636             : static uword
     637           3 : abf_input_ip6 (vlib_main_t * vm,
     638             :                vlib_node_runtime_t * node, vlib_frame_t * frame)
     639             : {
     640           3 :   return abf_input_inline (vm, node, frame, FIB_PROTOCOL_IP6);
     641             : }
     642             : 
     643             : static u8 *
     644         818 : format_abf_input_trace (u8 * s, va_list * args)
     645             : {
     646         818 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     647         818 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     648         818 :   abf_input_trace_t *t = va_arg (*args, abf_input_trace_t *);
     649             : 
     650         818 :   s = format (s, " next %d index %d", t->next, t->index);
     651         818 :   return s;
     652             : }
     653             : 
     654             : static char *abf_error_strings[] = {
     655             : #define abf_error(n,s) s,
     656             : #include "abf_error.def"
     657             : #undef abf_error
     658             : };
     659             : 
     660             : /* *INDENT-OFF* */
     661      177000 : VLIB_REGISTER_NODE (abf_ip4_node) =
     662             : {
     663             :   .function = abf_input_ip4,
     664             :   .name = "abf-input-ip4",
     665             :   .vector_size = sizeof (u32),
     666             :   .format_trace = format_abf_input_trace,
     667             :   .type = VLIB_NODE_TYPE_INTERNAL,
     668             :   .n_errors = ABF_N_ERROR,
     669             :   .error_strings = abf_error_strings,
     670             :   .n_next_nodes = ABF_N_NEXT,
     671             :   .next_nodes =
     672             :   {
     673             :     [ABF_NEXT_DROP] = "error-drop",
     674             :   }
     675             : };
     676             : 
     677      177000 : VLIB_REGISTER_NODE (abf_ip6_node) =
     678             : {
     679             :   .function = abf_input_ip6,
     680             :   .name = "abf-input-ip6",
     681             :   .vector_size = sizeof (u32),
     682             :   .format_trace = format_abf_input_trace,
     683             :   .type = VLIB_NODE_TYPE_INTERNAL,
     684             :   .n_errors = 0,
     685             :   .n_next_nodes = ABF_N_NEXT,
     686             : 
     687             :   .next_nodes =
     688             :   {
     689             :     [ABF_NEXT_DROP] = "error-drop",
     690             :   }
     691             : };
     692             : 
     693       69463 : VNET_FEATURE_INIT (abf_ip4_feat, static) =
     694             : {
     695             :   .arc_name = "ip4-unicast",
     696             :   .node_name = "abf-input-ip4",
     697             :   .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
     698             : };
     699             : 
     700       69463 : VNET_FEATURE_INIT (abf_ip6_feat, static) =
     701             : {
     702             :   .arc_name = "ip6-unicast",
     703             :   .node_name = "abf-input-ip6",
     704             :   .runs_after = VNET_FEATURES ("acl-plugin-in-ip6-fa"),
     705             : };
     706             : /* *INDENT-ON* */
     707             : 
     708             : static fib_node_t *
     709          20 : abf_itf_attach_get_node (fib_node_index_t index)
     710             : {
     711          20 :   abf_itf_attach_t *aia = abf_itf_attach_get (index);
     712          20 :   return (&(aia->aia_node));
     713             : }
     714             : 
     715             : static abf_itf_attach_t *
     716          20 : abf_itf_attach_get_from_node (fib_node_t * node)
     717             : {
     718          20 :   return ((abf_itf_attach_t *) (((char *) node) -
     719             :                                 STRUCT_OFFSET_OF (abf_itf_attach_t,
     720             :                                                   aia_node)));
     721             : }
     722             : 
     723             : static void
     724           0 : abf_itf_attach_last_lock_gone (fib_node_t * node)
     725             : {
     726             :   /*
     727             :    * ABF interface attachments are leaves on the graph.
     728             :    * we do not manage locks from children.
     729             :    */
     730           0 : }
     731             : 
     732             : /*
     733             :  * abf_itf_attach_back_walk_notify
     734             :  *
     735             :  * A back walk has reached this BIER fmask
     736             :  */
     737             : static fib_node_back_walk_rc_t
     738          20 : abf_itf_attach_back_walk_notify (fib_node_t * node,
     739             :                                  fib_node_back_walk_ctx_t * ctx)
     740             : {
     741             :   /*
     742             :    * re-stack the fmask on the n-eos of the via
     743             :    */
     744          20 :   abf_itf_attach_t *aia = abf_itf_attach_get_from_node (node);
     745             : 
     746          20 :   abf_itf_attach_stack (aia);
     747             : 
     748          20 :   return (FIB_NODE_BACK_WALK_CONTINUE);
     749             : }
     750             : 
     751             : /*
     752             :  * The BIER fmask's graph node virtual function table
     753             :  */
     754             : static const fib_node_vft_t abf_itf_attach_vft = {
     755             :   .fnv_get = abf_itf_attach_get_node,
     756             :   .fnv_last_lock = abf_itf_attach_last_lock_gone,
     757             :   .fnv_back_walk = abf_itf_attach_back_walk_notify,
     758             : };
     759             : 
     760             : static clib_error_t *
     761         559 : abf_itf_bond_init (vlib_main_t * vm)
     762             : {
     763         559 :   abf_itf_attach_fib_node_type =
     764         559 :     fib_node_register_new_type ("abf-attach", &abf_itf_attach_vft);
     765         559 :   clib_error_t *acl_init_res = acl_plugin_exports_init (&acl_plugin);
     766         559 :   if (acl_init_res)
     767           0 :     return (acl_init_res);
     768             : 
     769         559 :   abf_acl_user_id =
     770         559 :     acl_plugin.register_user_module ("ABF plugin", "sw_if_index", NULL);
     771             : 
     772         559 :   return (NULL);
     773             : }
     774             : 
     775             : /* *INDENT-OFF* */
     776        1679 : VLIB_INIT_FUNCTION (abf_itf_bond_init) =
     777             : {
     778             :   .runs_after = VLIB_INITS("acl_init"),
     779             : };
     780             : /* *INDENT-ON* */
     781             : 
     782             : /*
     783             :  * fd.io coding-style-patch-verification: ON
     784             :  *
     785             :  * Local Variables:
     786             :  * eval: (c-set-style "gnu")
     787             :  * End:
     788             :  */

Generated by: LCOV version 1.14