LCOV - code coverage report
Current view: top level - vnet/ip - ip_punt_drop.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 85 91 93.4 %
Date: 2023-10-26 01:39:38 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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 <vnet/ip/ip.h>
      17             : #include <vnet/ip/ip_punt_drop.h>
      18             : #include <vnet/fib/fib_path_list.h>
      19             : 
      20             : ip_punt_redirect_cfg_t ip_punt_redirect_cfg;
      21             : 
      22             : u8 *
      23        5118 : format_ip_punt_redirect_trace (u8 * s, va_list * args)
      24             : {
      25        5118 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      26        5118 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      27        5118 :   ip_punt_redirect_trace_t *t = va_arg (*args, ip_punt_redirect_trace_t *);
      28             : 
      29        5118 :   if (INDEX_INVALID == t->rrxi)
      30           0 :     s = format (s, "ignore");
      31             :   else
      32        5118 :     s = format (s, "via redirect:%d", t->rrxi);
      33             : 
      34        5118 :   return s;
      35             : }
      36             : 
      37             : static void
      38          96 : ip_punt_redirect_stack (ip_punt_redirect_rx_t * ipr)
      39             : {
      40          96 :   dpo_id_t dpo = DPO_INVALID;
      41             :   vlib_node_t *pnode;
      42             : 
      43          96 :   fib_path_list_contribute_forwarding (ipr->pl,
      44          96 :                                        ipr->payload_type,
      45             :                                        FIB_PATH_LIST_FWD_FLAG_COLLAPSE, &dpo);
      46             : 
      47          96 :   if (FIB_PROTOCOL_IP4 == ipr->fproto)
      48             :     pnode =
      49          49 :       vlib_get_node_by_name (vlib_get_main (), (u8 *) "ip4-punt-redirect");
      50             :   else
      51             :     pnode =
      52          47 :       vlib_get_node_by_name (vlib_get_main (), (u8 *) "ip6-punt-redirect");
      53             : 
      54          96 :   dpo_stack_from_node (pnode->index, &ipr->dpo, &dpo);
      55          96 :   dpo_reset (&dpo);
      56          96 : }
      57             : 
      58             : index_t
      59          50 : ip_punt_redirect_find (fib_protocol_t fproto, u32 rx_sw_if_index)
      60             : {
      61             :   index_t *rxs;
      62             : 
      63          50 :   rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
      64             : 
      65          50 :   if (vec_len (rxs) <= rx_sw_if_index)
      66           0 :     return (INDEX_INVALID);
      67             : 
      68          50 :   return rxs[rx_sw_if_index];
      69             : }
      70             : 
      71             : void
      72          39 : ip_punt_redirect_add (fib_protocol_t fproto, u32 rx_sw_if_index,
      73             :                       fib_forward_chain_type_t ct,
      74             :                       const fib_route_path_t *rpaths)
      75             : {
      76             :   ip_punt_redirect_rx_t *ipr;
      77             :   index_t ipri;
      78             : 
      79          39 :   if (~0 == rx_sw_if_index)
      80           3 :     rx_sw_if_index = 0;
      81             : 
      82         107 :   vec_validate_init_empty (ip_punt_redirect_cfg.redirect_by_rx_sw_if_index
      83             :                            [fproto], rx_sw_if_index, INDEX_INVALID);
      84             : 
      85          39 :   pool_get (ip_punt_redirect_cfg.pool, ipr);
      86          39 :   ipri = ipr - ip_punt_redirect_cfg.pool;
      87             : 
      88          39 :   ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto][rx_sw_if_index] =
      89             :     ipri;
      90             : 
      91          39 :   fib_node_init (&ipr->node, FIB_NODE_TYPE_IP_PUNT_REDIRECT);
      92          39 :   ipr->fproto = fproto;
      93          39 :   ipr->payload_type = ct;
      94             : 
      95          39 :   ipr->pl = fib_path_list_create (FIB_PATH_LIST_FLAG_NO_URPF, rpaths);
      96             : 
      97          39 :   ipr->sibling = fib_path_list_child_add (ipr->pl,
      98             :                                           FIB_NODE_TYPE_IP_PUNT_REDIRECT,
      99             :                                           ipri);
     100             : 
     101          39 :   ip_punt_redirect_stack (ipr);
     102          39 : }
     103             : 
     104             : void
     105          37 : ip_punt_redirect_del (fib_protocol_t fproto, u32 rx_sw_if_index)
     106             : {
     107             :   ip_punt_redirect_rx_t *ipr;
     108             :   index_t *rxs;
     109             : 
     110          37 :   if (~0 == rx_sw_if_index)
     111           3 :     rx_sw_if_index = 0;
     112             : 
     113          37 :   rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
     114             : 
     115          37 :   if ((vec_len (rxs) <= rx_sw_if_index) ||
     116          37 :       (INDEX_INVALID == rxs[rx_sw_if_index]))
     117           0 :     return;
     118             : 
     119          37 :   ipr = ip_punt_redirect_get (rxs[rx_sw_if_index]);
     120             : 
     121          37 :   fib_path_list_child_remove (ipr->pl, ipr->sibling);
     122          37 :   dpo_reset (&ipr->dpo);
     123          37 :   pool_put (ip_punt_redirect_cfg.pool, ipr);
     124             : 
     125          37 :   rxs[rx_sw_if_index] = INDEX_INVALID;
     126             : }
     127             : 
     128             : u8 *
     129           2 : format_ip_punt_redirect (u8 * s, va_list * args)
     130             : {
     131           2 :   fib_protocol_t fproto = va_arg (*args, int);
     132             :   ip_punt_redirect_rx_t *rx;
     133             :   index_t *rxs;
     134             :   u32 rx_sw_if_index;
     135           2 :   vnet_main_t *vnm = vnet_get_main ();
     136             : 
     137           2 :   rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
     138             : 
     139          18 :   vec_foreach_index (rx_sw_if_index, rxs)
     140             :   {
     141          16 :     if (INDEX_INVALID == rxs[rx_sw_if_index])
     142          13 :       continue;
     143             : 
     144           3 :     rx = ip_punt_redirect_get (rxs[rx_sw_if_index]);
     145             : 
     146           3 :     s = format (s, " rx %U via:\n",
     147             :                 format_vnet_sw_interface_name, vnm,
     148             :                 vnet_get_sw_interface (vnm, rx_sw_if_index));
     149           3 :     s = format (s, " %U", format_fib_path_list, rx->pl, 2);
     150           3 :     s = format (s, " forwarding\n", format_dpo_id, &rx->dpo, 0);
     151           3 :     s = format (s, "  %U\n", format_dpo_id, &rx->dpo, 0);
     152             :   }
     153             : 
     154           2 :   return (s);
     155             : }
     156             : 
     157             : void
     158           6 : ip_punt_redirect_walk (fib_protocol_t fproto,
     159             :                        ip_punt_redirect_walk_cb_t cb, void *ctx)
     160             : {
     161             :   ip_punt_redirect_rx_t *rx;
     162             :   u32 ii, rx_sw_if_index;
     163             :   index_t *rxs;
     164             : 
     165           6 :   rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
     166             : 
     167          24 :   vec_foreach_index (ii, rxs)
     168             :   {
     169          18 :     if (INDEX_INVALID == rxs[ii])
     170           9 :       continue;
     171             : 
     172           9 :     rx = ip_punt_redirect_get (rxs[ii]);
     173             : 
     174           9 :     rx_sw_if_index = (ii == 0 ? ~0 : ii);
     175           9 :     cb (rx_sw_if_index, rx, ctx);
     176             :   }
     177           6 : }
     178             : 
     179             : static fib_node_t *
     180          57 : ip_punt_redirect_get_node (fib_node_index_t index)
     181             : {
     182          57 :   ip_punt_redirect_rx_t *ipr = ip_punt_redirect_get (index);
     183          57 :   return (&(ipr->node));
     184             : }
     185             : 
     186             : static ip_punt_redirect_rx_t *
     187          57 : ip_punt_redirect_get_from_node (fib_node_t * node)
     188             : {
     189          57 :   return ((ip_punt_redirect_rx_t *) (((char *) node) -
     190             :                                      STRUCT_OFFSET_OF (ip_punt_redirect_rx_t,
     191             :                                                        node)));
     192             : }
     193             : 
     194             : static void
     195           0 : ip_punt_redirect_last_lock_gone (fib_node_t * node)
     196             : {
     197             :   /*
     198             :    * the lifetime of the entry is managed by the table.
     199             :    */
     200           0 :   ASSERT (0);
     201           0 : }
     202             : 
     203             : /*
     204             :  * A back walk has reached this BIER entry
     205             :  */
     206             : static fib_node_back_walk_rc_t
     207          57 : ip_punt_redirect_back_walk_notify (fib_node_t * node,
     208             :                                    fib_node_back_walk_ctx_t * ctx)
     209             : {
     210             :   /*
     211             :    * re-populate the ECMP tables with new choices
     212             :    */
     213          57 :   ip_punt_redirect_rx_t *ipr = ip_punt_redirect_get_from_node (node);
     214             : 
     215          57 :   ip_punt_redirect_stack (ipr);
     216             : 
     217             :   /*
     218             :    * no need to propagate further up the graph, since there's nothing there
     219             :    */
     220          57 :   return (FIB_NODE_BACK_WALK_CONTINUE);
     221             : }
     222             : 
     223             : /*
     224             :  * The BIER fmask's graph node virtual function table
     225             :  */
     226             : static const fib_node_vft_t ip_punt_redirect_vft = {
     227             :   .fnv_get = ip_punt_redirect_get_node,
     228             :   .fnv_last_lock = ip_punt_redirect_last_lock_gone,
     229             :   .fnv_back_walk = ip_punt_redirect_back_walk_notify,
     230             : };
     231             : 
     232             : static clib_error_t *
     233         575 : ip_punt_drop_init (vlib_main_t * vm)
     234             : {
     235         575 :   fib_node_register_type (FIB_NODE_TYPE_IP_PUNT_REDIRECT,
     236             :                           &ip_punt_redirect_vft);
     237             : 
     238         575 :   ip4_punt_policer_cfg.fq_index =
     239         575 :     vlib_frame_queue_main_init (ip4_punt_policer_node.index, 0);
     240         575 :   ip6_punt_policer_cfg.fq_index =
     241         575 :     vlib_frame_queue_main_init (ip6_punt_policer_node.index, 0);
     242             : 
     243         575 :   return (NULL);
     244             : }
     245             : 
     246       46655 : VLIB_INIT_FUNCTION (ip_punt_drop_init);
     247             : 
     248             : /*
     249             :  * fd.io coding-style-patch-verification: ON
     250             :  *
     251             :  * Local Variables:
     252             :  * eval: (c-set-style "gnu")
     253             :  * End:
     254             :  */

Generated by: LCOV version 1.14