LCOV - code coverage report
Current view: top level - plugins/adl - adl.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 88 159 55.3 %
Date: 2023-07-05 22:20:52 Functions: 14 16 87.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016,2020 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             : #include <vnet/ethernet/ethernet.h>
      16             : #include <vnet/plugin/plugin.h>
      17             : #include <vpp/app/version.h>
      18             : #include <plugins/adl/adl.h>
      19             : 
      20             : adl_main_t adl_main;
      21             : 
      22             : static clib_error_t *
      23       11597 : adl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
      24             : {
      25       11597 :   adl_main_t *am = &adl_main;
      26       11597 :   adl_config_data_t _data, *data = &_data;
      27       11597 :   vlib_main_t *vm = am->vlib_main;
      28       11597 :   vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);;
      29             :   adl_config_main_t *acm;
      30             :   int address_family;
      31             :   u32 ci, default_next;
      32             : 
      33       11597 :   clib_memset (data, 0, sizeof (*data));
      34             : 
      35             :   /*
      36             :    * Ignore local interface, pg interfaces. $$$ need a #define for the
      37             :    * first "real" interface. The answer is 5 at the moment.
      38             :    */
      39       11597 :   if (hi->dev_class_index == vnet_local_interface_device_class.index)
      40         559 :     return 0;
      41             : 
      42       44152 :   for (address_family = VNET_ADL_IP4; address_family < VNET_N_ADLS;
      43       33114 :        address_family++)
      44             :     {
      45       33114 :       acm = &am->adl_config_mains[address_family];
      46             : 
      47             :       /*
      48             :        * Once-only code to initialize the per-address-family
      49             :        * adl feature subgraphs.
      50             :        * Since the (single) start-node, adl-input, must be able
      51             :        * to push pkts into three separate subgraphs, we
      52             :        * use a unified adl_feature_type_t enumeration.
      53             :        */
      54             : 
      55       33114 :       if (!(acm->config_main.node_index_by_feature_index))
      56             :         {
      57        1515 :           switch (address_family)
      58             :             {
      59         505 :             case VNET_ADL_IP4:
      60             :               {
      61             :                 static char *start_nodes[] = { "adl-input" };
      62             :                 static char *feature_nodes[] = {
      63             :                   [IP4_RX_ADL_ALLOWLIST] = "ip4-adl-allowlist",
      64             :                   [IP4_RX_ADL_INPUT] = "ip4-input",
      65             :                 };
      66             : 
      67         505 :                 vnet_config_init (vm, &acm->config_main,
      68             :                                   start_nodes, ARRAY_LEN (start_nodes),
      69             :                                   feature_nodes, ARRAY_LEN (feature_nodes));
      70             :               }
      71         505 :               break;
      72         505 :             case VNET_ADL_IP6:
      73             :               {
      74             :                 static char *start_nodes[] = { "adl-input" };
      75             :                 static char *feature_nodes[] = {
      76             :                   [IP6_RX_ADL_ALLOWLIST] = "ip6-adl-allowlist",
      77             :                   [IP6_RX_ADL_INPUT] = "ip6-input",
      78             :                 };
      79         505 :                 vnet_config_init (vm, &acm->config_main,
      80             :                                   start_nodes, ARRAY_LEN (start_nodes),
      81             :                                   feature_nodes, ARRAY_LEN (feature_nodes));
      82             :               }
      83         505 :               break;
      84             : 
      85         505 :             case VNET_ADL_DEFAULT:
      86             :               {
      87             :                 static char *start_nodes[] = { "adl-input" };
      88             :                 static char *feature_nodes[] = {
      89             :                   [DEFAULT_RX_ADL_ALLOWLIST] = "default-adl-allowlist",
      90             :                   [DEFAULT_RX_ADL_INPUT] = "ethernet-input",
      91             :                 };
      92         505 :                 vnet_config_init (vm, &acm->config_main,
      93             :                                   start_nodes, ARRAY_LEN (start_nodes),
      94             :                                   feature_nodes, ARRAY_LEN (feature_nodes));
      95             :               }
      96         505 :               break;
      97             : 
      98           0 :             default:
      99           0 :               clib_warning ("bug");
     100           0 :               break;
     101             :             }
     102       31599 :         }
     103       44643 :       vec_validate_init_empty (acm->config_index_by_sw_if_index, sw_if_index,
     104             :                                ~0);
     105             : 
     106       33114 :       ci = acm->config_index_by_sw_if_index[sw_if_index];
     107             : 
     108             :       /* Create a sensible initial config: send pkts to xxx-input */
     109       33114 :       if (address_family == VNET_ADL_IP4)
     110       11038 :         default_next = IP4_RX_ADL_INPUT;
     111       22076 :       else if (address_family == VNET_ADL_IP6)
     112       11038 :         default_next = IP6_RX_ADL_INPUT;
     113             :       else
     114       11038 :         default_next = DEFAULT_RX_ADL_INPUT;
     115             : 
     116       33114 :       if (is_add)
     117       20577 :         ci = vnet_config_add_feature (vm, &acm->config_main,
     118             :                                       ci, default_next, data, sizeof (*data));
     119             :       else
     120             :         {
     121             :           /* If the feature was actually configured */
     122       12537 :           if (ci != ~0)
     123             :             {
     124       12537 :               ci = vnet_config_del_feature (vm, &acm->config_main,
     125             :                                             ci, default_next, data,
     126             :                                             sizeof (*data));
     127             :             }
     128             :         }
     129             : 
     130       33114 :       acm->config_index_by_sw_if_index[sw_if_index] = ci;
     131             :     }
     132       11038 :   return 0;
     133             : }
     134             : 
     135        2243 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (adl_sw_interface_add_del);
     136             : 
     137             : static clib_error_t *
     138         559 : adl_init (vlib_main_t * vm)
     139             : {
     140         559 :   adl_main_t *cm = &adl_main;
     141             : 
     142         559 :   cm->vlib_main = vm;
     143         559 :   cm->vnet_main = vnet_get_main ();
     144             : 
     145             :   /*
     146             :    * Setup the packet generator so we can inject ethernet
     147             :    * frames into this node
     148             :    */
     149         559 :   ethernet_setup_node (vm, adl_input_node.index);
     150         559 :   return 0;
     151             : }
     152             : 
     153             : /* *INDENT-OFF* */
     154        1119 : VLIB_INIT_FUNCTION (adl_init) =
     155             : {
     156             :   .runs_after = VLIB_INITS ("ip4_allowlist_init", "ip6_allowlist_init"),
     157             : };
     158             : /* *INDENT-ON* */
     159             : 
     160             : /* *INDENT-OFF* */
     161       63303 : VNET_FEATURE_INIT (adl, static) =
     162             : {
     163             :   .arc_name = "device-input",
     164             :   .node_name = "adl-input",
     165             :   .runs_before = VNET_FEATURES ("ethernet-input"),
     166             : };
     167             : /* *INDENT-ON */
     168             : 
     169           1 : int adl_interface_enable_disable (u32 sw_if_index, int enable_disable)
     170             : {
     171             :   /*
     172             :    * Redirect pkts from the driver to the adl node.
     173             :    */
     174           1 :   vnet_feature_enable_disable ("device-input", "adl-input",
     175             :                                sw_if_index, enable_disable, 0, 0);
     176           1 :   return 0;
     177             : }
     178             : 
     179             : static clib_error_t *
     180           0 : adl_enable_disable_command_fn (vlib_main_t * vm,
     181             :                                 unformat_input_t * input,
     182             :                                 vlib_cli_command_t * cmd)
     183             : {
     184           0 :   adl_main_t * cm = &adl_main;
     185           0 :   u32 sw_if_index = ~0;
     186           0 :   int enable_disable = 1;
     187             : 
     188             :   int rv;
     189             : 
     190           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
     191           0 :     if (unformat (input, "disable"))
     192           0 :       enable_disable = 0;
     193           0 :     else if (unformat (input, "%U", unformat_vnet_sw_interface,
     194             :                        cm->vnet_main, &sw_if_index))
     195             :       ;
     196             :     else
     197           0 :       break;
     198             :   }
     199             : 
     200           0 :   if (sw_if_index == ~0)
     201           0 :     return clib_error_return (0, "Please specify an interface...");
     202             : 
     203           0 :   rv = adl_interface_enable_disable (sw_if_index, enable_disable);
     204             : 
     205           0 :   switch(rv) {
     206           0 :   case 0:
     207           0 :     break;
     208             : 
     209           0 :   case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     210           0 :     return clib_error_return
     211             :       (0, "Invalid interface, only works on physical ports");
     212             :     break;
     213             : 
     214           0 :   case VNET_API_ERROR_UNIMPLEMENTED:
     215           0 :     return clib_error_return (0, "Device driver doesn't support redirection");
     216             :     break;
     217             : 
     218           0 :   default:
     219           0 :     return clib_error_return (0, "adl_interface_enable_disable returned %d",
     220             :                               rv);
     221             :   }
     222           0 :   return 0;
     223             : }
     224             : 
     225      261127 : VLIB_CLI_COMMAND (adl_interface_command, static) = {
     226             :     .path = "adl interface",
     227             :     .short_help =
     228             :     "adl interface <interface-name> [disable]",
     229             :     .function = adl_enable_disable_command_fn,
     230             : };
     231             : 
     232             : 
     233           1 : int adl_allowlist_enable_disable (adl_allowlist_enable_disable_args_t *a)
     234             : {
     235           1 :   adl_main_t * cm = &adl_main;
     236           1 :   vlib_main_t * vm = cm->vlib_main;
     237           1 :   ip4_main_t * im4 = &ip4_main;
     238           1 :   ip6_main_t * im6 = &ip6_main;
     239             :   int address_family;
     240             :   int is_add;
     241             :   adl_config_main_t * acm;
     242           1 :   u32 next_to_add_del = 0;
     243             :   uword * p;
     244           1 :   u32 fib_index = 0;
     245             :   u32 ci;
     246           1 :   adl_config_data_t _data, *data=&_data;
     247             : 
     248             :   /*
     249             :    * Enable / disable allowlist processing on the specified interface
     250             :    */
     251             : 
     252           4 :   for (address_family = VNET_ADL_IP4; address_family < VNET_N_ADLS;
     253           3 :        address_family++)
     254             :     {
     255           3 :       acm = &cm->adl_config_mains[address_family];
     256             : 
     257           3 :       switch(address_family)
     258             :         {
     259           1 :         case VNET_ADL_IP4:
     260           1 :           is_add = (a->ip4 != 0);
     261           1 :           next_to_add_del = IP4_RX_ADL_ALLOWLIST;
     262             :           /* configured opaque data must match, or no supper */
     263           1 :           p = hash_get (im4->fib_index_by_table_id, a->fib_id);
     264           1 :           if (p)
     265           1 :             fib_index = p[0];
     266             :           else
     267             :             {
     268           0 :               if (is_add)
     269           0 :                 return VNET_API_ERROR_NO_SUCH_FIB;
     270             :               else
     271           0 :                 continue;
     272             :             }
     273           1 :           break;
     274             : 
     275           1 :         case VNET_ADL_IP6:
     276           1 :           is_add = (a->ip6 != 0);
     277           1 :           next_to_add_del = IP6_RX_ADL_ALLOWLIST;
     278           1 :           p = hash_get (im6->fib_index_by_table_id, a->fib_id);
     279           1 :           if (p)
     280           1 :             fib_index = p[0];
     281             :           else
     282             :             {
     283           0 :               if (is_add)
     284           0 :                 return VNET_API_ERROR_NO_SUCH_FIB;
     285             :               else
     286           0 :                 continue;
     287             :             }
     288           1 :           break;
     289             : 
     290           1 :         case VNET_ADL_DEFAULT:
     291           1 :           is_add = (a->default_adl != 0);
     292           1 :           next_to_add_del = DEFAULT_RX_ADL_ALLOWLIST;
     293           1 :           break;
     294             : 
     295           0 :         default:
     296           0 :           clib_warning ("BUG");
     297             :         }
     298             : 
     299           3 :       ci = acm->config_index_by_sw_if_index[a->sw_if_index];
     300           3 :       data->fib_index = fib_index;
     301             : 
     302           3 :       if (is_add)
     303           2 :         ci = vnet_config_add_feature (vm, &acm->config_main,
     304             :                                       ci,
     305             :                                       next_to_add_del,
     306             :                                       data, sizeof (*data));
     307             :       else
     308             :         {
     309             :           /* If the feature was actually configured... */
     310           1 :           if (ci != ~0)
     311             :             {
     312             :               /* delete it */
     313           1 :               ci = vnet_config_del_feature (vm, &acm->config_main,
     314             :                                             ci,
     315             :                                             next_to_add_del,
     316             :                                             data, sizeof (*data));
     317             :             }
     318             :         }
     319             : 
     320           3 :       acm->config_index_by_sw_if_index[a->sw_if_index] = ci;
     321             :     }
     322           1 :   return 0;
     323             : }
     324             : 
     325             : static clib_error_t *
     326           0 : adl_allowlist_enable_disable_command_fn (vlib_main_t * vm,
     327             :                                          unformat_input_t * input,
     328             :                                          vlib_cli_command_t * cmd)
     329             : {
     330           0 :   adl_main_t * cm = &adl_main;
     331           0 :   u32 sw_if_index = ~0;
     332           0 :   u8 ip4 = 0;
     333           0 :   u8 ip6 = 0;
     334           0 :   u8 default_adl = 0;
     335           0 :   u32 fib_id = 0;
     336             :   int rv;
     337           0 :   adl_allowlist_enable_disable_args_t _a, * a = &_a;
     338             : 
     339           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
     340           0 :     if (unformat (input, "ip4"))
     341           0 :       ip4 = 1;
     342           0 :     else if (unformat (input, "ip6"))
     343           0 :       ip6 = 1;
     344           0 :     else if (unformat (input, "default"))
     345           0 :       default_adl = 1;
     346           0 :     else if (unformat (input, "%U", unformat_vnet_sw_interface,
     347             :                        cm->vnet_main, &sw_if_index))
     348             :       ;
     349           0 :     else if (unformat (input, "fib-id %d", &fib_id))
     350             :       ;
     351             :     else
     352           0 :       break;
     353             :   }
     354             : 
     355           0 :   if (sw_if_index == ~0)
     356           0 :     return clib_error_return (0, "Please specify an interface...");
     357             : 
     358           0 :   a->sw_if_index = sw_if_index;
     359           0 :   a->ip4 = ip4;
     360           0 :   a->ip6 = ip6;
     361           0 :   a->default_adl = default_adl;
     362           0 :   a->fib_id = fib_id;
     363             : 
     364           0 :   rv = adl_allowlist_enable_disable (a);
     365             : 
     366           0 :   switch(rv) {
     367           0 :   case 0:
     368           0 :     break;
     369             : 
     370           0 :   case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     371           0 :     return clib_error_return
     372             :       (0, "Invalid interface, only works on physical ports");
     373             :     break;
     374             : 
     375           0 :   case VNET_API_ERROR_NO_SUCH_FIB:
     376           0 :     return clib_error_return
     377             :       (0, "Invalid fib");
     378             :     break;
     379             : 
     380           0 :   case VNET_API_ERROR_UNIMPLEMENTED:
     381           0 :     return clib_error_return (0, "Device driver doesn't support redirection");
     382             :     break;
     383             : 
     384           0 :   default:
     385           0 :     return clib_error_return (0, "adl_allowlist_enable_disable returned %d",
     386             :                               rv);
     387             :   }
     388             : 
     389           0 :   return 0;
     390             : }
     391             : 
     392             : /* *INDENT-OFF* */
     393      261127 : VLIB_CLI_COMMAND (adl_allowlist_command, static) =
     394             : {
     395             :    .path = "adl allowlist",
     396             :    .short_help =
     397             :    "adl allowlist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]",
     398             :    .function = adl_allowlist_enable_disable_command_fn,
     399             : };
     400             : /* *INDENT-ON* */
     401             : 
     402             : /* *INDENT-OFF* */
     403             : VLIB_PLUGIN_REGISTER () =
     404             : {
     405             :   .version = VPP_BUILD_VER,
     406             :   .description = "Allow/deny list plugin",
     407             : };
     408             : /* *INDENT-ON* */
     409             : 
     410             : 
     411             : /*
     412             :  * fd.io coding-style-patch-verification: ON
     413             :  *
     414             :  * Local Variables:
     415             :  * eval: (c-set-style "gnu")
     416             :  * End:
     417             :  */

Generated by: LCOV version 1.14