LCOV - code coverage report
Current view: top level - vnet/pg - pg.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 57 64 89.1 %
Date: 2023-07-05 22:20:52 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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             :  * pg.h: VLIB packet generator
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #ifndef included_vlib_pg_h
      41             : #define included_vlib_pg_h
      42             : 
      43             : #include <vlib/vlib.h>            /* for VLIB_N_RX_TX */
      44             : #include <vnet/pg/edit.h>
      45             : #include <vppinfra/fifo.h>        /* for buffer_fifo */
      46             : #include <vppinfra/pcap.h>
      47             : #include <vnet/interface.h>
      48             : #include <vnet/ethernet/mac_address.h>
      49             : #include <vnet/gso/gro.h>
      50             : 
      51             : extern vnet_device_class_t pg_dev_class;
      52             : 
      53             : struct pg_main_t;
      54             : struct pg_stream_t;
      55             : 
      56             : typedef struct pg_edit_group_t
      57             : {
      58             :   /* Edits in this group. */
      59             :   pg_edit_t *edits;
      60             : 
      61             :   /* Vector of non-fixed edits for this group. */
      62             :   pg_edit_t *non_fixed_edits;
      63             : 
      64             :   /* Fixed edits for this group. */
      65             :   u8 *fixed_packet_data;
      66             :   u8 *fixed_packet_data_mask;
      67             : 
      68             :   /* Byte offset where packet data begins. */
      69             :   u32 start_byte_offset;
      70             : 
      71             :   /* Number of packet bytes for this edit group. */
      72             :   u32 n_packet_bytes;
      73             : 
      74             :   /* Function to perform miscellaneous edits (e.g. set IP checksum, ...). */
      75             :   void (*edit_function) (struct pg_main_t * pg,
      76             :                          struct pg_stream_t * s,
      77             :                          struct pg_edit_group_t * g,
      78             :                          u32 * buffers, u32 n_buffers);
      79             : 
      80             :   /* Opaque data for edit function's use. */
      81             :   uword edit_function_opaque;
      82             : } pg_edit_group_t;
      83             : 
      84             : /* Packets are made of multiple buffers chained together.
      85             :    This struct keeps track of data per-chain index. */
      86             : typedef struct
      87             : {
      88             :   /* Vector of buffer edits for this stream and buffer index. */
      89             :   pg_edit_t *edits;
      90             : 
      91             :   /* Buffers pre-initialized with fixed buffer data for this stream. */
      92             :   u32 *buffer_fifo;
      93             : 
      94             : } pg_buffer_index_t;
      95             : 
      96             : typedef struct pg_stream_t
      97             : {
      98             :   /* Stream name. */
      99             :   u8 *name;
     100             : 
     101             :   u32 flags;
     102             : 
     103             :   /* Stream is currently enabled. */
     104             : #define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
     105             : 
     106             :   /* Edit groups are created by each protocol level (e.g. ethernet,
     107             :      ip4, tcp, ...). */
     108             :   pg_edit_group_t *edit_groups;
     109             : 
     110             :   pg_edit_type_t packet_size_edit_type;
     111             : 
     112             :   /* Min/max packet size. */
     113             :   u32 min_packet_bytes, max_packet_bytes;
     114             : 
     115             :   /* Vector of non-fixed edits for this stream.
     116             :      All fixed edits are performed and placed into fixed_packet_data. */
     117             :   pg_edit_t *non_fixed_edits;
     118             : 
     119             :   /* Packet data with all fixed edits performed.
     120             :      All packets in stream are initialized according with this data.
     121             :      Mask specifies which bits of packet data are covered by fixed edits. */
     122             :   u8 *fixed_packet_data, *fixed_packet_data_mask;
     123             : 
     124             :   /* Size to use for buffers.  0 means use buffers big enough
     125             :      for max_packet_bytes. */
     126             :   u32 buffer_bytes;
     127             : 
     128             :   /* Buffer flags to set in each packet e.g. l2 valid  flags */
     129             :   u32 buffer_flags;
     130             : 
     131             :   /* Buffer offload flags to set in each packet e.g. checksum offload flags */
     132             :   u32 buffer_oflags;
     133             : 
     134             :   /* Last packet length if packet size edit type is increment. */
     135             :   u32 last_increment_packet_size;
     136             : 
     137             :   /* Index into main interface pool for this stream. */
     138             :   u32 pg_if_index;
     139             : 
     140             :   /* Interface used to mark packets for this stream.  May be different
     141             :      than hw/sw index from pg main interface pool.  They will be
     142             :      different if this stream is being used generate buffers as if
     143             :      they were received on a non-pg interface.  For example, suppose you
     144             :      are trying to test vlan code and you want to generate buffers that
     145             :      appear to come from an ethernet interface. */
     146             :   u32 sw_if_index[VLIB_N_RX_TX];
     147             : 
     148             :   /* Node where stream's buffers get put. */
     149             :   u32 node_index;
     150             : 
     151             :   /* Worker thread index */
     152             :   u32 worker_index;
     153             : 
     154             :   /* Output next index to reach output node from stream input node. */
     155             :   u32 next_index;
     156             : 
     157             :   u32 if_id;
     158             : 
     159             :   /* Number of packets currently generated. */
     160             :   u64 n_packets_generated;
     161             : 
     162             :   /* Stream is disabled when packet limit is reached.
     163             :      Zero means no packet limit. */
     164             :   u64 n_packets_limit;
     165             : 
     166             :   /* Only generate up to n_max_frame per frame. */
     167             :   u32 n_max_frame;
     168             : 
     169             :   /* Rate for this stream in packets/second.
     170             :      Zero means unlimited rate. */
     171             :   f64 rate_packets_per_second;
     172             : 
     173             :   f64 time_last_generate;
     174             : 
     175             :   f64 packet_accumulator;
     176             : 
     177             :   pg_buffer_index_t *buffer_indices;
     178             : 
     179             :   u8 **replay_packet_templates;
     180             :   u64 *replay_packet_timestamps;
     181             :   u32 current_replay_packet_index;
     182             : } pg_stream_t;
     183             : 
     184             : always_inline void
     185       18660 : pg_buffer_index_free (pg_buffer_index_t * bi)
     186             : {
     187       18660 :   vec_free (bi->edits);
     188       18660 :   clib_fifo_free (bi->buffer_fifo);
     189       18660 : }
     190             : 
     191             : always_inline void
     192           1 : pg_edit_group_free (pg_edit_group_t * g)
     193             : {
     194             :   pg_edit_t *e;
     195           4 :   vec_foreach (e, g->edits) pg_edit_free (e);
     196           1 :   vec_free (g->edits);
     197           1 :   vec_free (g->fixed_packet_data);
     198           1 :   vec_free (g->fixed_packet_data_mask);
     199           1 : }
     200             : 
     201             : always_inline void
     202       15047 : pg_stream_free (pg_stream_t * s)
     203             : {
     204             :   int i;
     205             :   pg_edit_group_t *g;
     206             :   pg_edit_t *e;
     207       15047 :   vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
     208       15047 :   vec_free (s->non_fixed_edits);
     209       15047 :   vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
     210       15047 :   vec_free (s->edit_groups);
     211       15047 :   vec_free (s->fixed_packet_data);
     212       15047 :   vec_free (s->fixed_packet_data_mask);
     213       15047 :   vec_free (s->name);
     214      543597 :   for (i = 0; i < vec_len (s->replay_packet_templates); i++)
     215      528550 :     vec_free (s->replay_packet_templates[i]);
     216       15047 :   vec_free (s->replay_packet_templates);
     217       15047 :   vec_free (s->replay_packet_timestamps);
     218             : 
     219             :   {
     220             :     pg_buffer_index_t *bi;
     221       33707 :     vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
     222       15047 :     vec_free (s->buffer_indices);
     223             :   }
     224       15047 : }
     225             : 
     226             : always_inline int
     227       60309 : pg_stream_is_enabled (pg_stream_t * s)
     228             : {
     229       60309 :   return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
     230             : }
     231             : 
     232             : always_inline pg_edit_group_t *
     233          25 : pg_stream_get_group (pg_stream_t * s, u32 group_index)
     234             : {
     235          25 :   return vec_elt_at_index (s->edit_groups, group_index);
     236             : }
     237             : 
     238             : always_inline void *
     239          24 : pg_create_edit_group (pg_stream_t * s,
     240             :                       int n_edit_bytes, int n_packet_bytes, u32 * group_index)
     241             : {
     242             :   pg_edit_group_t *g;
     243             :   int n_edits;
     244             : 
     245          24 :   vec_add2 (s->edit_groups, g, 1);
     246          24 :   if (group_index)
     247          18 :     *group_index = g - s->edit_groups;
     248             : 
     249          24 :   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
     250          24 :   n_edits = n_edit_bytes / sizeof (pg_edit_t);
     251          24 :   vec_resize (g->edits, n_edits);
     252             : 
     253          24 :   g->n_packet_bytes = n_packet_bytes;
     254             : 
     255          24 :   return g->edits;
     256             : }
     257             : 
     258             : always_inline void *
     259           0 : pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
     260             :               u32 group_index)
     261             : {
     262           0 :   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
     263             :   pg_edit_t *e;
     264             :   int n_edits;
     265           0 :   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
     266           0 :   n_edits = n_edit_bytes / sizeof (pg_edit_t);
     267           0 :   vec_add2 (g->edits, e, n_edits);
     268           0 :   g->n_packet_bytes += n_packet_bytes;
     269           0 :   return e;
     270             : }
     271             : 
     272             : always_inline void *
     273          17 : pg_get_edit_group (pg_stream_t * s, u32 group_index)
     274             : {
     275          17 :   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
     276          17 :   return g->edits;
     277             : }
     278             : 
     279             : /* Number of bytes for all groups >= given group. */
     280             : always_inline uword
     281       15065 : pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
     282             : {
     283             :   pg_edit_group_t *g;
     284       15065 :   uword n_bytes = 0;
     285             : 
     286       15122 :   for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
     287          57 :     n_bytes += g->n_packet_bytes;
     288       15065 :   return n_bytes;
     289             : }
     290             : 
     291             : always_inline void
     292           1 : pg_free_edit_group (pg_stream_t * s)
     293             : {
     294           1 :   uword i = vec_len (s->edit_groups) - 1;
     295           1 :   pg_edit_group_t *g = pg_stream_get_group (s, i);
     296             : 
     297           1 :   pg_edit_group_free (g);
     298           1 :   clib_memset (g, 0, sizeof (g[0]));
     299           1 :   vec_set_len (s->edit_groups, i);
     300           1 : }
     301             : 
     302             : typedef enum pg_interface_mode_t_
     303             : {
     304             :   PG_MODE_ETHERNET,
     305             :   PG_MODE_IP4,
     306             :   PG_MODE_IP6,
     307             : } pg_interface_mode_t;
     308             : 
     309             : typedef struct
     310             : {
     311             :   /* TX lock */
     312             :   volatile u32 *lockp;
     313             : 
     314             :   /* VLIB interface indices. */
     315             :   u32 hw_if_index, sw_if_index;
     316             : 
     317             :   /* Identifies stream for this interface. */
     318             :   u32 id;
     319             : 
     320             :   u8 coalesce_enabled;
     321             :   gro_flow_table_t *flow_table;
     322             :   u8 gso_enabled;
     323             :   u32 gso_size;
     324             :   pcap_main_t pcap_main;
     325             :   char *pcap_file_name;
     326             :   pg_interface_mode_t mode;
     327             : 
     328             :   mac_address_t *allowed_mcast_macs;
     329             : } pg_interface_t;
     330             : 
     331             : /* Per VLIB node data. */
     332             : typedef struct
     333             : {
     334             :   /* Parser function indexed by node index. */
     335             :   unformat_function_t *unformat_edit;
     336             : } pg_node_t;
     337             : 
     338             : typedef struct pg_main_t
     339             : {
     340             :   /* Pool of streams. */
     341             :   pg_stream_t *streams;
     342             : 
     343             :   /* Bitmap indicating which streams are currently enabled. */
     344             :   uword **enabled_streams;
     345             : 
     346             :   /* Hash mapping name -> stream index. */
     347             :   uword *stream_index_by_name;
     348             : 
     349             :   /* Pool of interfaces. */
     350             :   pg_interface_t *interfaces;
     351             :   uword *if_index_by_if_id;
     352             :   uword *if_id_by_sw_if_index;
     353             : 
     354             :   /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
     355             :   u32 **replay_buffers_by_thread;
     356             : 
     357             :   /* Per VLIB node information. */
     358             :   pg_node_t *nodes;
     359             : 
     360             :   u16 msg_id_base;
     361             : } pg_main_t;
     362             : 
     363             : /* Global main structure. */
     364             : extern pg_main_t pg_main;
     365             : 
     366             : /* Global node. */
     367             : extern vlib_node_registration_t pg_input_node;
     368             : 
     369             : /* Buffer generator input, output node functions. */
     370             : vlib_node_function_t pg_input, pg_output;
     371             : 
     372             : /* Stream add/delete. */
     373             : void pg_stream_del (pg_main_t * pg, uword index);
     374             : void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
     375             : void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
     376             : 
     377             : /* Enable/disable stream. */
     378             : void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
     379             :                                int is_enable);
     380             : 
     381             : /* Enable/disable packet coalesce on given interface */
     382             : void pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
     383             :                                            u32 tx_node_index);
     384             : 
     385             : /* Find/create free packet-generator interface index. */
     386             : u32 pg_interface_add_or_get (pg_main_t *pg, uword stream_index, u8 gso_enabled,
     387             :                              u32 gso_size, u8 coalesce_enabled,
     388             :                              pg_interface_mode_t mode);
     389             : 
     390             : always_inline pg_node_t *
     391       17422 : pg_get_node (uword node_index)
     392             : {
     393       17422 :   pg_main_t *pg = &pg_main;
     394       17422 :   vec_validate (pg->nodes, node_index);
     395       17422 :   return pg->nodes + node_index;
     396             : }
     397             : 
     398             : void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
     399             :                                           u32 group_index,
     400             :                                           void *fixed_packet_data,
     401             :                                           void *fixed_packet_data_mask);
     402             : 
     403             : void pg_enable_disable (u32 stream_index, int is_enable);
     404             : 
     405             : typedef struct
     406             : {
     407             :   u32 hw_if_index;
     408             :   u32 dev_instance;
     409             :   u8 is_enabled;
     410             :   char *pcap_file_name;
     411             :   u32 count;
     412             : } pg_capture_args_t;
     413             : 
     414             : clib_error_t *pg_capture (pg_capture_args_t * a);
     415             : 
     416             : typedef struct
     417             : {
     418             :   u32 buffer_index;
     419             :   vlib_buffer_t buffer;
     420             : }
     421             : pg_output_trace_t;
     422             : 
     423             : #endif /* included_vlib_pg_h */
     424             : 
     425             : /*
     426             :  * fd.io coding-style-patch-verification: ON
     427             :  *
     428             :  * Local Variables:
     429             :  * eval: (c-set-style "gnu")
     430             :  * End:
     431             :  */

Generated by: LCOV version 1.14