LCOV - code coverage report
Current view: top level - vnet/gso - gro.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 86 109 78.9 %
Date: 2023-10-26 01:39:38 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 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             : #ifndef included_gro_h
      17             : #define included_gro_h
      18             : 
      19             : #include <vlib/vlib.h>
      20             : #include <vppinfra/error.h>
      21             : #include <vnet/ip/ip46_address.h>
      22             : 
      23             : #define GRO_FLOW_TABLE_MAX_SIZE 16
      24             : #define GRO_FLOW_TABLE_FLUSH 1e-5
      25             : #define GRO_FLOW_N_BUFFERS 64
      26             : #define GRO_FLOW_TIMEOUT 1e-5   /* 10 micro-seconds */
      27             : #define GRO_TO_VECTOR_SIZE(X)   (X + GRO_FLOW_TABLE_MAX_SIZE)
      28             : 
      29             : typedef union
      30             : {
      31             :   struct
      32             :   {
      33             :     u32 sw_if_index[VLIB_N_RX_TX];
      34             :     ip46_address_t src_address;
      35             :     ip46_address_t dst_address;
      36             :     u16 src_port;
      37             :     u16 dst_port;
      38             :   };
      39             : 
      40             :   u64 flow_data[5];
      41             :   u32 flow_data_u32;
      42             : } gro_flow_key_t;
      43             : 
      44             : typedef struct
      45             : {
      46             :   gro_flow_key_t flow_key;
      47             :   f64 next_timeout_ts;
      48             :   u32 last_ack_number;
      49             :   u32 buffer_index;
      50             :   u16 n_buffers;
      51             : } gro_flow_t;
      52             : 
      53             : typedef struct
      54             : {
      55             :   f64 timeout_ts;
      56             :   u64 total_vectors;
      57             :   u32 n_vectors;
      58             :   u32 node_index;
      59             :   u8 is_enable;
      60             :   u8 is_l2;
      61             :   u8 flow_table_size;
      62             :   gro_flow_t gro_flow[GRO_FLOW_TABLE_MAX_SIZE];
      63             : } gro_flow_table_t;
      64             : 
      65             : static_always_inline void
      66     1221540 : gro_flow_set_flow_key (gro_flow_t * to, gro_flow_key_t * from)
      67             : {
      68     1221540 :   to->flow_key.flow_data[0] = from->flow_data[0];
      69     1221540 :   to->flow_key.flow_data[1] = from->flow_data[1];
      70     1221540 :   to->flow_key.flow_data[2] = from->flow_data[2];
      71     1221540 :   to->flow_key.flow_data[3] = from->flow_data[3];
      72     1221540 :   to->flow_key.flow_data[4] = from->flow_data[4];
      73     1221540 :   to->flow_key.flow_data_u32 = from->flow_data_u32;
      74     1221540 : }
      75             : 
      76             : static_always_inline u8
      77    43270758 : gro_flow_is_equal (gro_flow_key_t * first, gro_flow_key_t * second)
      78             : {
      79    43270758 :   if (first->flow_data[0] == second->flow_data[0] &&
      80    23422758 :       first->flow_data[1] == second->flow_data[1] &&
      81    23422758 :       first->flow_data[2] == second->flow_data[2] &&
      82    23422758 :       first->flow_data[3] == second->flow_data[3] &&
      83    23422758 :       first->flow_data[4] == second->flow_data[4] &&
      84    23422758 :       first->flow_data_u32 == second->flow_data_u32)
      85    23422758 :     return 1;
      86             : 
      87    19848000 :   return 0;
      88             : }
      89             : 
      90             : /**
      91             :  * timeout_expire is in between 3 to 10 microseconds
      92             :  * 3e-6 1e-5
      93             :  */
      94             : static_always_inline void
      95     1262523 : gro_flow_set_timeout (vlib_main_t * vm, gro_flow_t * gro_flow,
      96             :                       f64 timeout_expire)
      97             : {
      98     1262523 :   gro_flow->next_timeout_ts = vlib_time_now (vm) + timeout_expire;
      99     1262523 : }
     100             : 
     101             : static_always_inline u8
     102      175783 : gro_flow_is_timeout (vlib_main_t * vm, gro_flow_t * gro_flow)
     103             : {
     104      175783 :   if (gro_flow->next_timeout_ts < vlib_time_now (vm))
     105      175722 :     return 1;
     106          61 :   return 0;
     107             : }
     108             : 
     109             : static_always_inline void
     110    24573708 : gro_flow_store_packet (gro_flow_t * gro_flow, u32 bi0)
     111             : {
     112    24573708 :   if (gro_flow->n_buffers == 0)
     113             :     {
     114     1262523 :       gro_flow->buffer_index = bi0;
     115             :     }
     116    24573708 :   gro_flow->n_buffers++;
     117    24573708 : }
     118             : 
     119             : static_always_inline u32
     120         110 : gro_flow_table_init (gro_flow_table_t ** flow_table, u8 is_l2, u32 node_index)
     121             : {
     122         110 :   if (*flow_table)
     123           0 :     return 0;
     124             : 
     125         110 :   gro_flow_table_t *flow_table_temp = 0;
     126             :   flow_table_temp =
     127         110 :     (gro_flow_table_t *) clib_mem_alloc (sizeof (gro_flow_table_t));
     128         110 :   if (!flow_table_temp)
     129           0 :     return 0;
     130         110 :   clib_memset (flow_table_temp, 0, sizeof (gro_flow_table_t));
     131         110 :   flow_table_temp->node_index = node_index;
     132         110 :   flow_table_temp->is_enable = 1;
     133         110 :   flow_table_temp->is_l2 = is_l2;
     134         110 :   *flow_table = flow_table_temp;
     135         110 :   return 1;
     136             : }
     137             : 
     138             : static_always_inline void
     139    16167005 : gro_flow_table_set_timeout (vlib_main_t * vm, gro_flow_table_t * flow_table,
     140             :                             f64 timeout_expire)
     141             : {
     142    16167005 :   if (flow_table)
     143    16167005 :     flow_table->timeout_ts = vlib_time_now (vm) + timeout_expire;
     144    16167005 : }
     145             : 
     146             : static_always_inline u8
     147   170057005 : gro_flow_table_is_timeout (vlib_main_t * vm, gro_flow_table_t * flow_table)
     148             : {
     149   170057005 :   if (flow_table && (flow_table->timeout_ts < vlib_time_now (vm)))
     150    16167005 :     return 1;
     151   153890000 :   return 0;
     152             : }
     153             : 
     154             : static_always_inline u8
     155    27007415 : gro_flow_table_is_enable (gro_flow_table_t * flow_table)
     156             : {
     157    27007415 :   if (flow_table)
     158    27007415 :     return flow_table->is_enable;
     159             : 
     160           0 :   return 0;
     161             : }
     162             : 
     163             : static_always_inline void
     164             : gro_flow_table_set_is_enable (gro_flow_table_t * flow_table, u8 is_enable)
     165             : {
     166             :   if (flow_table)
     167             :     flow_table->is_enable = is_enable;
     168             : }
     169             : 
     170             : static_always_inline void
     171         372 : gro_flow_table_free (gro_flow_table_t * flow_table)
     172             : {
     173         372 :   if (flow_table)
     174         108 :     clib_mem_free (flow_table);
     175         372 : }
     176             : 
     177             : static_always_inline void
     178             : gro_flow_table_set_node_index (gro_flow_table_t * flow_table, u32 node_index)
     179             : {
     180             :   if (flow_table)
     181             :     flow_table->node_index = node_index;
     182             : }
     183             : 
     184             : static_always_inline gro_flow_t *
     185     1221540 : gro_flow_table_new_flow (gro_flow_table_t * flow_table)
     186             : {
     187     1221540 :   if (PREDICT_TRUE (flow_table->flow_table_size < GRO_FLOW_TABLE_MAX_SIZE))
     188             :     {
     189             :       gro_flow_t *gro_flow;
     190     1221540 :       u32 i = 0;
     191     1221540 :       while (i < GRO_FLOW_TABLE_MAX_SIZE)
     192             :         {
     193     1221540 :           gro_flow = &flow_table->gro_flow[i];
     194     1221540 :           if (gro_flow->n_buffers == 0)
     195             :             {
     196     1221540 :               flow_table->flow_table_size++;
     197     1221540 :               return gro_flow;
     198             :             }
     199           0 :           i++;
     200             :         }
     201             :     }
     202             : 
     203           0 :   return (0);
     204             : }
     205             : 
     206             : static_always_inline gro_flow_t *
     207    24663208 : gro_flow_table_get_flow (gro_flow_table_t * flow_table,
     208             :                          gro_flow_key_t * flow_key)
     209             : {
     210    24663208 :   gro_flow_t *gro_flow = 0;
     211    24663208 :   u32 i = 0;
     212    44511208 :   while (i < GRO_FLOW_TABLE_MAX_SIZE)
     213             :     {
     214    43270758 :       gro_flow = &flow_table->gro_flow[i];
     215    43270758 :       if (gro_flow_is_equal (flow_key, &gro_flow->flow_key))
     216    23422758 :         return gro_flow;
     217    19848000 :       i++;
     218             :     }
     219     1240500 :   return (0);
     220             : }
     221             : 
     222             : static_always_inline gro_flow_t *
     223    23598659 : gro_flow_table_find_or_add_flow (gro_flow_table_t * flow_table,
     224             :                                  gro_flow_key_t * flow_key)
     225             : {
     226    23598659 :   gro_flow_t *gro_flow = 0;
     227             : 
     228    23598659 :   gro_flow = gro_flow_table_get_flow (flow_table, flow_key);
     229    23598659 :   if (gro_flow)
     230    22377109 :     return gro_flow;
     231             : 
     232     1221540 :   gro_flow = gro_flow_table_new_flow (flow_table);
     233             : 
     234     1221540 :   if (gro_flow)
     235             :     {
     236     1221540 :       gro_flow_set_flow_key (gro_flow, flow_key);
     237     1221540 :       return gro_flow;
     238             :     }
     239             : 
     240           0 :   return (0);
     241             : }
     242             : 
     243             : static_always_inline void
     244     1221541 : gro_flow_table_reset_flow (gro_flow_table_t * flow_table,
     245             :                            gro_flow_t * gro_flow)
     246             : {
     247     1221541 :   if (PREDICT_TRUE (flow_table->flow_table_size > 0))
     248             :     {
     249     1221541 :       clib_memset (gro_flow, 0, sizeof (gro_flow_t));
     250     1221541 :       flow_table->flow_table_size--;
     251             :     }
     252     1221541 : }
     253             : 
     254             : static_always_inline u8 *
     255           0 : gro_flow_table_format (u8 * s, va_list * args)
     256             : {
     257           0 :   gro_flow_table_t *flow_table = va_arg (*args, gro_flow_table_t *);
     258             :   u32 indent;
     259             : 
     260           0 :   if (!flow_table)
     261           0 :     return s;
     262             : 
     263           0 :   indent = format_get_indent (s);
     264           0 :   if (flow_table->is_enable)
     265           0 :     s = format (s, "packet-coalesce: enable\n");
     266             :   else
     267           0 :     s = format (s, "packet-coalesce: disable\n");
     268             : 
     269           0 :   indent += 2;
     270             : 
     271             :   s =
     272           0 :     format (s,
     273             :             "%Uflow-table: size %u gro-total-vectors %lu gro-n-vectors %u",
     274           0 :             format_white_space, indent, flow_table->flow_table_size,
     275             :             flow_table->total_vectors, flow_table->n_vectors);
     276           0 :   if (flow_table->n_vectors)
     277             :     {
     278           0 :       double average_rate =
     279           0 :         (double) flow_table->total_vectors / (double) flow_table->n_vectors;
     280           0 :       s = format (s, " gro-average-rate %.2f", average_rate);
     281             :     }
     282             :   else
     283           0 :     s = format (s, " gro-average-rate 0.00");
     284             : 
     285           0 :   return s;
     286             : }
     287             : #endif /* included_gro_h */
     288             : 
     289             : /*
     290             :  * fd.io coding-style-patch-verification: ON
     291             :  *
     292             :  * Local Variables:
     293             :  * eval: (c-set-style "gnu")
     294             :  * End:
     295             :  */

Generated by: LCOV version 1.14