LCOV - code coverage report
Current view: top level - vnet/dpo - interface_rx_dpo.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 119 125 95.2 %
Date: 2023-07-05 22:20:52 Functions: 39 50 78.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 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/dpo/interface_rx_dpo.h>
      17             : #include <vnet/fib/fib_node.h>
      18             : #include <vnet/l2/l2_input.h>
      19             : 
      20             : #ifndef CLIB_MARCH_VARIANT
      21             : interface_rx_dpo_t *interface_rx_dpo_pool;
      22             : 
      23             : /*
      24             :  * The 'DB' of interface DPOs.
      25             :  * There is only one  per-interface per-protocol, so this is a per-interface
      26             :  * vector
      27             :  */
      28             : static index_t *interface_rx_dpo_db[DPO_PROTO_NUM];
      29             : 
      30             : static interface_rx_dpo_t *
      31           6 : interface_rx_dpo_alloc (void)
      32             : {
      33             :     interface_rx_dpo_t *ido;
      34             : 
      35           6 :     pool_get(interface_rx_dpo_pool, ido);
      36             : 
      37           6 :     return (ido);
      38             : }
      39             : 
      40             : static inline interface_rx_dpo_t *
      41         146 : interface_rx_dpo_get_from_dpo (const dpo_id_t *dpo)
      42             : {
      43         146 :     ASSERT(DPO_INTERFACE_RX == dpo->dpoi_type);
      44             : 
      45         146 :     return (interface_rx_dpo_get(dpo->dpoi_index));
      46             : }
      47             : 
      48             : static inline index_t
      49          36 : interface_rx_dpo_get_index (interface_rx_dpo_t *ido)
      50             : {
      51          36 :     return (ido - interface_rx_dpo_pool);
      52             : }
      53             : 
      54             : static void
      55          73 : interface_rx_dpo_lock (dpo_id_t *dpo)
      56             : {
      57             :     interface_rx_dpo_t *ido;
      58             : 
      59          73 :     ido = interface_rx_dpo_get_from_dpo(dpo);
      60          73 :     ido->ido_locks++;
      61          73 : }
      62             : 
      63             : static void
      64          73 : interface_rx_dpo_unlock (dpo_id_t *dpo)
      65             : {
      66             :     interface_rx_dpo_t *ido;
      67             : 
      68          73 :     ido = interface_rx_dpo_get_from_dpo(dpo);
      69          73 :     ido->ido_locks--;
      70             : 
      71          73 :     if (0 == ido->ido_locks)
      72             :     {
      73           6 :         interface_rx_dpo_db[ido->ido_proto][ido->ido_sw_if_index] =
      74             :             INDEX_INVALID;
      75           6 :         pool_put(interface_rx_dpo_pool, ido);
      76             :     }
      77          73 : }
      78             : 
      79             : /*
      80             :  * interface_rx_dpo_add_or_lock
      81             :  *
      82             :  * Add/create and lock a new or lock an existing for the interface DPO
      83             :  * on the interface and protocol given
      84             :  */
      85             : void
      86          30 : interface_rx_dpo_add_or_lock (dpo_proto_t proto,
      87             :                               u32 sw_if_index,
      88             :                               dpo_id_t *dpo)
      89             : {
      90             :     interface_rx_dpo_t *ido;
      91             : 
      92          40 :     vec_validate_init_empty(interface_rx_dpo_db[proto],
      93             :                             sw_if_index,
      94             :                             INDEX_INVALID);
      95             : 
      96          30 :     if (INDEX_INVALID == interface_rx_dpo_db[proto][sw_if_index])
      97             :     {
      98           6 :         ido = interface_rx_dpo_alloc();
      99             : 
     100           6 :         ido->ido_sw_if_index = sw_if_index;
     101           6 :         ido->ido_proto = proto;
     102             : 
     103           6 :         interface_rx_dpo_db[proto][sw_if_index] =
     104           6 :             interface_rx_dpo_get_index(ido);
     105             :     }
     106             :     else
     107             :     {
     108          24 :         ido = interface_rx_dpo_get(interface_rx_dpo_db[proto][sw_if_index]);
     109             :     }
     110             : 
     111          30 :     dpo_set(dpo, DPO_INTERFACE_RX, proto, interface_rx_dpo_get_index(ido));
     112          30 : }
     113             : #endif /* CLIB_MARCH_VARIANT */
     114             : 
     115             : 
     116             : static clib_error_t *
     117       13268 : interface_rx_dpo_interface_state_change (vnet_main_t * vnm,
     118             :                                          u32 sw_if_index,
     119             :                                          u32 flags)
     120             : {
     121             :     /*
     122             :      */
     123       13268 :     return (NULL);
     124             : }
     125             : 
     126        2801 : VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(
     127             :     interface_rx_dpo_interface_state_change);
     128             : 
     129             : /**
     130             :  * @brief Registered callback for HW interface state changes
     131             :  */
     132             : static clib_error_t *
     133       13092 : interface_rx_dpo_hw_interface_state_change (vnet_main_t * vnm,
     134             :                                             u32 hw_if_index,
     135             :                                             u32 flags)
     136             : {
     137       13092 :     return (NULL);
     138             : }
     139             : 
     140        2801 : VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(
     141             :     interface_rx_dpo_hw_interface_state_change);
     142             : 
     143             : static clib_error_t *
     144       11597 : interface_rx_dpo_interface_delete (vnet_main_t * vnm,
     145             :                                    u32 sw_if_index,
     146             :                                    u32 is_add)
     147             : {
     148       11597 :     return (NULL);
     149             : }
     150             : 
     151        3363 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION(
     152             :     interface_rx_dpo_interface_delete);
     153             : 
     154             : #ifndef CLIB_MARCH_VARIANT
     155             : static u8*
     156         259 : format_interface_rx_dpo (u8* s, va_list *ap)
     157             : {
     158         259 :     index_t index = va_arg(*ap, index_t);
     159         259 :     CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
     160         259 :     vnet_main_t * vnm = vnet_get_main();
     161         259 :     interface_rx_dpo_t *ido = interface_rx_dpo_get(index);
     162             : 
     163         259 :     return (format(s, "%U-rx-dpo: %U",
     164             :                    format_vnet_sw_interface_name,
     165             :                    vnm,
     166             :                    vnet_get_sw_interface(vnm, ido->ido_sw_if_index),
     167         259 :                    format_dpo_proto, ido->ido_proto));
     168             : }
     169             : 
     170             : static void
     171           0 : interface_rx_dpo_mem_show (void)
     172             : {
     173           0 :     fib_show_memory_usage("Interface",
     174           0 :                           pool_elts(interface_rx_dpo_pool),
     175           0 :                           pool_len(interface_rx_dpo_pool),
     176             :                           sizeof(interface_rx_dpo_t));
     177           0 : }
     178             : 
     179             : 
     180             : const static dpo_vft_t interface_rx_dpo_vft = {
     181             :     .dv_lock = interface_rx_dpo_lock,
     182             :     .dv_unlock = interface_rx_dpo_unlock,
     183             :     .dv_format = format_interface_rx_dpo,
     184             :     .dv_mem_show = interface_rx_dpo_mem_show,
     185             : };
     186             : 
     187             : /**
     188             :  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
     189             :  *        object.
     190             :  *
     191             :  * this means that these graph nodes are ones from which a glean is the
     192             :  * parent object in the DPO-graph.
     193             :  */
     194             : const static char* const interface_rx_dpo_ip4_nodes[] =
     195             : {
     196             :     "interface-rx-dpo-ip4",
     197             :     NULL,
     198             : };
     199             : const static char* const interface_rx_dpo_ip6_nodes[] =
     200             : {
     201             :     "interface-rx-dpo-ip6",
     202             :     NULL,
     203             : };
     204             : const static char* const interface_rx_dpo_l2_nodes[] =
     205             : {
     206             :     "interface-rx-dpo-l2",
     207             :     NULL,
     208             : };
     209             : 
     210             : const static char* const * const interface_rx_dpo_nodes[DPO_PROTO_NUM] =
     211             : {
     212             :     [DPO_PROTO_IP4]  = interface_rx_dpo_ip4_nodes,
     213             :     [DPO_PROTO_IP6]  = interface_rx_dpo_ip6_nodes,
     214             :     [DPO_PROTO_ETHERNET]  = interface_rx_dpo_l2_nodes,
     215             :     [DPO_PROTO_MPLS] = NULL,
     216             : };
     217             : 
     218             : void
     219         559 : interface_rx_dpo_module_init (void)
     220             : {
     221         559 :     dpo_register(DPO_INTERFACE_RX,
     222             :                  &interface_rx_dpo_vft,
     223             :                  interface_rx_dpo_nodes);
     224         559 : }
     225             : #endif /* CLIB_MARCH_VARIANT */
     226             : 
     227             : /**
     228             :  * @brief Interface DPO trace data
     229             :  */
     230             : typedef struct interface_rx_dpo_trace_t_
     231             : {
     232             :     u32 sw_if_index;
     233             : } interface_rx_dpo_trace_t;
     234             : 
     235             : typedef enum interface_rx_dpo_next_t_
     236             : {
     237             :     INTERFACE_RX_DPO_DROP = 0,
     238             :     INTERFACE_RX_DPO_INPUT = 1,
     239             : } interface_rx_dpo_next_t;
     240             : 
     241             : always_inline uword
     242           9 : interface_rx_dpo_inline (vlib_main_t * vm,
     243             :                          vlib_node_runtime_t * node,
     244             :                          vlib_frame_t * from_frame,
     245             :                          u8 is_l2)
     246             : {
     247             :     u32 n_left_from, next_index, * from, * to_next;
     248           9 :     u32 thread_index = vm->thread_index;
     249             :     vnet_interface_main_t *im;
     250             : 
     251           9 :     im = &vnet_get_main ()->interface_main;
     252           9 :     from = vlib_frame_vector_args (from_frame);
     253           9 :     n_left_from = from_frame->n_vectors;
     254             : 
     255           9 :     next_index = INTERFACE_RX_DPO_INPUT;
     256             : 
     257          18 :     while (n_left_from > 0)
     258             :     {
     259             :         u32 n_left_to_next;
     260             : 
     261           9 :         vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
     262             : 
     263         359 :         while (n_left_from >= 4 && n_left_to_next > 2)
     264             :         {
     265             :             const interface_rx_dpo_t *ido0, *ido1;
     266             :             u32 bi0, idoi0, bi1, idoi1;
     267             :             vlib_buffer_t *b0, *b1;
     268             : 
     269         350 :             bi0 = from[0];
     270         350 :             to_next[0] = bi0;
     271         350 :             bi1 = from[1];
     272         350 :             to_next[1] = bi1;
     273         350 :             from += 2;
     274         350 :             to_next += 2;
     275         350 :             n_left_from -= 2;
     276         350 :             n_left_to_next -= 2;
     277             : 
     278         350 :             b0 = vlib_get_buffer (vm, bi0);
     279         350 :             b1 = vlib_get_buffer (vm, bi1);
     280             : 
     281         350 :             idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
     282         350 :             idoi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
     283         350 :             ido0 = interface_rx_dpo_get(idoi0);
     284         350 :             ido1 = interface_rx_dpo_get(idoi1);
     285             : 
     286         350 :             vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
     287         350 :             vnet_buffer(b1)->sw_if_index[VLIB_RX] = ido1->ido_sw_if_index;
     288             : 
     289         350 :             if (is_l2)
     290             :             {
     291          96 :                 vnet_update_l2_len (b0);
     292          96 :                 vnet_update_l2_len (b1);
     293             :             }
     294             : 
     295         350 :             vlib_increment_combined_counter (im->combined_sw_if_counters
     296             :                                              + VNET_INTERFACE_COUNTER_RX,
     297             :                                              thread_index,
     298             :                                              ido0->ido_sw_if_index,
     299             :                                              1,
     300             :                                              vlib_buffer_length_in_chain (vm, b0));
     301         350 :             vlib_increment_combined_counter (im->combined_sw_if_counters
     302             :                                              + VNET_INTERFACE_COUNTER_RX,
     303             :                                              thread_index,
     304             :                                              ido1->ido_sw_if_index,
     305             :                                              1,
     306             :                                              vlib_buffer_length_in_chain (vm, b1));
     307             : 
     308         350 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     309             :             {
     310             :                 interface_rx_dpo_trace_t *tr0;
     311             : 
     312         350 :                 tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
     313         350 :                 tr0->sw_if_index = ido0->ido_sw_if_index;
     314             :             }
     315         350 :             if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
     316             :             {
     317             :                 interface_rx_dpo_trace_t *tr1;
     318             : 
     319         350 :                 tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
     320         350 :                 tr1->sw_if_index = ido1->ido_sw_if_index;
     321             :             }
     322             :         }
     323             : 
     324          26 :         while (n_left_from > 0 && n_left_to_next > 0)
     325             :         {
     326             :             const interface_rx_dpo_t * ido0;
     327             :             vlib_buffer_t * b0;
     328             :             u32 bi0, idoi0;
     329             : 
     330          17 :             bi0 = from[0];
     331          17 :             to_next[0] = bi0;
     332          17 :             from += 1;
     333          17 :             to_next += 1;
     334          17 :             n_left_from -= 1;
     335          17 :             n_left_to_next -= 1;
     336             : 
     337          17 :             b0 = vlib_get_buffer (vm, bi0);
     338             : 
     339          17 :             idoi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
     340          17 :             ido0 = interface_rx_dpo_get(idoi0);
     341             : 
     342             :             /* Swap the RX interface of the packet to the one the
     343             :              * interface DPR represents */
     344          17 :             vnet_buffer(b0)->sw_if_index[VLIB_RX] = ido0->ido_sw_if_index;
     345             : 
     346             :             /* Update l2_len to make l2 tag rewrite work */
     347          17 :             if (is_l2)
     348          11 :                 vnet_update_l2_len (b0);
     349             : 
     350             :             /* Bump the interface's RX coutners */
     351          17 :             vlib_increment_combined_counter (im->combined_sw_if_counters
     352             :                                              + VNET_INTERFACE_COUNTER_RX,
     353             :                                              thread_index,
     354             :                                              ido0->ido_sw_if_index,
     355             :                                              1,
     356             :                                              vlib_buffer_length_in_chain (vm, b0));
     357             : 
     358          17 :             if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     359             :             {
     360             :                 interface_rx_dpo_trace_t *tr;
     361             : 
     362          17 :                 tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
     363          17 :                 tr->sw_if_index = ido0->ido_sw_if_index;
     364             :             }
     365             :         }
     366           9 :         vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     367             :     }
     368           9 :     return from_frame->n_vectors;
     369             : }
     370             : 
     371             : static u8 *
     372         783 : format_interface_rx_dpo_trace (u8 * s, va_list * args)
     373             : {
     374         783 :     CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
     375         783 :     CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
     376         783 :     interface_rx_dpo_trace_t * t = va_arg (*args, interface_rx_dpo_trace_t *);
     377         783 :     u32 indent = format_get_indent (s);
     378         783 :     s = format (s, "%U sw_if_index:%d",
     379             :                 format_white_space, indent,
     380             :                 t->sw_if_index);
     381         783 :     return s;
     382             : }
     383             : 
     384        2240 : VLIB_NODE_FN (interface_rx_dpo_ip4_node) (vlib_main_t * vm,
     385             :                       vlib_node_runtime_t * node,
     386             :                       vlib_frame_t * from_frame)
     387             : {
     388           4 :     return (interface_rx_dpo_inline(vm, node, from_frame, 0));
     389             : }
     390             : 
     391        2236 : VLIB_NODE_FN (interface_rx_dpo_ip6_node) (vlib_main_t * vm,
     392             :                       vlib_node_runtime_t * node,
     393             :                       vlib_frame_t * from_frame)
     394             : {
     395           0 :     return (interface_rx_dpo_inline(vm, node, from_frame, 0));
     396             : }
     397             : 
     398        2241 : VLIB_NODE_FN (interface_rx_dpo_l2_node) (vlib_main_t * vm,
     399             :                      vlib_node_runtime_t * node,
     400             :                      vlib_frame_t * from_frame)
     401             : {
     402           5 :     return (interface_rx_dpo_inline(vm, node, from_frame, 1));
     403             : }
     404             : 
     405      178120 : VLIB_REGISTER_NODE (interface_rx_dpo_ip4_node) = {
     406             :     .name = "interface-rx-dpo-ip4",
     407             :     .vector_size = sizeof (u32),
     408             :     .format_trace = format_interface_rx_dpo_trace,
     409             : 
     410             :     .n_next_nodes = 2,
     411             :     .next_nodes = {
     412             :         [INTERFACE_RX_DPO_DROP] = "ip4-drop",
     413             :         [INTERFACE_RX_DPO_INPUT] = "ip4-input",
     414             :     },
     415             : };
     416             : 
     417             : 
     418      178120 : VLIB_REGISTER_NODE (interface_rx_dpo_ip6_node) = {
     419             :     .name = "interface-rx-dpo-ip6",
     420             :     .vector_size = sizeof (u32),
     421             :     .format_trace = format_interface_rx_dpo_trace,
     422             : 
     423             :     .n_next_nodes = 2,
     424             :     .next_nodes = {
     425             :         [INTERFACE_RX_DPO_DROP] = "ip6-drop",
     426             :         [INTERFACE_RX_DPO_INPUT] = "ip6-input",
     427             :     },
     428             : };
     429             : 
     430             : 
     431      178120 : VLIB_REGISTER_NODE (interface_rx_dpo_l2_node) = {
     432             :     .name = "interface-rx-dpo-l2",
     433             :     .vector_size = sizeof (u32),
     434             :     .format_trace = format_interface_rx_dpo_trace,
     435             : 
     436             :     .n_next_nodes = 2,
     437             :     .next_nodes = {
     438             :         [INTERFACE_RX_DPO_DROP] = "error-drop",
     439             :         [INTERFACE_RX_DPO_INPUT] = "l2-input",
     440             :     },
     441             : };
     442             : 

Generated by: LCOV version 1.14