blob: a6616d9ced7e2198b54489cf1abb97b45d1c0c69 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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>
Calvin71e97c62016-08-19 16:23:14 -040045#include <vppinfra/fifo.h> /* for buffer_fifo */
Dave Barach3ae28732018-11-16 17:19:00 -050046#include <vppinfra/pcap.h>
Damjan Marion3d9c86e2016-07-04 21:04:40 +020047#include <vnet/interface.h>
48
49extern vnet_device_class_t pg_dev_class;
Ed Warnickecb9cada2015-12-08 15:45:58 -070050
51struct pg_main_t;
52struct pg_stream_t;
53
Calvin71e97c62016-08-19 16:23:14 -040054typedef struct pg_edit_group_t
55{
Ed Warnickecb9cada2015-12-08 15:45:58 -070056 /* Edits in this group. */
Calvin71e97c62016-08-19 16:23:14 -040057 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
59 /* Vector of non-fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040060 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070061
62 /* Fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040063 u8 *fixed_packet_data;
64 u8 *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -070065
66 /* Byte offset where packet data begins. */
67 u32 start_byte_offset;
68
69 /* Number of packet bytes for this edit group. */
70 u32 n_packet_bytes;
71
72 /* Function to perform miscellaneous edits (e.g. set IP checksum, ...). */
Calvin71e97c62016-08-19 16:23:14 -040073 void (*edit_function) (struct pg_main_t * pg,
74 struct pg_stream_t * s,
75 struct pg_edit_group_t * g,
76 u32 * buffers, u32 n_buffers);
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
78 /* Opaque data for edit function's use. */
79 uword edit_function_opaque;
80} pg_edit_group_t;
81
82/* Packets are made of multiple buffers chained together.
83 This struct keeps track of data per-chain index. */
Calvin71e97c62016-08-19 16:23:14 -040084typedef struct
85{
Ed Warnickecb9cada2015-12-08 15:45:58 -070086 /* Vector of buffer edits for this stream and buffer index. */
Calvin71e97c62016-08-19 16:23:14 -040087 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070088
89 /* Buffers pre-initialized with fixed buffer data for this stream. */
Calvin71e97c62016-08-19 16:23:14 -040090 u32 *buffer_fifo;
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
Ed Warnickecb9cada2015-12-08 15:45:58 -070092} pg_buffer_index_t;
93
Calvin71e97c62016-08-19 16:23:14 -040094typedef struct pg_stream_t
95{
Ed Warnickecb9cada2015-12-08 15:45:58 -070096 /* Stream name. */
Calvin71e97c62016-08-19 16:23:14 -040097 u8 *name;
Ed Warnickecb9cada2015-12-08 15:45:58 -070098
99 u32 flags;
100
101 /* Stream is currently enabled. */
102#define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
104 /* Edit groups are created by each protocol level (e.g. ethernet,
105 ip4, tcp, ...). */
Calvin71e97c62016-08-19 16:23:14 -0400106 pg_edit_group_t *edit_groups;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107
108 pg_edit_type_t packet_size_edit_type;
109
110 /* Min/max packet size. */
111 u32 min_packet_bytes, max_packet_bytes;
112
113 /* Vector of non-fixed edits for this stream.
114 All fixed edits are performed and placed into fixed_packet_data. */
Calvin71e97c62016-08-19 16:23:14 -0400115 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116
117 /* Packet data with all fixed edits performed.
118 All packets in stream are initialized according with this data.
119 Mask specifies which bits of packet data are covered by fixed edits. */
Calvin71e97c62016-08-19 16:23:14 -0400120 u8 *fixed_packet_data, *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121
122 /* Size to use for buffers. 0 means use buffers big enough
123 for max_packet_bytes. */
124 u32 buffer_bytes;
125
Dave Barach08eb2bb2020-04-15 09:34:43 -0400126 /* Buffer flags to set in each packet e.g. checksum offload flags */
127 u32 buffer_flags;
128
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129 /* Last packet length if packet size edit type is increment. */
130 u32 last_increment_packet_size;
131
132 /* Index into main interface pool for this stream. */
133 u32 pg_if_index;
134
135 /* Interface used to mark packets for this stream. May be different
136 than hw/sw index from pg main interface pool. They will be
137 different if this stream is being used generate buffers as if
138 they were received on a non-pg interface. For example, suppose you
139 are trying to test vlan code and you want to generate buffers that
140 appear to come from an ethernet interface. */
141 u32 sw_if_index[VLIB_N_RX_TX];
142
143 /* Node where stream's buffers get put. */
144 u32 node_index;
145
Damjan Marion64034362016-11-07 22:19:55 +0100146 /* Worker thread index */
147 u32 worker_index;
148
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149 /* Output next index to reach output node from stream input node. */
150 u32 next_index;
151
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200152 u32 if_id;
153
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 /* Number of packets currently generated. */
155 u64 n_packets_generated;
156
157 /* Stream is disabled when packet limit is reached.
158 Zero means no packet limit. */
159 u64 n_packets_limit;
160
Christian E. Hopps87d7bac2019-09-27 12:59:30 -0400161 /* Only generate up to n_max_frame per frame. */
162 u32 n_max_frame;
163
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164 /* Rate for this stream in packets/second.
165 Zero means unlimited rate. */
166 f64 rate_packets_per_second;
167
168 f64 time_last_generate;
169
170 f64 packet_accumulator;
171
Calvin71e97c62016-08-19 16:23:14 -0400172 pg_buffer_index_t *buffer_indices;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173
Calvin71e97c62016-08-19 16:23:14 -0400174 u8 **replay_packet_templates;
Dave Barach78c56892018-05-16 11:34:35 -0400175 u64 *replay_packet_timestamps;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176 u32 current_replay_packet_index;
177} pg_stream_t;
178
179always_inline void
180pg_buffer_index_free (pg_buffer_index_t * bi)
181{
182 vec_free (bi->edits);
183 clib_fifo_free (bi->buffer_fifo);
184}
185
186always_inline void
187pg_edit_group_free (pg_edit_group_t * g)
188{
Calvin71e97c62016-08-19 16:23:14 -0400189 pg_edit_t *e;
190 vec_foreach (e, g->edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700191 vec_free (g->edits);
192 vec_free (g->fixed_packet_data);
193 vec_free (g->fixed_packet_data_mask);
194}
195
196always_inline void
197pg_stream_free (pg_stream_t * s)
198{
Dave Barach78c56892018-05-16 11:34:35 -0400199 int i;
Calvin71e97c62016-08-19 16:23:14 -0400200 pg_edit_group_t *g;
201 pg_edit_t *e;
202 vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700203 vec_free (s->non_fixed_edits);
Calvin71e97c62016-08-19 16:23:14 -0400204 vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205 vec_free (s->edit_groups);
206 vec_free (s->fixed_packet_data);
207 vec_free (s->fixed_packet_data_mask);
208 vec_free (s->name);
Dave Barach78c56892018-05-16 11:34:35 -0400209 for (i = 0; i < vec_len (s->replay_packet_templates); i++)
210 vec_free (s->replay_packet_templates[i]);
211 vec_free (s->replay_packet_templates);
212 vec_free (s->replay_packet_timestamps);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
214 {
Calvin71e97c62016-08-19 16:23:14 -0400215 pg_buffer_index_t *bi;
216 vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217 vec_free (s->buffer_indices);
218 }
219}
220
221always_inline int
222pg_stream_is_enabled (pg_stream_t * s)
Calvin71e97c62016-08-19 16:23:14 -0400223{
224 return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
225}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700226
227always_inline pg_edit_group_t *
228pg_stream_get_group (pg_stream_t * s, u32 group_index)
Calvin71e97c62016-08-19 16:23:14 -0400229{
230 return vec_elt_at_index (s->edit_groups, group_index);
231}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232
233always_inline void *
234pg_create_edit_group (pg_stream_t * s,
Calvin71e97c62016-08-19 16:23:14 -0400235 int n_edit_bytes, int n_packet_bytes, u32 * group_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236{
Calvin71e97c62016-08-19 16:23:14 -0400237 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700238 int n_edits;
239
240 vec_add2 (s->edit_groups, g, 1);
241 if (group_index)
242 *group_index = g - s->edit_groups;
243
244 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
245 n_edits = n_edit_bytes / sizeof (pg_edit_t);
246 vec_resize (g->edits, n_edits);
247
248 g->n_packet_bytes = n_packet_bytes;
249
250 return g->edits;
251}
252
253always_inline void *
254pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
255 u32 group_index)
256{
Calvin71e97c62016-08-19 16:23:14 -0400257 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
258 pg_edit_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259 int n_edits;
260 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
261 n_edits = n_edit_bytes / sizeof (pg_edit_t);
262 vec_add2 (g->edits, e, n_edits);
263 g->n_packet_bytes += n_packet_bytes;
264 return e;
265}
266
267always_inline void *
268pg_get_edit_group (pg_stream_t * s, u32 group_index)
269{
Calvin71e97c62016-08-19 16:23:14 -0400270 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271 return g->edits;
272}
273
274/* Number of bytes for all groups >= given group. */
275always_inline uword
276pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
277{
Calvin71e97c62016-08-19 16:23:14 -0400278 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700279 uword n_bytes = 0;
280
281 for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
282 n_bytes += g->n_packet_bytes;
283 return n_bytes;
284}
285
286always_inline void
287pg_free_edit_group (pg_stream_t * s)
288{
289 uword i = vec_len (s->edit_groups) - 1;
Calvin71e97c62016-08-19 16:23:14 -0400290 pg_edit_group_t *g = pg_stream_get_group (s, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291
292 pg_edit_group_free (g);
Dave Barachb7b92992018-10-17 10:38:51 -0400293 clib_memset (g, 0, sizeof (g[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700294 _vec_len (s->edit_groups) = i;
295}
296
Calvin71e97c62016-08-19 16:23:14 -0400297typedef struct
298{
Damjan Marion64034362016-11-07 22:19:55 +0100299 /* TX lock */
300 volatile u32 *lockp;
301
Ed Warnickecb9cada2015-12-08 15:45:58 -0700302 /* VLIB interface indices. */
303 u32 hw_if_index, sw_if_index;
304
305 /* Identifies stream for this interface. */
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200306 u32 id;
307
Mohsin Kazmi22e9cfd2019-07-23 11:54:48 +0200308 u8 gso_enabled;
309 u32 gso_size;
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200310 pcap_main_t pcap_main;
Jakub Grajciardb863292020-01-30 14:14:15 +0100311 char *pcap_file_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700312} pg_interface_t;
313
314/* Per VLIB node data. */
Calvin71e97c62016-08-19 16:23:14 -0400315typedef struct
316{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317 /* Parser function indexed by node index. */
Calvin71e97c62016-08-19 16:23:14 -0400318 unformat_function_t *unformat_edit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700319} pg_node_t;
320
Calvin71e97c62016-08-19 16:23:14 -0400321typedef struct pg_main_t
322{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700323 /* Pool of streams. */
Calvin71e97c62016-08-19 16:23:14 -0400324 pg_stream_t *streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700325
326 /* Bitmap indicating which streams are currently enabled. */
Damjan Marion3a4ed392016-11-08 13:20:42 +0100327 uword **enabled_streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700328
329 /* Hash mapping name -> stream index. */
Calvin71e97c62016-08-19 16:23:14 -0400330 uword *stream_index_by_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200332 /* Pool of interfaces. */
Calvin71e97c62016-08-19 16:23:14 -0400333 pg_interface_t *interfaces;
334 uword *if_index_by_if_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335
Dave Barach3c8e1462019-01-05 16:51:41 -0500336 /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
337 u32 **replay_buffers_by_thread;
338
Ed Warnickecb9cada2015-12-08 15:45:58 -0700339 /* Per VLIB node information. */
Calvin71e97c62016-08-19 16:23:14 -0400340 pg_node_t *nodes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341} pg_main_t;
342
343/* Global main structure. */
344extern pg_main_t pg_main;
345
346/* Global node. */
347extern vlib_node_registration_t pg_input_node;
348
349/* Buffer generator input, output node functions. */
350vlib_node_function_t pg_input, pg_output;
351
352/* Stream add/delete. */
353void pg_stream_del (pg_main_t * pg, uword index);
354void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
Kingwel Xie42223472019-01-19 22:49:26 -0500355void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700356
357/* Enable/disable stream. */
Calvin71e97c62016-08-19 16:23:14 -0400358void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
359 int is_enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360
361/* Find/create free packet-generator interface index. */
Mohsin Kazmi22e9cfd2019-07-23 11:54:48 +0200362u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index,
363 u8 gso_enabled, u32 gso_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700364
365always_inline pg_node_t *
366pg_get_node (uword node_index)
367{
Calvin71e97c62016-08-19 16:23:14 -0400368 pg_main_t *pg = &pg_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700369 vec_validate (pg->nodes, node_index);
370 return pg->nodes + node_index;
371}
372
373void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
374 u32 group_index,
Calvin71e97c62016-08-19 16:23:14 -0400375 void *fixed_packet_data,
376 void *fixed_packet_data_mask);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200378void pg_enable_disable (u32 stream_index, int is_enable);
379
Calvin71e97c62016-08-19 16:23:14 -0400380typedef struct
381{
382 u32 hw_if_index;
383 u32 dev_instance;
384 u8 is_enabled;
Jakub Grajciardb863292020-01-30 14:14:15 +0100385 char *pcap_file_name;
Calvin71e97c62016-08-19 16:23:14 -0400386 u32 count;
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200387} pg_capture_args_t;
388
Calvin71e97c62016-08-19 16:23:14 -0400389clib_error_t *pg_capture (pg_capture_args_t * a);
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200390
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100391typedef struct
392{
393 vlib_buffer_t buffer;
394 u32 buffer_index;
395}
396pg_output_trace_t;
397
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398#endif /* included_vlib_pg_h */
Calvin71e97c62016-08-19 16:23:14 -0400399
400/*
401 * fd.io coding-style-patch-verification: ON
402 *
403 * Local Variables:
404 * eval: (c-set-style "gnu")
405 * End:
406 */