LCOV - code coverage report
Current view: top level - vnet/qos - qos_record_node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 73 90 81.1 %
Date: 2023-10-26 01:39:38 Functions: 69 92 75.0 %

          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             : extern u8 *qos_record_configs[QOS_N_SOURCES];
      25             : extern u32 l2_qos_input_next[QOS_N_SOURCES][32];
      26             : 
      27             : /**
      28             :  * per-packet trace data
      29             :  */
      30             : typedef struct qos_record_trace_t_
      31             : {
      32             :   /* per-pkt trace data */
      33             :   qos_bits_t bits;
      34             : } qos_record_trace_t;
      35             : 
      36             : /* packet trace format function */
      37             : static u8 *
      38        1184 : format_qos_record_trace (u8 * s, va_list * args)
      39             : {
      40        1184 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      41        1184 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      42        1184 :   qos_record_trace_t *t = va_arg (*args, qos_record_trace_t *);
      43             : 
      44        1184 :   s = format (s, "qos:%d", t->bits);
      45             : 
      46        1184 :   return s;
      47             : }
      48             : 
      49             : static inline uword
      50          21 : qos_record_inline (vlib_main_t * vm,
      51             :                    vlib_node_runtime_t * node,
      52             :                    vlib_frame_t * frame,
      53             :                    qos_source_t qos_src, dpo_proto_t dproto, int is_l2)
      54             : {
      55             :   u32 n_left_from, *from, *to_next, next_index;
      56             : 
      57          21 :   next_index = 0;
      58          21 :   n_left_from = frame->n_vectors;
      59          21 :   from = vlib_frame_vector_args (frame);
      60             : 
      61          42 :   while (n_left_from > 0)
      62             :     {
      63             :       u32 n_left_to_next;
      64             : 
      65          21 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
      66             : 
      67        1428 :       while (n_left_from > 0 && n_left_to_next > 0)
      68             :         {
      69             :           ip4_header_t *ip4_0;
      70             :           ip6_header_t *ip6_0;
      71             :           vlib_buffer_t *b0;
      72             :           u32 next0, bi0;
      73             :           qos_bits_t qos0;
      74             :           u8 l2_len;
      75             : 
      76        1407 :           next0 = 0;
      77        1407 :           bi0 = from[0];
      78        1407 :           to_next[0] = bi0;
      79        1407 :           from += 1;
      80        1407 :           to_next += 1;
      81        1407 :           n_left_from -= 1;
      82        1407 :           n_left_to_next -= 1;
      83             : 
      84        1407 :           b0 = vlib_get_buffer (vm, bi0);
      85             : 
      86        1407 :           if (is_l2)
      87             :             {
      88           0 :               l2_len = vnet_buffer (b0)->l2.l2_len;
      89             :               u8 *l3h;
      90             :               u16 ethertype;
      91             : 
      92           0 :               vlib_buffer_advance (b0, l2_len);
      93             : 
      94           0 :               l3h = vlib_buffer_get_current (b0);
      95           0 :               ethertype = clib_net_to_host_u16 (*(u16 *) (l3h - 2));
      96             : 
      97           0 :               if (ethertype == ETHERNET_TYPE_IP4)
      98           0 :                 dproto = DPO_PROTO_IP4;
      99           0 :               else if (ethertype == ETHERNET_TYPE_IP6)
     100           0 :                 dproto = DPO_PROTO_IP6;
     101           0 :               else if (ethertype == ETHERNET_TYPE_MPLS)
     102           0 :                 dproto = DPO_PROTO_MPLS;
     103             :               else
     104           0 :                 goto non_ip;
     105             :             }
     106             : 
     107        1407 :           if (DPO_PROTO_IP6 == dproto)
     108             :             {
     109         335 :               ip6_0 = vlib_buffer_get_current (b0);
     110         335 :               qos0 = ip6_traffic_class_network_order (ip6_0);
     111             :             }
     112        1072 :           else if (DPO_PROTO_IP4 == dproto)
     113             :             {
     114         737 :               ip4_0 = vlib_buffer_get_current (b0);
     115         737 :               qos0 = ip4_0->tos;
     116             :             }
     117         335 :           else if (DPO_PROTO_ETHERNET == dproto)
     118             :             {
     119             :               ethernet_vlan_header_t *vlan0;
     120             : 
     121         201 :               vlan0 = (vlib_buffer_get_current (b0) -
     122             :                        sizeof (ethernet_vlan_header_t));
     123             : 
     124         201 :               qos0 = ethernet_vlan_header_get_priority_net_order (vlan0);
     125             :             }
     126             :           else if (DPO_PROTO_MPLS)
     127             :             {
     128             :               mpls_unicast_header_t *mh;
     129             : 
     130         134 :               mh = vlib_buffer_get_current (b0);
     131         134 :               qos0 = vnet_mpls_uc_get_exp (mh->label_exp_s_ttl);
     132             :             }
     133             : 
     134        1407 :           vnet_buffer2 (b0)->qos.bits = qos0;
     135        1407 :           vnet_buffer2 (b0)->qos.source = qos_src;
     136        1407 :           b0->flags |= VNET_BUFFER_F_QOS_DATA_VALID;
     137             : 
     138        1407 :           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
     139             :                              (b0->flags & VLIB_BUFFER_IS_TRACED)))
     140             :             {
     141             :               qos_record_trace_t *t =
     142        1407 :                 vlib_add_trace (vm, node, b0, sizeof (*t));
     143        1407 :               t->bits = qos0;
     144             :             }
     145             : 
     146           0 :         non_ip:
     147        1407 :           if (is_l2)
     148             :             {
     149           0 :               vlib_buffer_advance (b0, -l2_len);
     150           0 :               next0 = vnet_l2_feature_next (b0,
     151           0 :                                             l2_qos_input_next[qos_src],
     152             :                                             L2INPUT_FEAT_L2_IP_QOS_RECORD);
     153             :             }
     154             :           else
     155        1407 :             vnet_feature_next (&next0, b0);
     156             : 
     157             :           /* verify speculative enqueue, maybe switch current next frame */
     158        1407 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
     159             :                                            to_next, n_left_to_next,
     160             :                                            bi0, next0);
     161             :         }
     162             : 
     163          21 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     164             :     }
     165             : 
     166          21 :   return frame->n_vectors;
     167             : }
     168             : 
     169             : 
     170        2311 : VLIB_NODE_FN (ip4_qos_record_node) (vlib_main_t * vm,
     171             :                                     vlib_node_runtime_t * node,
     172             :                                     vlib_frame_t * frame)
     173             : {
     174          11 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_IP,
     175             :                              DPO_PROTO_IP4, 0));
     176             : }
     177             : 
     178        2305 : VLIB_NODE_FN (ip6_qos_record_node) (vlib_main_t * vm,
     179             :                                     vlib_node_runtime_t * node,
     180             :                                     vlib_frame_t * frame)
     181             : {
     182           5 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_IP,
     183             :                              DPO_PROTO_IP6, 0));
     184             : }
     185             : 
     186        2302 : VLIB_NODE_FN (mpls_qos_record_node) (vlib_main_t * vm,
     187             :                                      vlib_node_runtime_t * node,
     188             :                                      vlib_frame_t * frame)
     189             : {
     190           2 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_MPLS,
     191             :                              DPO_PROTO_MPLS, 0));
     192             : }
     193             : 
     194        2302 : VLIB_NODE_FN (vlan_ip4_qos_record_node) (vlib_main_t * vm,
     195             :                                          vlib_node_runtime_t * node,
     196             :                                          vlib_frame_t * frame)
     197             : {
     198           2 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN,
     199             :                              DPO_PROTO_ETHERNET, 0));
     200             : }
     201             : 
     202        2301 : VLIB_NODE_FN (vlan_ip6_qos_record_node) (vlib_main_t * vm,
     203             :                                          vlib_node_runtime_t * node,
     204             :                                          vlib_frame_t * frame)
     205             : {
     206           1 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN,
     207             :                              DPO_PROTO_ETHERNET, 0));
     208             : }
     209             : 
     210        2300 : VLIB_NODE_FN (vlan_mpls_qos_record_node) (vlib_main_t * vm,
     211             :                                           vlib_node_runtime_t * node,
     212             :                                           vlib_frame_t * frame)
     213             : {
     214           0 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN,
     215             :                              DPO_PROTO_ETHERNET, 0));
     216             : }
     217             : 
     218        2300 : VLIB_NODE_FN (l2_ip_qos_record_node) (vlib_main_t * vm,
     219             :                                       vlib_node_runtime_t * node,
     220             :                                       vlib_frame_t * frame)
     221             : {
     222           0 :   return (qos_record_inline (vm, node, frame, QOS_SOURCE_VLAN, 0, 1));
     223             : }
     224             : 
     225             : /* *INDENT-OFF* */
     226      183788 : VLIB_REGISTER_NODE (ip4_qos_record_node) = {
     227             :   .name = "ip4-qos-record",
     228             :   .vector_size = sizeof (u32),
     229             :   .format_trace = format_qos_record_trace,
     230             :   .type = VLIB_NODE_TYPE_INTERNAL,
     231             : 
     232             :   .n_errors = 0,
     233             :   .n_next_nodes = 1,
     234             : 
     235             :   .next_nodes = {
     236             :     [0] = "ip4-drop",
     237             :   },
     238             : };
     239             : 
     240       76635 : VNET_FEATURE_INIT (ip4_qos_record_node, static) = {
     241             :     .arc_name = "ip4-unicast",
     242             :     .node_name = "ip4-qos-record",
     243             : };
     244       76635 : VNET_FEATURE_INIT (ip4m_qos_record_node, static) = {
     245             :     .arc_name = "ip4-multicast",
     246             :     .node_name = "ip4-qos-record",
     247             : };
     248             : 
     249      183788 : VLIB_REGISTER_NODE (ip6_qos_record_node) = {
     250             :   .name = "ip6-qos-record",
     251             :   .vector_size = sizeof (u32),
     252             :   .format_trace = format_qos_record_trace,
     253             :   .type = VLIB_NODE_TYPE_INTERNAL,
     254             : 
     255             :   .n_errors = 0,
     256             :   .n_next_nodes = 1,
     257             : 
     258             :   .next_nodes = {
     259             :     [0] = "ip6-drop",
     260             :   },
     261             : };
     262             : 
     263       76635 : VNET_FEATURE_INIT (ip6_qos_record_node, static) = {
     264             :     .arc_name = "ip6-unicast",
     265             :     .node_name = "ip6-qos-record",
     266             : };
     267       76635 : VNET_FEATURE_INIT (ip6m_qos_record_node, static) = {
     268             :     .arc_name = "ip6-multicast",
     269             :     .node_name = "ip6-qos-record",
     270             : };
     271             : 
     272      183788 : VLIB_REGISTER_NODE (mpls_qos_record_node) = {
     273             :   .name = "mpls-qos-record",
     274             :   .vector_size = sizeof (u32),
     275             :   .format_trace = format_qos_record_trace,
     276             :   .type = VLIB_NODE_TYPE_INTERNAL,
     277             : 
     278             :   .n_errors = 0,
     279             :   .n_next_nodes = 1,
     280             : 
     281             :   .next_nodes = {
     282             :     [0] = "mpls-drop",
     283             :   },
     284             : };
     285             : 
     286       76635 : VNET_FEATURE_INIT (mpls_qos_record_node, static) = {
     287             :     .arc_name = "mpls-input",
     288             :     .node_name = "mpls-qos-record",
     289             : };
     290             : 
     291      183788 : VLIB_REGISTER_NODE (vlan_mpls_qos_record_node) = {
     292             :   .name = "vlan-mpls-qos-record",
     293             :   .vector_size = sizeof (u32),
     294             :   .format_trace = format_qos_record_trace,
     295             :   .type = VLIB_NODE_TYPE_INTERNAL,
     296             : 
     297             :   .n_errors = 0,
     298             :   .n_next_nodes = 1,
     299             : 
     300             :   .next_nodes = {
     301             :     [0] = "mpls-drop",
     302             :   },
     303             : };
     304             : 
     305       76635 : VNET_FEATURE_INIT (vlan_mpls_qos_record_node, static) = {
     306             :     .arc_name = "mpls-input",
     307             :     .node_name = "vlan-mpls-qos-record",
     308             :     .runs_before = VNET_FEATURES ("mpls-qos-record"),
     309             : };
     310             : 
     311      183788 : VLIB_REGISTER_NODE (vlan_ip4_qos_record_node) = {
     312             :   .name = "vlan-ip4-qos-record",
     313             :   .vector_size = sizeof (u32),
     314             :   .format_trace = format_qos_record_trace,
     315             :   .type = VLIB_NODE_TYPE_INTERNAL,
     316             : 
     317             :   .n_errors = 0,
     318             :   .n_next_nodes = 1,
     319             : 
     320             :   .next_nodes = {
     321             :     [0] = "ip4-drop",
     322             :   },
     323             : };
     324             : 
     325       76635 : VNET_FEATURE_INIT (vlan_ip4_qos_record_node, static) = {
     326             :     .arc_name = "ip4-unicast",
     327             :     .node_name = "vlan-ip4-qos-record",
     328             :     .runs_before = VNET_FEATURES ("ip4-qos-record"),
     329             : };
     330       76635 : VNET_FEATURE_INIT (vlan_ip4m_qos_record_node, static) = {
     331             :     .arc_name = "ip4-multicast",
     332             :     .node_name = "vlan-ip4-qos-record",
     333             :     .runs_before = VNET_FEATURES ("ip4-qos-record"),
     334             : };
     335             : 
     336      183788 : VLIB_REGISTER_NODE (vlan_ip6_qos_record_node) = {
     337             :   .name = "vlan-ip6-qos-record",
     338             :   .vector_size = sizeof (u32),
     339             :   .format_trace = format_qos_record_trace,
     340             :   .type = VLIB_NODE_TYPE_INTERNAL,
     341             : 
     342             :   .n_errors = 0,
     343             :   .n_next_nodes = 1,
     344             : 
     345             :   .next_nodes = {
     346             :     [0] = "ip6-drop",
     347             :   },
     348             : };
     349             : 
     350       76635 : VNET_FEATURE_INIT (vlan_ip6_qos_record_node, static) = {
     351             :     .arc_name = "ip6-unicast",
     352             :     .node_name = "vlan-ip6-qos-record",
     353             :     .runs_before = VNET_FEATURES ("ip6-qos-record"),
     354             : };
     355       76635 : VNET_FEATURE_INIT (vlan_ip6m_qos_record_node, static) = {
     356             :     .arc_name = "ip6-multicast",
     357             :     .node_name = "vlan-ip6-qos-record",
     358             :     .runs_before = VNET_FEATURES ("ip6-qos-record"),
     359             : };
     360             : 
     361      183788 : VLIB_REGISTER_NODE (l2_ip_qos_record_node) = {
     362             :   .name = "l2-ip-qos-record",
     363             :   .vector_size = sizeof (u32),
     364             :   .format_trace = format_qos_record_trace,
     365             :   .type = VLIB_NODE_TYPE_INTERNAL,
     366             : 
     367             :   .n_errors = 0,
     368             :   .n_next_nodes = 1,
     369             : 
     370             :   /* Consider adding error "no IP after L2, no recording" */
     371             :   .next_nodes = {
     372             :     [0] = "error-drop",
     373             :   },
     374             : };
     375             : /* *INDENT-ON* */
     376             : 
     377             : /*
     378             :  * fd.io coding-style-patch-verification: ON
     379             :  *
     380             :  * Local Variables:
     381             :  * eval: (c-set-style "gnu")
     382             :  * End:
     383             :  */

Generated by: LCOV version 1.14