LCOV - code coverage report
Current view: top level - vnet/qos - qos_record.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 76 102 74.5 %
Date: 2023-10-26 01:39:38 Functions: 16 17 94.1 %

          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/qos/qos_record.h>
      17             : #include <vnet/ip/ip.h>
      18             : #include <vnet/ip/ip6_to_ip4.h>
      19             : #include <vnet/feature/feature.h>
      20             : #include <vnet/qos/qos_types.h>
      21             : #include <vnet/l2/l2_input.h>
      22             : #include <vnet/l2/feat_bitmap.h>
      23             : 
      24             : /**
      25             :  * Per-interface, per-protocol vector of feature on/off configurations
      26             :  */
      27             : u8 *qos_record_configs[QOS_N_SOURCES];
      28             : u32 l2_qos_input_next[QOS_N_SOURCES][32];
      29             : 
      30             : static void
      31          10 : qos_record_feature_config (u32 sw_if_index,
      32             :                            qos_source_t input_source, u8 enable)
      33             : {
      34          10 :   switch (input_source)
      35             :     {
      36           6 :     case QOS_SOURCE_IP:
      37           6 :       ip_feature_enable_disable (AF_IP6, N_SAFI, IP_FEATURE_INPUT,
      38             :                                  "ip6-qos-record",
      39             :                                  sw_if_index, enable, NULL, 0);
      40           6 :       ip_feature_enable_disable (AF_IP4, N_SAFI, IP_FEATURE_INPUT,
      41             :                                  "ip4-qos-record",
      42             :                                  sw_if_index, enable, NULL, 0);
      43           6 :       l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_L2_IP_QOS_RECORD,
      44             :                                   enable);
      45           6 :       break;
      46           2 :     case QOS_SOURCE_MPLS:
      47           2 :       vnet_feature_enable_disable ("mpls-input", "mpls-qos-record",
      48             :                                    sw_if_index, enable, NULL, 0);
      49           2 :       break;
      50           2 :     case QOS_SOURCE_VLAN:
      51           2 :       ip_feature_enable_disable (AF_IP6, N_SAFI, IP_FEATURE_INPUT,
      52             :                                  "vlan-ip6-qos-record",
      53             :                                  sw_if_index, enable, NULL, 0);
      54           2 :       ip_feature_enable_disable (AF_IP4, N_SAFI, IP_FEATURE_INPUT,
      55             :                                  "vlan-ip4-qos-record",
      56             :                                  sw_if_index, enable, NULL, 0);
      57           2 :       vnet_feature_enable_disable ("mpls-input", "vlan-mpls-qos-record",
      58             :                                    sw_if_index, enable, NULL, 0);
      59           2 :       break;
      60           0 :     case QOS_SOURCE_EXT:
      61             :       /* not a valid option for recording */
      62           0 :       break;
      63             :     }
      64          10 : }
      65             : 
      66             : int
      67           5 : qos_record_enable (u32 sw_if_index, qos_source_t input_source)
      68             : {
      69           5 :   vec_validate (qos_record_configs[input_source], sw_if_index);
      70             : 
      71           5 :   if (0 == qos_record_configs[input_source][sw_if_index])
      72             :     {
      73           5 :       qos_record_feature_config (sw_if_index, input_source, 1);
      74             :     }
      75             : 
      76           5 :   qos_record_configs[input_source][sw_if_index]++;
      77           5 :   return (0);
      78             : }
      79             : 
      80             : int
      81       17009 : qos_record_disable (u32 sw_if_index, qos_source_t input_source)
      82             : {
      83       17009 :   if (vec_len (qos_record_configs[input_source]) <= sw_if_index)
      84       17004 :     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
      85             : 
      86           5 :   if (0 == qos_record_configs[input_source][sw_if_index])
      87           0 :     return VNET_API_ERROR_VALUE_EXIST;
      88             : 
      89           5 :   qos_record_configs[input_source][sw_if_index]--;
      90             : 
      91           5 :   if (0 == qos_record_configs[input_source][sw_if_index])
      92             :     {
      93           5 :       qos_record_feature_config (sw_if_index, input_source, 0);
      94             :     }
      95             : 
      96           5 :   return (0);
      97             : }
      98             : 
      99             : void
     100          10 : qos_record_walk (qos_record_walk_cb_t fn, void *c)
     101             : {
     102             :   qos_source_t qs;
     103             : 
     104          50 :   FOR_EACH_QOS_SOURCE (qs)
     105             :   {
     106             :     u32 sw_if_index;
     107             : 
     108         108 :     vec_foreach_index (sw_if_index, qos_record_configs[qs])
     109             :     {
     110          68 :       if (0 != qos_record_configs[qs][sw_if_index])
     111           9 :         fn (sw_if_index, qs, c);
     112             :     }
     113             :   }
     114          10 : }
     115             : 
     116             : /*
     117             :  * Disable recording feature for all protocols when the interface
     118             :  * is deleted
     119             :  */
     120             : static clib_error_t *
     121       11798 : qos_record_ip_interface_add_del (vnet_main_t * vnm,
     122             :                                  u32 sw_if_index, u32 is_add)
     123             : {
     124       11798 :   if (!is_add)
     125             :     {
     126             :       qos_source_t qs;
     127             : 
     128       21255 :       FOR_EACH_QOS_SOURCE (qs)
     129             :       {
     130       17004 :         while (qos_record_disable (sw_if_index, qs) == 0);
     131             :       }
     132             :     }
     133             : 
     134       11798 :   return (NULL);
     135             : }
     136             : 
     137        3459 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (qos_record_ip_interface_add_del);
     138             : 
     139             : clib_error_t *
     140         575 : qos_record_init (vlib_main_t * vm)
     141             : {
     142             :   qos_source_t qs;
     143         575 :   vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "l2-ip-qos-record");
     144             : 
     145             :   /* Initialize the feature next-node indexes */
     146        2875 :   FOR_EACH_QOS_SOURCE (qs)
     147        2300 :     feat_bitmap_init_next_nodes (vm,
     148             :                                  node->index,
     149             :                                  L2INPUT_N_FEAT,
     150             :                                  l2input_get_feat_names (),
     151        2300 :                                  l2_qos_input_next[qs]);
     152         575 :   return 0;
     153             : }
     154             : 
     155       88703 : VLIB_INIT_FUNCTION (qos_record_init);
     156             : 
     157             : static clib_error_t *
     158           0 : qos_record_cli (vlib_main_t * vm,
     159             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     160             : {
     161           0 :   vnet_main_t *vnm = vnet_get_main ();
     162             :   u32 sw_if_index, qs;
     163             :   u8 enable;
     164             : 
     165           0 :   qs = 0xff;
     166           0 :   enable = 1;
     167           0 :   sw_if_index = ~0;
     168             : 
     169           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     170             :     {
     171           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     172             :                     vnm, &sw_if_index))
     173             :         ;
     174           0 :       else if (unformat (input, "%U", unformat_qos_source, &qs))
     175             :         ;
     176           0 :       else if (unformat (input, "enable"))
     177           0 :         enable = 1;
     178           0 :       else if (unformat (input, "disable"))
     179           0 :         enable = 0;
     180             :       else
     181           0 :         break;
     182             :     }
     183             : 
     184           0 :   if (~0 == sw_if_index)
     185           0 :     return clib_error_return (0, "interface must be specified");
     186           0 :   if (0xff == qs)
     187           0 :     return clib_error_return (0, "input location must be specified");
     188             : 
     189           0 :   if (enable)
     190           0 :     qos_record_enable (sw_if_index, qs);
     191             :   else
     192           0 :     qos_record_disable (sw_if_index, qs);
     193             : 
     194           0 :   return (NULL);
     195             : }
     196             : 
     197             : /*?
     198             :  * Enable QoS bit recording on an interface using the packet's input DSCP bits
     199             :  * Which input QoS bits to use are either; IP, MPLS or VLAN. If more than
     200             :  * one protocol is chosen (which is foolish) the higher layers override the
     201             :  * lower.
     202             :  *
     203             :  * @cliexpar
     204             :  * @cliexcmd{qos record ip GigEthernet0/1/0}
     205             :  ?*/
     206             : /* *INDENT-OFF* */
     207      285289 : VLIB_CLI_COMMAND (qos_record_command, static) = {
     208             :   .path = "qos record",
     209             :   .short_help = "qos record <record-source> <INTERFACE> [disable]",
     210             :   .function = qos_record_cli,
     211             :   .is_mp_safe = 1,
     212             : };
     213             : /* *INDENT-ON* */
     214             : 
     215             : static void
     216           2 : qos_record_show_one_interface (vlib_main_t * vm, u32 sw_if_index)
     217             : {
     218           2 :   u8 n_cfgs[QOS_N_SOURCES] = { };
     219             :   qos_source_t qs;
     220             :   bool set;
     221             : 
     222           2 :   set = false;
     223             : 
     224          10 :   FOR_EACH_QOS_SOURCE (qs)
     225             :   {
     226           8 :     if (vec_len (qos_record_configs[qs]) <= sw_if_index)
     227           6 :       continue;
     228           2 :     if (0 != (n_cfgs[qs] = qos_record_configs[qs][sw_if_index]))
     229           1 :       set = true;
     230             :   }
     231             : 
     232           2 :   if (set)
     233             :     {
     234           1 :       vlib_cli_output (vm, " %U:", format_vnet_sw_if_index_name,
     235             :                        vnet_get_main (), sw_if_index);
     236             : 
     237           5 :       FOR_EACH_QOS_SOURCE (qs)
     238             :       {
     239           4 :         if (n_cfgs[qs] != 0)
     240           1 :           vlib_cli_output (vm, "  %U", format_qos_source, qs);
     241             :       }
     242             :     }
     243           2 : }
     244             : 
     245             : static clib_error_t *
     246           1 : qos_record_show (vlib_main_t * vm,
     247             :                  unformat_input_t * input, vlib_cli_command_t * cmd)
     248             : {
     249           1 :   vnet_main_t *vnm = vnet_get_main ();
     250             :   qos_source_t qs;
     251             :   u32 sw_if_index;
     252             : 
     253           1 :   sw_if_index = ~0;
     254             : 
     255           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     256             :     {
     257           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     258             :                     vnm, &sw_if_index))
     259             :         ;
     260             :     }
     261             : 
     262           1 :   if (~0 == sw_if_index)
     263             :     {
     264           1 :       u32 ii, n_ints = 0;
     265             : 
     266           5 :       FOR_EACH_QOS_SOURCE (qs)
     267             :       {
     268           4 :         n_ints = clib_max (n_ints, vec_len (qos_record_configs[qs]));
     269             :       }
     270             : 
     271           3 :       for (ii = 0; ii < n_ints; ii++)
     272             :         {
     273           2 :           qos_record_show_one_interface (vm, ii);
     274             :         }
     275             :     }
     276             :   else
     277           0 :     qos_record_show_one_interface (vm, sw_if_index);
     278             : 
     279           1 :   return (NULL);
     280             : }
     281             : 
     282             : /*?
     283             :  * Show Egress Qos Maps
     284             :  *
     285             :  * @cliexpar
     286             :  * @cliexcmd{show qos egress map}
     287             :  ?*/
     288             : /* *INDENT-OFF* */
     289      285289 : VLIB_CLI_COMMAND (qos_record_show_command, static) = {
     290             :   .path = "show qos record",
     291             :   .short_help = "show qos record [interface]",
     292             :   .function = qos_record_show,
     293             :   .is_mp_safe = 1,
     294             : };
     295             : /* *INDENT-ON* */
     296             : 
     297             : /*
     298             :  * fd.io coding-style-patch-verification: ON
     299             :  *
     300             :  * Local Variables:
     301             :  * eval: (c-set-style "gnu")
     302             :  * End:
     303             :  */

Generated by: LCOV version 1.14