LCOV - code coverage report
Current view: top level - plugins/unittest - punt_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 107 116 92.2 %
Date: 2023-07-05 22:20:52 Functions: 28 29 96.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 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/vnet.h>
      17             : #include <vnet/adj/rewrite.h>
      18             : #include <vnet/ethernet/ethernet.h>
      19             : #include <vnet/adj/adj.h>
      20             : #include <vnet/ip/ip.h>
      21             : #include <vnet/ip/punt.h>
      22             : 
      23             : typedef enum punt_next_t_
      24             : {
      25             :   PUNT_NEXT_DROP,
      26             :   PUNT_N_NEXT,
      27             : } punt_next_t;
      28             : 
      29             : typedef struct punt_trace_t_
      30             : {
      31             :   vlib_punt_reason_t pt_reason;
      32             : } punt_trace_t;
      33             : 
      34             : #define SW_IF_INDEX_PG0 1
      35             : #define SW_IF_INDEX_PG1 2
      36             : 
      37             : index_t *adjs[FIB_PROTOCOL_IP_MAX];
      38             : 
      39             : static vlib_punt_reason_t punt_reason_v4, punt_reason_v6;
      40             : static vlib_punt_hdl_t punt_hdl;
      41             : 
      42             : static u8 *
      43           0 : format_punt_trace (u8 * s, va_list * args)
      44             : {
      45           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      46           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      47           0 :   punt_trace_t *t = va_arg (*args, punt_trace_t *);
      48             : 
      49           0 :   s = format (s, "punt: %U", format_vlib_punt_reason, t->pt_reason);
      50             : 
      51           0 :   return s;
      52             : }
      53             : 
      54             : always_inline uword
      55           6 : punt_test_fwd (vlib_main_t * vm,
      56             :                vlib_node_runtime_t * node,
      57             :                vlib_frame_t * frame, fib_protocol_t fproto, u32 sw_if_index)
      58             : {
      59             :   u32 n_left_from, *from, *to_next, next_index;
      60             : 
      61           6 :   from = vlib_frame_vector_args (frame);
      62           6 :   n_left_from = frame->n_vectors;
      63           6 :   next_index = node->cached_next_index;
      64             : 
      65          12 :   while (n_left_from > 0)
      66             :     {
      67             :       u32 n_left_to_next;
      68             : 
      69           6 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
      70             : 
      71         408 :       while (n_left_from > 0 && n_left_to_next > 0)
      72             :         {
      73             :           ip_adjacency_t *adj0;
      74             :           vlib_buffer_t *b0;
      75             :           void *ip0;
      76             :           index_t ai0;
      77             :           u32 bi0;
      78             : 
      79         402 :           bi0 = to_next[0] = from[0];
      80         402 :           from += 1;
      81         402 :           to_next += 1;
      82         402 :           n_left_to_next -= 1;
      83         402 :           n_left_from -= 1;
      84             : 
      85         402 :           b0 = vlib_get_buffer (vm, bi0);
      86         402 :           vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
      87         402 :           ai0 = adjs[fproto][sw_if_index];
      88             : 
      89         402 :           adj0 = adj_get (ai0);
      90         402 :           ip0 = vlib_buffer_get_current (b0);
      91             : 
      92         402 :           vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
      93         402 :           vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
      94             : 
      95         402 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
      96             :                                            to_next, n_left_to_next, bi0, 0);
      97             :         }
      98           6 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
      99             :     }
     100             : 
     101           6 :   return frame->n_vectors;
     102             : }
     103             : 
     104             : always_inline uword
     105           2 : punt_test_pg0_ip4 (vlib_main_t * vm,
     106             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     107             : {
     108           2 :   return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG0));
     109             : }
     110             : 
     111             : always_inline uword
     112           1 : punt_test_pg1_ip4 (vlib_main_t * vm,
     113             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     114             : {
     115           1 :   return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG1));
     116             : }
     117             : 
     118             : always_inline uword
     119           2 : punt_test_pg0_ip6 (vlib_main_t * vm,
     120             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     121             : {
     122           2 :   return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG0));
     123             : }
     124             : 
     125             : always_inline uword
     126           1 : punt_test_pg1_ip6 (vlib_main_t * vm,
     127             :                    vlib_node_runtime_t * node, vlib_frame_t * frame)
     128             : {
     129           1 :   return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG1));
     130             : }
     131             : 
     132             : /* *INDENT-OFF* */
     133       23519 : VLIB_REGISTER_NODE (punt_test_pg0_ip4_node) = {
     134             :   .function = punt_test_pg0_ip4,
     135             :   .name = "punt-test-pg0-ip4",
     136             :   .vector_size = sizeof (u32),
     137             :   .format_trace = format_punt_trace,
     138             : };
     139       23519 : VLIB_REGISTER_NODE (punt_test_pg1_ip4_node) = {
     140             :   .function = punt_test_pg1_ip4,
     141             :   .name = "punt-test-pg1-ip4",
     142             :   .vector_size = sizeof (u32),
     143             :   .format_trace = format_punt_trace,
     144             : };
     145       23519 : VLIB_REGISTER_NODE (punt_test_pg0_ip6_node) = {
     146             :   .function = punt_test_pg0_ip6,
     147             :   .name = "punt-test-pg0-ip6",
     148             :   .vector_size = sizeof (u32),
     149             :   .format_trace = format_punt_trace,
     150             : };
     151       23519 : VLIB_REGISTER_NODE (punt_test_pg1_ip6_node) = {
     152             :   .function = punt_test_pg1_ip6,
     153             :   .name = "punt-test-pg1-ip6",
     154             :   .vector_size = sizeof (u32),
     155             :   .format_trace = format_punt_trace,
     156             : };
     157             : /* *INDENT-ON* */
     158             : 
     159             : typedef struct punt_feat_trace_t_
     160             : {
     161             :   vlib_punt_reason_t pt_reason;
     162             : } punt_feat_trace_t;
     163             : 
     164             : always_inline uword
     165           6 : punt_test_feat_inline (vlib_main_t * vm,
     166             :                        vlib_node_runtime_t * node,
     167             :                        vlib_frame_t * frame, u8 is_ip4)
     168             : {
     169             :   u32 n_left_from, *from, *to_next, next_index;
     170             : 
     171           6 :   from = vlib_frame_vector_args (frame);
     172           6 :   n_left_from = frame->n_vectors;
     173           6 :   next_index = node->cached_next_index;
     174             : 
     175          12 :   while (n_left_from > 0)
     176             :     {
     177             :       u32 n_left_to_next;
     178             : 
     179           6 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     180             : 
     181         408 :       while (n_left_from > 0 && n_left_to_next > 0)
     182             :         {
     183             :           vlib_buffer_t *b0;
     184             :           u32 bi0, next0;
     185             : 
     186         402 :           bi0 = to_next[0] = from[0];
     187         402 :           from += 1;
     188         402 :           to_next += 1;
     189         402 :           n_left_to_next -= 1;
     190         402 :           n_left_from -= 1;
     191         402 :           next0 = 0;
     192             : 
     193         402 :           b0 = vlib_get_buffer (vm, bi0);
     194             : 
     195         402 :           if (is_ip4)
     196         201 :             b0->punt_reason = punt_reason_v4;
     197             :           else
     198         201 :             b0->punt_reason = punt_reason_v6;
     199             : 
     200         402 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     201             :             {
     202             :               punt_feat_trace_t *t;
     203             : 
     204         402 :               b0 = vlib_get_buffer (vm, bi0);
     205             : 
     206         402 :               t = vlib_add_trace (vm, node, b0, sizeof (*t));
     207         402 :               t->pt_reason = b0->punt_reason;
     208             :             }
     209         402 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     210             :                                            to_next, n_left_to_next,
     211             :                                            bi0, next0);
     212             :         }
     213           6 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     214             :     }
     215             : 
     216           6 :   return frame->n_vectors;
     217             : }
     218             : 
     219             : static u8 *
     220         267 : format_punt_feat_trace (u8 * s, va_list * args)
     221             : {
     222         267 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     223         267 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     224         267 :   punt_feat_trace_t *t = va_arg (*args, punt_feat_trace_t *);
     225             : 
     226         267 :   s = format (s, "reason: %U", format_vlib_punt_reason, t->pt_reason);
     227             : 
     228         267 :   return s;
     229             : }
     230             : 
     231             : always_inline uword
     232           3 : punt_test_feat_ip4 (vlib_main_t * vm,
     233             :                     vlib_node_runtime_t * node, vlib_frame_t * frame)
     234             : {
     235           3 :   return (punt_test_feat_inline (vm, node, frame, 1));
     236             : }
     237             : 
     238             : always_inline uword
     239           3 : punt_test_feat_ip6 (vlib_main_t * vm,
     240             :                     vlib_node_runtime_t * node, vlib_frame_t * frame)
     241             : {
     242           3 :   return (punt_test_feat_inline (vm, node, frame, 0));
     243             : }
     244             : 
     245             : /* *INDENT-OFF* */
     246       23519 : VLIB_REGISTER_NODE (punt_test_feat_ip6_node) = {
     247             :   .function = punt_test_feat_ip6,
     248             :   .name = "punt-test-feat-ip6",
     249             :   .vector_size = sizeof (u32),
     250             :   .format_trace = format_punt_feat_trace,
     251             :   .n_next_nodes = 1,
     252             :   .next_nodes = {
     253             :     [0] = "punt-dispatch"
     254             :   }
     255             : };
     256       23519 : VLIB_REGISTER_NODE (punt_test_feat_ip4_node) = {
     257             :   .function = punt_test_feat_ip4,
     258             :   .name = "punt-test-feat-ip4",
     259             :   .vector_size = sizeof (u32),
     260             :   .format_trace = format_punt_feat_trace,
     261             :   .n_next_nodes = 1,
     262             :   .next_nodes = {
     263             :     [0] = "punt-dispatch"
     264             :   }
     265             : };
     266        8399 : VNET_FEATURE_INIT (punt_test_feat_ip6_feature, static) =
     267             : {
     268             :   .arc_name = "ip6-unicast",
     269             :   .node_name = "punt-test-feat-ip6",
     270             : };
     271        8399 : VNET_FEATURE_INIT (punt_test_feat_ip4_feature, static) =
     272             : {
     273             :   .arc_name = "ip4-unicast",
     274             :   .node_name = "punt-test-feat-ip4",
     275             : };
     276             : /* *INDENT-ON* */
     277             : 
     278             : static clib_error_t *
     279           5 : punt_test (vlib_main_t * vm,
     280             :            unformat_input_t * input, vlib_cli_command_t * cmd_arg)
     281             : {
     282           5 :   ip46_address_t ip46 = ip46_address_initializer;
     283             :   fib_protocol_t fproto;
     284             :   vnet_main_t *vnm;
     285             :   u32 sw_if_index;
     286             :   int rc;
     287             : 
     288           5 :   vnm = vnet_get_main ();
     289           5 :   fproto = FIB_PROTOCOL_IP4;
     290             : 
     291           5 :   if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
     292             :     {
     293             :       vlib_node_t *from;
     294             : 
     295           5 :       if (unformat (input, "%U", unformat_ip4_address, &ip46.ip4))
     296             :         {
     297           2 :           fproto = FIB_PROTOCOL_IP4;
     298             :         }
     299           3 :       else if (unformat (input, "%U", unformat_ip6_address, &ip46.ip6))
     300             :         {
     301           2 :           fproto = FIB_PROTOCOL_IP6;
     302             :         }
     303           1 :       else if (unformat (input, "clear"))
     304             :         {
     305           0 :           vnet_feature_enable_disable ("ip4-unicast",
     306             :                                        "punt-test-feat-ip4",
     307             :                                        sw_if_index, 0, NULL, 0);
     308           0 :           vnet_feature_enable_disable ("ip6-unicast",
     309             :                                        "punt-test-feat-ip6",
     310             :                                        sw_if_index, 0, NULL, 0);
     311           0 :           return NULL;
     312             :         }
     313             :       else
     314             :         {
     315             :           /*
     316             :            * allocate a client and a reason
     317             :            */
     318           1 :           punt_hdl = vlib_punt_client_register ("test");
     319             : 
     320           1 :           rc = vlib_punt_reason_alloc (
     321             :             punt_hdl, "reason-v4", NULL, NULL, &punt_reason_v4,
     322             :             VNET_PUNT_REASON_F_IP4_PACKET, format_vnet_punt_reason_flags);
     323           1 :           rc |= vlib_punt_reason_alloc (
     324             :             punt_hdl, "reason-v6", NULL, NULL, &punt_reason_v6,
     325             :             VNET_PUNT_REASON_F_IP6_PACKET, format_vnet_punt_reason_flags);
     326           1 :           ASSERT (!rc);
     327             : 
     328           1 :           vnet_feature_enable_disable ("ip4-unicast",
     329             :                                        "punt-test-feat-ip4",
     330             :                                        sw_if_index, 1, NULL, 0);
     331           1 :           vnet_feature_enable_disable ("ip6-unicast",
     332             :                                        "punt-test-feat-ip6",
     333             :                                        sw_if_index, 1, NULL, 0);
     334           1 :           return NULL;
     335             :         }
     336             : 
     337           4 :       if (SW_IF_INDEX_PG0 == sw_if_index)
     338             :         {
     339           2 :           if (FIB_PROTOCOL_IP4 == fproto)
     340             :             {
     341             :               /*
     342             :                * register the node that will forward the punted packet
     343             :                */
     344           1 :               vlib_punt_register (punt_hdl, punt_reason_v4,
     345             :                                   "punt-test-pg0-ip4");
     346           1 :               from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip4");
     347             :             }
     348             :           else
     349             :             {
     350           1 :               vlib_punt_register (punt_hdl, punt_reason_v6,
     351             :                                   "punt-test-pg0-ip6");
     352           1 :               from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip6");
     353             :             }
     354             :         }
     355             :       else
     356             :         {
     357           2 :           if (FIB_PROTOCOL_IP4 == fproto)
     358             :             {
     359           1 :               vlib_punt_register (punt_hdl, punt_reason_v4,
     360             :                                   "punt-test-pg1-ip4");
     361           1 :               from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip4");
     362             :             }
     363             :           else
     364             :             {
     365           1 :               vlib_punt_register (punt_hdl, punt_reason_v6,
     366             :                                   "punt-test-pg1-ip6");
     367           1 :               from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip6");
     368             :             }
     369             :         }
     370             : 
     371           4 :       vlib_node_add_next (vm, from->index,
     372           4 :                           vnet_tx_node_index_for_sw_interface
     373             :                           (vnm, sw_if_index));
     374             : 
     375           4 :       vec_validate (adjs[fproto], sw_if_index);
     376             : 
     377           4 :       adjs[fproto][sw_if_index] = adj_nbr_find (fproto,
     378           4 :                                                 fib_proto_to_link (fproto),
     379             :                                                 &ip46, sw_if_index);
     380             :     }
     381             : 
     382           4 :   return (NULL);
     383             : }
     384             : 
     385             : /* *INDENT-OFF* */
     386       16239 : VLIB_CLI_COMMAND (test_fib_command, static) =
     387             : {
     388             :   .path = "test punt",
     389             :   .short_help = "punt unit tests - DO NOT RUN ON A LIVE SYSTEM",
     390             :   .function = punt_test,
     391             : };
     392             : /* *INDENT-ON* */
     393             : 
     394             : /*
     395             :  * fd.io coding-style-patch-verification: ON
     396             :  *
     397             :  * Local Variables:
     398             :  * eval: (c-set-style "gnu")
     399             :  * End:
     400             :  */

Generated by: LCOV version 1.14