blob: 963d23a8e01002dc5f867fcc3ce98a8eff4d40c1 [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>
Neale Ranns21fb4f72020-10-05 12:26:47 +000048#include <vnet/ethernet/mac_address.h>
Mohsin Kazmif382b062020-08-11 15:00:44 +020049#include <vnet/gso/gro.h>
Damjan Marion3d9c86e2016-07-04 21:04:40 +020050
51extern vnet_device_class_t pg_dev_class;
Ed Warnickecb9cada2015-12-08 15:45:58 -070052
53struct pg_main_t;
54struct pg_stream_t;
55
Calvin71e97c62016-08-19 16:23:14 -040056typedef struct pg_edit_group_t
57{
Ed Warnickecb9cada2015-12-08 15:45:58 -070058 /* Edits in this group. */
Calvin71e97c62016-08-19 16:23:14 -040059 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070060
61 /* Vector of non-fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040062 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070063
64 /* Fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040065 u8 *fixed_packet_data;
66 u8 *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -070067
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, ...). */
Calvin71e97c62016-08-19 16:23:14 -040075 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);
Ed Warnickecb9cada2015-12-08 15:45:58 -070079
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. */
Calvin71e97c62016-08-19 16:23:14 -040086typedef struct
87{
Ed Warnickecb9cada2015-12-08 15:45:58 -070088 /* Vector of buffer edits for this stream and buffer index. */
Calvin71e97c62016-08-19 16:23:14 -040089 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070090
91 /* Buffers pre-initialized with fixed buffer data for this stream. */
Calvin71e97c62016-08-19 16:23:14 -040092 u32 *buffer_fifo;
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
Ed Warnickecb9cada2015-12-08 15:45:58 -070094} pg_buffer_index_t;
95
Calvin71e97c62016-08-19 16:23:14 -040096typedef struct pg_stream_t
97{
Ed Warnickecb9cada2015-12-08 15:45:58 -070098 /* Stream name. */
Calvin71e97c62016-08-19 16:23:14 -040099 u8 *name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100
101 u32 flags;
102
103 /* Stream is currently enabled. */
104#define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105
106 /* Edit groups are created by each protocol level (e.g. ethernet,
107 ip4, tcp, ...). */
Calvin71e97c62016-08-19 16:23:14 -0400108 pg_edit_group_t *edit_groups;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109
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. */
Calvin71e97c62016-08-19 16:23:14 -0400117 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118
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. */
Calvin71e97c62016-08-19 16:23:14 -0400122 u8 *fixed_packet_data, *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123
124 /* Size to use for buffers. 0 means use buffers big enough
125 for max_packet_bytes. */
126 u32 buffer_bytes;
127
Mohsin Kazmi68095382021-02-10 11:26:24 +0100128 /* Buffer flags to set in each packet e.g. l2 valid flags */
Dave Barach08eb2bb2020-04-15 09:34:43 -0400129 u32 buffer_flags;
130
Mohsin Kazmi68095382021-02-10 11:26:24 +0100131 /* Buffer offload flags to set in each packet e.g. checksum offload flags */
132 u32 buffer_oflags;
133
Ed Warnickecb9cada2015-12-08 15:45:58 -0700134 /* 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
Damjan Marion64034362016-11-07 22:19:55 +0100151 /* Worker thread index */
152 u32 worker_index;
153
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 /* Output next index to reach output node from stream input node. */
155 u32 next_index;
156
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200157 u32 if_id;
158
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159 /* 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
Christian E. Hopps87d7bac2019-09-27 12:59:30 -0400166 /* Only generate up to n_max_frame per frame. */
167 u32 n_max_frame;
168
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169 /* 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
Calvin71e97c62016-08-19 16:23:14 -0400177 pg_buffer_index_t *buffer_indices;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178
Calvin71e97c62016-08-19 16:23:14 -0400179 u8 **replay_packet_templates;
Dave Barach78c56892018-05-16 11:34:35 -0400180 u64 *replay_packet_timestamps;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181 u32 current_replay_packet_index;
182} pg_stream_t;
183
184always_inline void
185pg_buffer_index_free (pg_buffer_index_t * bi)
186{
187 vec_free (bi->edits);
188 clib_fifo_free (bi->buffer_fifo);
189}
190
191always_inline void
192pg_edit_group_free (pg_edit_group_t * g)
193{
Calvin71e97c62016-08-19 16:23:14 -0400194 pg_edit_t *e;
195 vec_foreach (e, g->edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 vec_free (g->edits);
197 vec_free (g->fixed_packet_data);
198 vec_free (g->fixed_packet_data_mask);
199}
200
201always_inline void
202pg_stream_free (pg_stream_t * s)
203{
Dave Barach78c56892018-05-16 11:34:35 -0400204 int i;
Calvin71e97c62016-08-19 16:23:14 -0400205 pg_edit_group_t *g;
206 pg_edit_t *e;
207 vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208 vec_free (s->non_fixed_edits);
Calvin71e97c62016-08-19 16:23:14 -0400209 vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210 vec_free (s->edit_groups);
211 vec_free (s->fixed_packet_data);
212 vec_free (s->fixed_packet_data_mask);
213 vec_free (s->name);
Dave Barach78c56892018-05-16 11:34:35 -0400214 for (i = 0; i < vec_len (s->replay_packet_templates); i++)
215 vec_free (s->replay_packet_templates[i]);
216 vec_free (s->replay_packet_templates);
217 vec_free (s->replay_packet_timestamps);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700218
219 {
Calvin71e97c62016-08-19 16:23:14 -0400220 pg_buffer_index_t *bi;
221 vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222 vec_free (s->buffer_indices);
223 }
224}
225
226always_inline int
227pg_stream_is_enabled (pg_stream_t * s)
Calvin71e97c62016-08-19 16:23:14 -0400228{
229 return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
230}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231
232always_inline pg_edit_group_t *
233pg_stream_get_group (pg_stream_t * s, u32 group_index)
Calvin71e97c62016-08-19 16:23:14 -0400234{
235 return vec_elt_at_index (s->edit_groups, group_index);
236}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237
238always_inline void *
239pg_create_edit_group (pg_stream_t * s,
Calvin71e97c62016-08-19 16:23:14 -0400240 int n_edit_bytes, int n_packet_bytes, u32 * group_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241{
Calvin71e97c62016-08-19 16:23:14 -0400242 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243 int n_edits;
244
245 vec_add2 (s->edit_groups, g, 1);
246 if (group_index)
247 *group_index = g - s->edit_groups;
248
249 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
250 n_edits = n_edit_bytes / sizeof (pg_edit_t);
251 vec_resize (g->edits, n_edits);
252
253 g->n_packet_bytes = n_packet_bytes;
254
255 return g->edits;
256}
257
258always_inline void *
259pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
260 u32 group_index)
261{
Calvin71e97c62016-08-19 16:23:14 -0400262 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
263 pg_edit_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264 int n_edits;
265 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
266 n_edits = n_edit_bytes / sizeof (pg_edit_t);
267 vec_add2 (g->edits, e, n_edits);
268 g->n_packet_bytes += n_packet_bytes;
269 return e;
270}
271
272always_inline void *
273pg_get_edit_group (pg_stream_t * s, u32 group_index)
274{
Calvin71e97c62016-08-19 16:23:14 -0400275 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700276 return g->edits;
277}
278
279/* Number of bytes for all groups >= given group. */
280always_inline uword
281pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
282{
Calvin71e97c62016-08-19 16:23:14 -0400283 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284 uword n_bytes = 0;
285
286 for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
287 n_bytes += g->n_packet_bytes;
288 return n_bytes;
289}
290
291always_inline void
292pg_free_edit_group (pg_stream_t * s)
293{
294 uword i = vec_len (s->edit_groups) - 1;
Calvin71e97c62016-08-19 16:23:14 -0400295 pg_edit_group_t *g = pg_stream_get_group (s, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700296
297 pg_edit_group_free (g);
Dave Barachb7b92992018-10-17 10:38:51 -0400298 clib_memset (g, 0, sizeof (g[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700299 _vec_len (s->edit_groups) = i;
300}
301
Neale Ranns6197cb72021-06-03 14:43:21 +0000302typedef enum pg_interface_mode_t_
303{
304 PG_MODE_ETHERNET,
305 PG_MODE_IP4,
306 PG_MODE_IP6,
307} pg_interface_mode_t;
308
Calvin71e97c62016-08-19 16:23:14 -0400309typedef struct
310{
Damjan Marion64034362016-11-07 22:19:55 +0100311 /* TX lock */
312 volatile u32 *lockp;
313
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314 /* VLIB interface indices. */
315 u32 hw_if_index, sw_if_index;
316
317 /* Identifies stream for this interface. */
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200318 u32 id;
319
Mohsin Kazmif382b062020-08-11 15:00:44 +0200320 u8 coalesce_enabled;
321 gro_flow_table_t *flow_table;
Mohsin Kazmi22e9cfd2019-07-23 11:54:48 +0200322 u8 gso_enabled;
323 u32 gso_size;
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200324 pcap_main_t pcap_main;
Jakub Grajciardb863292020-01-30 14:14:15 +0100325 char *pcap_file_name;
Neale Ranns6197cb72021-06-03 14:43:21 +0000326 pg_interface_mode_t mode;
Neale Ranns21fb4f72020-10-05 12:26:47 +0000327
328 mac_address_t *allowed_mcast_macs;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329} pg_interface_t;
330
331/* Per VLIB node data. */
Calvin71e97c62016-08-19 16:23:14 -0400332typedef struct
333{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700334 /* Parser function indexed by node index. */
Calvin71e97c62016-08-19 16:23:14 -0400335 unformat_function_t *unformat_edit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336} pg_node_t;
337
Calvin71e97c62016-08-19 16:23:14 -0400338typedef struct pg_main_t
339{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340 /* Pool of streams. */
Calvin71e97c62016-08-19 16:23:14 -0400341 pg_stream_t *streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700342
343 /* Bitmap indicating which streams are currently enabled. */
Damjan Marion3a4ed392016-11-08 13:20:42 +0100344 uword **enabled_streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700345
346 /* Hash mapping name -> stream index. */
Calvin71e97c62016-08-19 16:23:14 -0400347 uword *stream_index_by_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200349 /* Pool of interfaces. */
Calvin71e97c62016-08-19 16:23:14 -0400350 pg_interface_t *interfaces;
351 uword *if_index_by_if_id;
Neale Ranns21fb4f72020-10-05 12:26:47 +0000352 uword *if_id_by_sw_if_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353
Dave Barach3c8e1462019-01-05 16:51:41 -0500354 /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
355 u32 **replay_buffers_by_thread;
356
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357 /* Per VLIB node information. */
Calvin71e97c62016-08-19 16:23:14 -0400358 pg_node_t *nodes;
Filip Tehlar83e5a112021-06-21 12:11:28 +0000359
360 u16 msg_id_base;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700361} pg_main_t;
362
363/* Global main structure. */
364extern pg_main_t pg_main;
365
366/* Global node. */
367extern vlib_node_registration_t pg_input_node;
368
369/* Buffer generator input, output node functions. */
370vlib_node_function_t pg_input, pg_output;
371
372/* Stream add/delete. */
373void pg_stream_del (pg_main_t * pg, uword index);
374void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
Kingwel Xie42223472019-01-19 22:49:26 -0500375void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376
377/* Enable/disable stream. */
Calvin71e97c62016-08-19 16:23:14 -0400378void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
379 int is_enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380
Mohsin Kazmif382b062020-08-11 15:00:44 +0200381/* Enable/disable packet coalesce on given interface */
382void pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
383 u32 tx_node_index);
384
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385/* Find/create free packet-generator interface index. */
Neale Ranns6197cb72021-06-03 14:43:21 +0000386u32 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);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389
390always_inline pg_node_t *
391pg_get_node (uword node_index)
392{
Calvin71e97c62016-08-19 16:23:14 -0400393 pg_main_t *pg = &pg_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394 vec_validate (pg->nodes, node_index);
395 return pg->nodes + node_index;
396}
397
398void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
399 u32 group_index,
Calvin71e97c62016-08-19 16:23:14 -0400400 void *fixed_packet_data,
401 void *fixed_packet_data_mask);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200403void pg_enable_disable (u32 stream_index, int is_enable);
404
Calvin71e97c62016-08-19 16:23:14 -0400405typedef struct
406{
407 u32 hw_if_index;
408 u32 dev_instance;
409 u8 is_enabled;
Jakub Grajciardb863292020-01-30 14:14:15 +0100410 char *pcap_file_name;
Calvin71e97c62016-08-19 16:23:14 -0400411 u32 count;
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200412} pg_capture_args_t;
413
Calvin71e97c62016-08-19 16:23:14 -0400414clib_error_t *pg_capture (pg_capture_args_t * a);
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200415
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100416typedef struct
417{
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100418 u32 buffer_index;
Damjan Marion8c698872020-10-10 19:17:58 +0200419 vlib_buffer_t buffer;
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100420}
421pg_output_trace_t;
422
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423#endif /* included_vlib_pg_h */
Calvin71e97c62016-08-19 16:23:14 -0400424
425/*
426 * fd.io coding-style-patch-verification: ON
427 *
428 * Local Variables:
429 * eval: (c-set-style "gnu")
430 * End:
431 */