LCOV - code coverage report
Current view: top level - vnet/qos - qos_store.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 71 102 69.6 %
Date: 2023-07-05 22:20:52 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_store.h>
      17             : #include <vnet/ip/ip.h>
      18             : #include <vnet/feature/feature.h>
      19             : 
      20             : /**
      21             :  * QoS Store configuration
      22             :  */
      23             : typedef struct qos_store_t_
      24             : {
      25             :   u8 qst_n_cfgs;
      26             :   qos_bits_t qst_value;
      27             : } qos_store_t;
      28             : 
      29             : /**
      30             :  * Per-interface, per-protocol vector of feature on/off configurations
      31             :  */
      32             : qos_store_t *qos_store_configs[QOS_N_SOURCES];
      33             : 
      34             : static void
      35           2 : qos_store_feature_config (u32 sw_if_index,
      36             :                           qos_source_t input_source,
      37             :                           u8 enable, qos_bits_t value)
      38             : {
      39           2 :   switch (input_source)
      40             :     {
      41           2 :     case QOS_SOURCE_IP:
      42           2 :       vnet_feature_enable_disable ("ip6-unicast", "ip6-qos-store",
      43             :                                    sw_if_index, enable, &value,
      44             :                                    sizeof (value));
      45           2 :       vnet_feature_enable_disable ("ip6-multicast", "ip6-qos-store",
      46             :                                    sw_if_index, enable, &value,
      47             :                                    sizeof (value));
      48           2 :       vnet_feature_enable_disable ("ip4-unicast", "ip4-qos-store",
      49             :                                    sw_if_index, enable, &value,
      50             :                                    sizeof (value));
      51           2 :       vnet_feature_enable_disable ("ip4-multicast", "ip4-qos-store",
      52             :                                    sw_if_index, enable, &value,
      53             :                                    sizeof (value));
      54           2 :       break;
      55           0 :     case QOS_SOURCE_MPLS:
      56             :     case QOS_SOURCE_VLAN:
      57             :     case QOS_SOURCE_EXT:
      58             :       /* not a valid option for storing */
      59           0 :       break;
      60             :     }
      61           2 : }
      62             : 
      63             : int
      64           1 : qos_store_enable (u32 sw_if_index,
      65             :                   qos_source_t input_source, qos_bits_t value)
      66             : {
      67             :   qos_store_t *qst;
      68             : 
      69           1 :   if (QOS_SOURCE_IP != input_source)
      70           0 :     return VNET_API_ERROR_UNIMPLEMENTED;
      71             : 
      72           1 :   vec_validate (qos_store_configs[input_source], sw_if_index);
      73             : 
      74           1 :   qst = &qos_store_configs[input_source][sw_if_index];
      75             : 
      76           1 :   if (0 == qst->qst_n_cfgs)
      77             :     {
      78           1 :       qst->qst_value = value;
      79           1 :       qos_store_feature_config (sw_if_index, input_source, 1, value);
      80             :     }
      81             : 
      82           1 :   qst->qst_n_cfgs++;
      83             : 
      84           1 :   return (0);
      85             : }
      86             : 
      87             : int
      88       16717 : qos_store_disable (u32 sw_if_index, qos_source_t input_source)
      89             : {
      90             :   qos_store_t *qst;
      91             : 
      92       16717 :   if (vec_len (qos_store_configs[input_source]) <= sw_if_index)
      93       16716 :     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
      94             : 
      95           1 :   qst = &qos_store_configs[input_source][sw_if_index];
      96             : 
      97           1 :   if (0 == qst->qst_n_cfgs)
      98           0 :     return VNET_API_ERROR_VALUE_EXIST;
      99             : 
     100           1 :   qst->qst_n_cfgs--;
     101             : 
     102           1 :   if (0 == qst->qst_n_cfgs)
     103             :     {
     104           1 :       qos_store_feature_config (sw_if_index, input_source, 0, qst->qst_value);
     105             :     }
     106             : 
     107           1 :   return (0);
     108             : }
     109             : 
     110             : void
     111           2 : qos_store_walk (qos_store_walk_cb_t fn, void *c)
     112             : {
     113             :   qos_source_t qs;
     114             : 
     115          10 :   FOR_EACH_QOS_SOURCE (qs)
     116             :   {
     117             :     qos_store_t *qst;
     118             :     u32 sw_if_index;
     119             : 
     120          12 :     vec_foreach_index (sw_if_index, qos_store_configs[qs])
     121             :     {
     122           4 :       qst = &qos_store_configs[qs][sw_if_index];
     123           4 :       if (0 != qst->qst_n_cfgs)
     124           1 :         fn (sw_if_index, qs, qst->qst_value, c);
     125             :     }
     126             :   }
     127           2 : }
     128             : 
     129             : /*
     130             :  * Disable storing feature for all protocols when the interface
     131             :  * is deleted
     132             :  */
     133             : static clib_error_t *
     134       11597 : qos_store_ip_interface_add_del (vnet_main_t * vnm,
     135             :                                 u32 sw_if_index, u32 is_add)
     136             : {
     137       11597 :   if (!is_add)
     138             :     {
     139             :       qos_source_t qs;
     140             : 
     141       20895 :       FOR_EACH_QOS_SOURCE (qs)
     142             :       {
     143       16716 :         while (qos_store_disable (sw_if_index, qs) == 0);
     144             :       }
     145             :     }
     146             : 
     147       11597 :   return (NULL);
     148             : }
     149             : 
     150        3363 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (qos_store_ip_interface_add_del);
     151             : 
     152             : clib_error_t *
     153         559 : qos_store_init (vlib_main_t * vm)
     154             : {
     155         559 :   return 0;
     156             : }
     157             : 
     158       87359 : VLIB_INIT_FUNCTION (qos_store_init);
     159             : 
     160             : static clib_error_t *
     161           0 : qos_store_cli (vlib_main_t * vm,
     162             :                unformat_input_t * input, vlib_cli_command_t * cmd)
     163             : {
     164           0 :   vnet_main_t *vnm = vnet_get_main ();
     165             :   u32 sw_if_index, qs, value;
     166             :   u8 enable;
     167             : 
     168           0 :   qs = 0xff;
     169           0 :   enable = 1;
     170           0 :   sw_if_index = ~0;
     171           0 :   value = ~0;
     172             : 
     173           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     174             :     {
     175           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     176             :                     vnm, &sw_if_index))
     177             :         ;
     178           0 :       else if (unformat (input, "%U", unformat_qos_source, &qs))
     179             :         ;
     180           0 :       else if (unformat (input, "enable"))
     181           0 :         enable = 1;
     182           0 :       else if (unformat (input, "disable"))
     183           0 :         enable = 0;
     184           0 :       else if (unformat (input, "value &d", &value))
     185             :         ;
     186             :       else
     187           0 :         break;
     188             :     }
     189             : 
     190           0 :   if (~0 == sw_if_index)
     191           0 :     return clib_error_return (0, "interface must be specified");
     192           0 :   if (~0 == value)
     193           0 :     return clib_error_return (0, "value to be stored must be specified");
     194           0 :   if (0xff == qs)
     195           0 :     return clib_error_return (0, "input location must be specified");
     196             : 
     197           0 :   if (enable)
     198           0 :     qos_store_enable (sw_if_index, qs, value);
     199             :   else
     200           0 :     qos_store_disable (sw_if_index, qs);
     201             : 
     202           0 :   return (NULL);
     203             : }
     204             : 
     205             : /*?
     206             :  * Enable QoS bit storing on an interface using the packet's input DSCP bits
     207             :  * Which input QoS bits to use are either; IP, MPLS or VLAN. If more than
     208             :  * one protocol is chosen (which is foolish) the higher layers override the
     209             :  * lower.
     210             :  *
     211             :  * @cliexpar
     212             :  * @cliexcmd{qos store ip GigEthernet0/1/0}
     213             :  ?*/
     214             : /* *INDENT-OFF* */
     215      272887 : VLIB_CLI_COMMAND (qos_store_command, static) = {
     216             :   .path = "qos store",
     217             :   .short_help = "qos store <store-source> <INTERFACE> [disable]",
     218             :   .function = qos_store_cli,
     219             :   .is_mp_safe = 1,
     220             : };
     221             : /* *INDENT-ON* */
     222             : 
     223             : static void
     224           2 : qos_store_show_one_interface (vlib_main_t * vm, u32 sw_if_index)
     225             : {
     226           2 :   u8 n_cfgs[QOS_N_SOURCES] = { };
     227             :   qos_source_t qs;
     228             :   bool set;
     229             : 
     230           2 :   set = false;
     231             : 
     232          10 :   FOR_EACH_QOS_SOURCE (qs)
     233             :   {
     234           8 :     if (vec_len (qos_store_configs[qs]) <= sw_if_index)
     235           6 :       continue;
     236           2 :     if (0 != (n_cfgs[qs] = qos_store_configs[qs][sw_if_index].qst_n_cfgs))
     237           1 :       set = true;
     238             :   }
     239             : 
     240           2 :   if (set)
     241             :     {
     242           1 :       vlib_cli_output (vm, " %U:", format_vnet_sw_if_index_name,
     243             :                        vnet_get_main (), sw_if_index);
     244             : 
     245           5 :       FOR_EACH_QOS_SOURCE (qs)
     246             :       {
     247           4 :         if (n_cfgs[qs] != 0)
     248           1 :           vlib_cli_output (vm, "  %U -> %d",
     249             :                            format_qos_source, qs,
     250           1 :                            qos_store_configs[qs][sw_if_index].qst_value);
     251             :       }
     252             :     }
     253           2 : }
     254             : 
     255             : static clib_error_t *
     256           1 : qos_store_show (vlib_main_t * vm,
     257             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     258             : {
     259           1 :   vnet_main_t *vnm = vnet_get_main ();
     260             :   qos_source_t qs;
     261             :   u32 sw_if_index;
     262             : 
     263           1 :   sw_if_index = ~0;
     264             : 
     265           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     266             :     {
     267           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     268             :                     vnm, &sw_if_index))
     269             :         ;
     270             :     }
     271             : 
     272           1 :   if (~0 == sw_if_index)
     273             :     {
     274           1 :       u32 ii, n_ints = 0;
     275             : 
     276           5 :       FOR_EACH_QOS_SOURCE (qs)
     277             :       {
     278           4 :         n_ints = clib_max (n_ints, vec_len (qos_store_configs[qs]));
     279             :       }
     280             : 
     281           3 :       for (ii = 0; ii < n_ints; ii++)
     282             :         {
     283           2 :           qos_store_show_one_interface (vm, ii);
     284             :         }
     285             :     }
     286             :   else
     287           0 :     qos_store_show_one_interface (vm, sw_if_index);
     288             : 
     289           1 :   return (NULL);
     290             : }
     291             : 
     292             : /*?
     293             :  * Show Egress Qos Maps
     294             :  *
     295             :  * @cliexpar
     296             :  * @cliexcmd{show qos egress map}
     297             :  ?*/
     298             : /* *INDENT-OFF* */
     299      272887 : VLIB_CLI_COMMAND (qos_store_show_command, static) = {
     300             :   .path = "show qos store",
     301             :   .short_help = "show qos store [interface]",
     302             :   .function = qos_store_show,
     303             :   .is_mp_safe = 1,
     304             : };
     305             : /* *INDENT-ON* */
     306             : 
     307             : /*
     308             :  * fd.io coding-style-patch-verification: ON
     309             :  *
     310             :  * Local Variables:
     311             :  * eval: (c-set-style "gnu")
     312             :  * End:
     313             :  */

Generated by: LCOV version 1.14