LCOV - code coverage report
Current view: top level - vnet/qos - qos_mark.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 73 103 70.9 %
Date: 2023-10-26 01:39:38 Functions: 13 14 92.9 %

          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/ip/ip.h>
      17             : #include <vnet/feature/feature.h>
      18             : #include <vnet/qos/qos_egress_map.h>
      19             : #include <vnet/qos/qos_mark.h>
      20             : 
      21             : /**
      22             :  * per-interface vector of which MAP is used by which interface
      23             :  * for each output source
      24             :  */
      25             : index_t *qos_mark_configs[QOS_N_SOURCES];
      26             : 
      27             : void
      28          12 : qos_mark_ip_enable_disable (u32 sw_if_index, u8 enable)
      29             : {
      30          12 :   vnet_feature_enable_disable ("ip6-output", "ip6-qos-mark",
      31             :                                sw_if_index, enable, NULL, 0);
      32          12 :   vnet_feature_enable_disable ("ip4-output", "ip4-qos-mark",
      33             :                                sw_if_index, enable, NULL, 0);
      34          12 : }
      35             : 
      36             : void
      37           4 : qos_mark_vlan_enable_disable (u32 sw_if_index, u8 enable)
      38             : {
      39             :   /*
      40             :    * one cannot run a feature on a sub-interface, so we need
      41             :    * to enable a feature on all the L3 output paths
      42             :    */
      43           4 :   vnet_feature_enable_disable ("ip6-output", "vlan-ip6-qos-mark",
      44             :                                sw_if_index, enable, NULL, 0);
      45           4 :   vnet_feature_enable_disable ("ip4-output", "vlan-ip4-qos-mark",
      46             :                                sw_if_index, enable, NULL, 0);
      47           4 :   vnet_feature_enable_disable ("mpls-output", "vlan-mpls-qos-mark",
      48             :                                sw_if_index, enable, NULL, 0);
      49           4 : }
      50             : 
      51             : void
      52           2 : qos_mark_mpls_enable_disable (u32 sw_if_index, u8 enable)
      53             : {
      54           2 :   vnet_feature_enable_disable ("mpls-output", "mpls-qos-mark",
      55             :                                sw_if_index, enable, NULL, 0);
      56           2 : }
      57             : 
      58             : static void
      59          18 : qos_egress_map_feature_config (u32 sw_if_index, qos_source_t qs, u8 enable)
      60             : {
      61          18 :   switch (qs)
      62             :     {
      63           0 :     case QOS_SOURCE_EXT:
      64           0 :       ASSERT (0);
      65           0 :       break;
      66           4 :     case QOS_SOURCE_VLAN:
      67           4 :       qos_mark_vlan_enable_disable (sw_if_index, enable);
      68           4 :       break;
      69           2 :     case QOS_SOURCE_MPLS:
      70           2 :       qos_mark_mpls_enable_disable (sw_if_index, enable);
      71           2 :       break;
      72          12 :     case QOS_SOURCE_IP:
      73          12 :       qos_mark_ip_enable_disable (sw_if_index, enable);
      74          12 :       break;
      75             :     }
      76          18 : }
      77             : 
      78             : int
      79           9 : qos_mark_enable (u32 sw_if_index,
      80             :                  qos_source_t output_source, qos_egress_map_id_t mid)
      81             : {
      82             :   index_t qemi;
      83             : 
      84          33 :   vec_validate_init_empty (qos_mark_configs[output_source],
      85             :                            sw_if_index, INDEX_INVALID);
      86             : 
      87           9 :   qemi = qos_egress_map_find (mid);
      88             : 
      89           9 :   if (INDEX_INVALID == qemi)
      90           0 :     return VNET_API_ERROR_NO_SUCH_TABLE;
      91             : 
      92           9 :   if (INDEX_INVALID == qos_mark_configs[output_source][sw_if_index])
      93             :     {
      94           9 :       qos_egress_map_feature_config (sw_if_index, output_source, 1);
      95             :     }
      96             : 
      97           9 :   qos_mark_configs[output_source][sw_if_index] = qemi;
      98             : 
      99           9 :   return (0);
     100             : }
     101             : 
     102             : int
     103           9 : qos_mark_disable (u32 sw_if_index, qos_source_t output_source)
     104             : {
     105           9 :   if (vec_len (qos_mark_configs[output_source]) <= sw_if_index)
     106           0 :     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
     107           9 :   if (INDEX_INVALID == qos_mark_configs[output_source][sw_if_index])
     108           0 :     return VNET_API_ERROR_VALUE_EXIST;
     109             : 
     110           9 :   if (INDEX_INVALID != qos_mark_configs[output_source][sw_if_index])
     111             :     {
     112           9 :       qos_egress_map_feature_config (sw_if_index, output_source, 0);
     113             :     }
     114             : 
     115           9 :   qos_mark_configs[output_source][sw_if_index] = INDEX_INVALID;
     116             : 
     117           9 :   return (0);
     118             : }
     119             : 
     120             : void
     121          16 : qos_mark_walk (qos_mark_walk_cb_t fn, void *c)
     122             : {
     123             :   qos_source_t qs;
     124             : 
     125          80 :   FOR_EACH_QOS_SOURCE (qs)
     126             :   {
     127             :     u32 sw_if_index;
     128             : 
     129         216 :     vec_foreach_index (sw_if_index, qos_mark_configs[qs])
     130             :     {
     131         152 :       if (INDEX_INVALID != qos_mark_configs[qs][sw_if_index])
     132          15 :         fn (sw_if_index,
     133          15 :             qos_egress_map_get_id (qos_mark_configs[qs][sw_if_index]), qs, c);
     134             :     }
     135             :   }
     136          16 : }
     137             : 
     138             : static clib_error_t *
     139           0 : qos_mark_cli (vlib_main_t * vm,
     140             :               unformat_input_t * input, vlib_cli_command_t * cmd)
     141             : {
     142             :   qos_egress_map_id_t map_id;
     143             :   u32 sw_if_index, qs;
     144             :   vnet_main_t *vnm;
     145             :   int rv, enable;
     146             : 
     147           0 :   vnm = vnet_get_main ();
     148           0 :   map_id = ~0;
     149           0 :   qs = 0xff;
     150           0 :   enable = 1;
     151             : 
     152           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     153             :     {
     154           0 :       if (unformat (input, "id %d", &map_id))
     155             :         ;
     156           0 :       else if (unformat (input, "disable"))
     157           0 :         enable = 0;
     158           0 :       else if (unformat (input, "%U", unformat_qos_source, &qs))
     159             :         ;
     160           0 :       else if (unformat (input, "%U",
     161             :                          unformat_vnet_sw_interface, vnm, &sw_if_index))
     162             :         ;
     163             :       else
     164           0 :         break;
     165             :     }
     166             : 
     167           0 :   if (~0 == sw_if_index)
     168           0 :     return clib_error_return (0, "interface must be specified");
     169           0 :   if (0xff == qs)
     170           0 :     return clib_error_return (0, "output location must be specified");
     171             : 
     172           0 :   if (enable)
     173           0 :     rv = qos_mark_enable (sw_if_index, qs, map_id);
     174             :   else
     175           0 :     rv = qos_mark_disable (sw_if_index, qs);
     176             : 
     177           0 :   if (0 == rv)
     178           0 :     return (NULL);
     179             : 
     180           0 :   return clib_error_return (0, "Failed to map interface");
     181             : }
     182             : 
     183             : /*?
     184             :  * Apply a QoS egress mapping table to an interface for QoS marking packets
     185             :  * at the given output protocol.
     186             :  *
     187             :  * @cliexpar
     188             :  * @cliexcmd{qos egress interface GigEthernet0/9/0 id 0 output ip}
     189             :  ?*/
     190             : /* *INDENT-OFF* */
     191      285289 : VLIB_CLI_COMMAND (qos_egress_map_interface_command, static) = {
     192             :   .path = "qos mark",
     193             :   .short_help = "qos mark <SOURCE> <INTERFACE> id <MAP>",
     194             :   .function = qos_mark_cli,
     195             :   .is_mp_safe = 1,
     196             : };
     197             : /* *INDENT-ON* */
     198             : 
     199             : static void
     200          12 : qos_mark_show_one_interface (vlib_main_t * vm, u32 sw_if_index)
     201             : {
     202             :   index_t qemis[QOS_N_SOURCES];
     203             :   qos_source_t qs;
     204             :   bool set;
     205             : 
     206          12 :   set = false;
     207          12 :   clib_memset_u32 (qemis, INDEX_INVALID, QOS_N_SOURCES);
     208             : 
     209          60 :   FOR_EACH_QOS_SOURCE (qs)
     210             :   {
     211          48 :     if (vec_len (qos_mark_configs[qs]) <= sw_if_index)
     212          36 :       continue;
     213          12 :     if (INDEX_INVALID != (qemis[qs] = qos_mark_configs[qs][sw_if_index]))
     214           6 :       set = true;
     215             :   }
     216             : 
     217          12 :   if (set)
     218             :     {
     219           6 :       vlib_cli_output (vm, " %U:", format_vnet_sw_if_index_name,
     220             :                        vnet_get_main (), sw_if_index);
     221             : 
     222          30 :       FOR_EACH_QOS_SOURCE (qs)
     223             :       {
     224          24 :         if (qemis[qs] != INDEX_INVALID)
     225           6 :           vlib_cli_output (vm, "  %U: map:%d", format_qos_source, qs,
     226             :                            qemis[qs]);
     227             :       }
     228             :     }
     229          12 : }
     230             : 
     231             : static clib_error_t *
     232           2 : qos_mark_show (vlib_main_t * vm,
     233             :                unformat_input_t * input, vlib_cli_command_t * cmd)
     234             : {
     235           2 :   vnet_main_t *vnm = vnet_get_main ();
     236             :   qos_source_t qs;
     237             :   u32 sw_if_index;
     238             : 
     239           2 :   sw_if_index = ~0;
     240             : 
     241           2 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     242             :     {
     243           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface,
     244             :                     vnm, &sw_if_index))
     245             :         ;
     246             :     }
     247             : 
     248           2 :   if (~0 == sw_if_index)
     249             :     {
     250           2 :       u32 ii, n_ints = 0;
     251             : 
     252          10 :       FOR_EACH_QOS_SOURCE (qs)
     253             :       {
     254           8 :         n_ints = clib_max (n_ints, vec_len (qos_mark_configs[qs]));
     255             :       }
     256             : 
     257          14 :       for (ii = 0; ii < n_ints; ii++)
     258             :         {
     259          12 :           qos_mark_show_one_interface (vm, ii);
     260             :         }
     261             :     }
     262             :   else
     263           0 :     qos_mark_show_one_interface (vm, sw_if_index);
     264             : 
     265           2 :   return (NULL);
     266             : }
     267             : 
     268             : /*?
     269             :  * Show Egress Qos Maps
     270             :  *
     271             :  * @cliexpar
     272             :  * @cliexcmd{show qos egress map}
     273             :  ?*/
     274             : /* *INDENT-OFF* */
     275      285289 : VLIB_CLI_COMMAND (qos_mark_show_command, static) = {
     276             :   .path = "show qos mark",
     277             :   .short_help = "show qos mark [interface]",
     278             :   .function = qos_mark_show,
     279             :   .is_mp_safe = 1,
     280             : };
     281             : /* *INDENT-ON* */
     282             : 
     283             : /*
     284             :  * fd.io coding-style-patch-verification: ON
     285             :  *
     286             : * Local Variables:
     287             : * eval: (c-set-style "gnu")
     288             : * End:
     289             : *
     290             : */

Generated by: LCOV version 1.14