blob: 06e61261b7dfb0d7e132f2542c7a66a3e19f3d95 [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>
Mohsin Kazmif382b062020-08-11 15:00:44 +020048#include <vnet/gso/gro.h>
Damjan Marion3d9c86e2016-07-04 21:04:40 +020049
50extern vnet_device_class_t pg_dev_class;
Ed Warnickecb9cada2015-12-08 15:45:58 -070051
52struct pg_main_t;
53struct pg_stream_t;
54
Calvin71e97c62016-08-19 16:23:14 -040055typedef struct pg_edit_group_t
56{
Ed Warnickecb9cada2015-12-08 15:45:58 -070057 /* Edits in this group. */
Calvin71e97c62016-08-19 16:23:14 -040058 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070059
60 /* Vector of non-fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040061 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070062
63 /* Fixed edits for this group. */
Calvin71e97c62016-08-19 16:23:14 -040064 u8 *fixed_packet_data;
65 u8 *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -070066
67 /* Byte offset where packet data begins. */
68 u32 start_byte_offset;
69
70 /* Number of packet bytes for this edit group. */
71 u32 n_packet_bytes;
72
73 /* Function to perform miscellaneous edits (e.g. set IP checksum, ...). */
Calvin71e97c62016-08-19 16:23:14 -040074 void (*edit_function) (struct pg_main_t * pg,
75 struct pg_stream_t * s,
76 struct pg_edit_group_t * g,
77 u32 * buffers, u32 n_buffers);
Ed Warnickecb9cada2015-12-08 15:45:58 -070078
79 /* Opaque data for edit function's use. */
80 uword edit_function_opaque;
81} pg_edit_group_t;
82
83/* Packets are made of multiple buffers chained together.
84 This struct keeps track of data per-chain index. */
Calvin71e97c62016-08-19 16:23:14 -040085typedef struct
86{
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 /* Vector of buffer edits for this stream and buffer index. */
Calvin71e97c62016-08-19 16:23:14 -040088 pg_edit_t *edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -070089
90 /* Buffers pre-initialized with fixed buffer data for this stream. */
Calvin71e97c62016-08-19 16:23:14 -040091 u32 *buffer_fifo;
Ed Warnickecb9cada2015-12-08 15:45:58 -070092
Ed Warnickecb9cada2015-12-08 15:45:58 -070093} pg_buffer_index_t;
94
Calvin71e97c62016-08-19 16:23:14 -040095typedef struct pg_stream_t
96{
Ed Warnickecb9cada2015-12-08 15:45:58 -070097 /* Stream name. */
Calvin71e97c62016-08-19 16:23:14 -040098 u8 *name;
Ed Warnickecb9cada2015-12-08 15:45:58 -070099
100 u32 flags;
101
102 /* Stream is currently enabled. */
103#define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104
105 /* Edit groups are created by each protocol level (e.g. ethernet,
106 ip4, tcp, ...). */
Calvin71e97c62016-08-19 16:23:14 -0400107 pg_edit_group_t *edit_groups;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700108
109 pg_edit_type_t packet_size_edit_type;
110
111 /* Min/max packet size. */
112 u32 min_packet_bytes, max_packet_bytes;
113
114 /* Vector of non-fixed edits for this stream.
115 All fixed edits are performed and placed into fixed_packet_data. */
Calvin71e97c62016-08-19 16:23:14 -0400116 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700117
118 /* Packet data with all fixed edits performed.
119 All packets in stream are initialized according with this data.
120 Mask specifies which bits of packet data are covered by fixed edits. */
Calvin71e97c62016-08-19 16:23:14 -0400121 u8 *fixed_packet_data, *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122
123 /* Size to use for buffers. 0 means use buffers big enough
124 for max_packet_bytes. */
125 u32 buffer_bytes;
126
Dave Barach08eb2bb2020-04-15 09:34:43 -0400127 /* Buffer flags to set in each packet e.g. checksum offload flags */
128 u32 buffer_flags;
129
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130 /* Last packet length if packet size edit type is increment. */
131 u32 last_increment_packet_size;
132
133 /* Index into main interface pool for this stream. */
134 u32 pg_if_index;
135
136 /* Interface used to mark packets for this stream. May be different
137 than hw/sw index from pg main interface pool. They will be
138 different if this stream is being used generate buffers as if
139 they were received on a non-pg interface. For example, suppose you
140 are trying to test vlan code and you want to generate buffers that
141 appear to come from an ethernet interface. */
142 u32 sw_if_index[VLIB_N_RX_TX];
143
144 /* Node where stream's buffers get put. */
145 u32 node_index;
146
Damjan Marion64034362016-11-07 22:19:55 +0100147 /* Worker thread index */
148 u32 worker_index;
149
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 /* Output next index to reach output node from stream input node. */
151 u32 next_index;
152
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200153 u32 if_id;
154
Ed Warnickecb9cada2015-12-08 15:45:58 -0700155 /* Number of packets currently generated. */
156 u64 n_packets_generated;
157
158 /* Stream is disabled when packet limit is reached.
159 Zero means no packet limit. */
160 u64 n_packets_limit;
161
Christian E. Hopps87d7bac2019-09-27 12:59:30 -0400162 /* Only generate up to n_max_frame per frame. */
163 u32 n_max_frame;
164
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165 /* Rate for this stream in packets/second.
166 Zero means unlimited rate. */
167 f64 rate_packets_per_second;
168
169 f64 time_last_generate;
170
171 f64 packet_accumulator;
172
Calvin71e97c62016-08-19 16:23:14 -0400173 pg_buffer_index_t *buffer_indices;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174
Calvin71e97c62016-08-19 16:23:14 -0400175 u8 **replay_packet_templates;
Dave Barach78c56892018-05-16 11:34:35 -0400176 u64 *replay_packet_timestamps;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177 u32 current_replay_packet_index;
178} pg_stream_t;
179
180always_inline void
181pg_buffer_index_free (pg_buffer_index_t * bi)
182{
183 vec_free (bi->edits);
184 clib_fifo_free (bi->buffer_fifo);
185}
186
187always_inline void
188pg_edit_group_free (pg_edit_group_t * g)
189{
Calvin71e97c62016-08-19 16:23:14 -0400190 pg_edit_t *e;
191 vec_foreach (e, g->edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192 vec_free (g->edits);
193 vec_free (g->fixed_packet_data);
194 vec_free (g->fixed_packet_data_mask);
195}
196
197always_inline void
198pg_stream_free (pg_stream_t * s)
199{
Dave Barach78c56892018-05-16 11:34:35 -0400200 int i;
Calvin71e97c62016-08-19 16:23:14 -0400201 pg_edit_group_t *g;
202 pg_edit_t *e;
203 vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 vec_free (s->non_fixed_edits);
Calvin71e97c62016-08-19 16:23:14 -0400205 vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206 vec_free (s->edit_groups);
207 vec_free (s->fixed_packet_data);
208 vec_free (s->fixed_packet_data_mask);
209 vec_free (s->name);
Dave Barach78c56892018-05-16 11:34:35 -0400210 for (i = 0; i < vec_len (s->replay_packet_templates); i++)
211 vec_free (s->replay_packet_templates[i]);
212 vec_free (s->replay_packet_templates);
213 vec_free (s->replay_packet_timestamps);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214
215 {
Calvin71e97c62016-08-19 16:23:14 -0400216 pg_buffer_index_t *bi;
217 vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700218 vec_free (s->buffer_indices);
219 }
220}
221
222always_inline int
223pg_stream_is_enabled (pg_stream_t * s)
Calvin71e97c62016-08-19 16:23:14 -0400224{
225 return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
226}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227
228always_inline pg_edit_group_t *
229pg_stream_get_group (pg_stream_t * s, u32 group_index)
Calvin71e97c62016-08-19 16:23:14 -0400230{
231 return vec_elt_at_index (s->edit_groups, group_index);
232}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
234always_inline void *
235pg_create_edit_group (pg_stream_t * s,
Calvin71e97c62016-08-19 16:23:14 -0400236 int n_edit_bytes, int n_packet_bytes, u32 * group_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237{
Calvin71e97c62016-08-19 16:23:14 -0400238 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700239 int n_edits;
240
241 vec_add2 (s->edit_groups, g, 1);
242 if (group_index)
243 *group_index = g - s->edit_groups;
244
245 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
246 n_edits = n_edit_bytes / sizeof (pg_edit_t);
247 vec_resize (g->edits, n_edits);
248
249 g->n_packet_bytes = n_packet_bytes;
250
251 return g->edits;
252}
253
254always_inline void *
255pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
256 u32 group_index)
257{
Calvin71e97c62016-08-19 16:23:14 -0400258 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
259 pg_edit_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260 int n_edits;
261 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
262 n_edits = n_edit_bytes / sizeof (pg_edit_t);
263 vec_add2 (g->edits, e, n_edits);
264 g->n_packet_bytes += n_packet_bytes;
265 return e;
266}
267
268always_inline void *
269pg_get_edit_group (pg_stream_t * s, u32 group_index)
270{
Calvin71e97c62016-08-19 16:23:14 -0400271 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272 return g->edits;
273}
274
275/* Number of bytes for all groups >= given group. */
276always_inline uword
277pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
278{
Calvin71e97c62016-08-19 16:23:14 -0400279 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280 uword n_bytes = 0;
281
282 for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
283 n_bytes += g->n_packet_bytes;
284 return n_bytes;
285}
286
287always_inline void
288pg_free_edit_group (pg_stream_t * s)
289{
290 uword i = vec_len (s->edit_groups) - 1;
Calvin71e97c62016-08-19 16:23:14 -0400291 pg_edit_group_t *g = pg_stream_get_group (s, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700292
293 pg_edit_group_free (g);
Dave Barachb7b92992018-10-17 10:38:51 -0400294 clib_memset (g, 0, sizeof (g[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700295 _vec_len (s->edit_groups) = i;
296}
297
Calvin71e97c62016-08-19 16:23:14 -0400298typedef struct
299{
Damjan Marion64034362016-11-07 22:19:55 +0100300 /* TX lock */
301 volatile u32 *lockp;
302
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303 /* VLIB interface indices. */
304 u32 hw_if_index, sw_if_index;
305
306 /* Identifies stream for this interface. */
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200307 u32 id;
308
Mohsin Kazmif382b062020-08-11 15:00:44 +0200309 u8 coalesce_enabled;
310 gro_flow_table_t *flow_table;
Mohsin Kazmi22e9cfd2019-07-23 11:54:48 +0200311 u8 gso_enabled;
312 u32 gso_size;
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200313 pcap_main_t pcap_main;
Jakub Grajciardb863292020-01-30 14:14:15 +0100314 char *pcap_file_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700315} pg_interface_t;
316
317/* Per VLIB node data. */
Calvin71e97c62016-08-19 16:23:14 -0400318typedef struct
319{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700320 /* Parser function indexed by node index. */
Calvin71e97c62016-08-19 16:23:14 -0400321 unformat_function_t *unformat_edit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700322} pg_node_t;
323
Calvin71e97c62016-08-19 16:23:14 -0400324typedef struct pg_main_t
325{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700326 /* Pool of streams. */
Calvin71e97c62016-08-19 16:23:14 -0400327 pg_stream_t *streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700328
329 /* Bitmap indicating which streams are currently enabled. */
Damjan Marion3a4ed392016-11-08 13:20:42 +0100330 uword **enabled_streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331
332 /* Hash mapping name -> stream index. */
Calvin71e97c62016-08-19 16:23:14 -0400333 uword *stream_index_by_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700334
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200335 /* Pool of interfaces. */
Calvin71e97c62016-08-19 16:23:14 -0400336 pg_interface_t *interfaces;
337 uword *if_index_by_if_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700338
Dave Barach3c8e1462019-01-05 16:51:41 -0500339 /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
340 u32 **replay_buffers_by_thread;
341
Ed Warnickecb9cada2015-12-08 15:45:58 -0700342 /* Per VLIB node information. */
Calvin71e97c62016-08-19 16:23:14 -0400343 pg_node_t *nodes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344} pg_main_t;
345
346/* Global main structure. */
347extern pg_main_t pg_main;
348
349/* Global node. */
350extern vlib_node_registration_t pg_input_node;
351
352/* Buffer generator input, output node functions. */
353vlib_node_function_t pg_input, pg_output;
354
355/* Stream add/delete. */
356void pg_stream_del (pg_main_t * pg, uword index);
357void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
Kingwel Xie42223472019-01-19 22:49:26 -0500358void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359
360/* Enable/disable stream. */
Calvin71e97c62016-08-19 16:23:14 -0400361void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
362 int is_enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363
Mohsin Kazmif382b062020-08-11 15:00:44 +0200364/* Enable/disable packet coalesce on given interface */
365void pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
366 u32 tx_node_index);
367
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368/* Find/create free packet-generator interface index. */
Mohsin Kazmi22e9cfd2019-07-23 11:54:48 +0200369u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index,
Mohsin Kazmif382b062020-08-11 15:00:44 +0200370 u8 gso_enabled, u32 gso_size,
371 u8 coalesce_enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372
373always_inline pg_node_t *
374pg_get_node (uword node_index)
375{
Calvin71e97c62016-08-19 16:23:14 -0400376 pg_main_t *pg = &pg_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377 vec_validate (pg->nodes, node_index);
378 return pg->nodes + node_index;
379}
380
381void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
382 u32 group_index,
Calvin71e97c62016-08-19 16:23:14 -0400383 void *fixed_packet_data,
384 void *fixed_packet_data_mask);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200386void pg_enable_disable (u32 stream_index, int is_enable);
387
Calvin71e97c62016-08-19 16:23:14 -0400388typedef struct
389{
390 u32 hw_if_index;
391 u32 dev_instance;
392 u8 is_enabled;
Jakub Grajciardb863292020-01-30 14:14:15 +0100393 char *pcap_file_name;
Calvin71e97c62016-08-19 16:23:14 -0400394 u32 count;
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200395} pg_capture_args_t;
396
Calvin71e97c62016-08-19 16:23:14 -0400397clib_error_t *pg_capture (pg_capture_args_t * a);
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200398
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100399typedef struct
400{
401 vlib_buffer_t buffer;
402 u32 buffer_index;
403}
404pg_output_trace_t;
405
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406#endif /* included_vlib_pg_h */
Calvin71e97c62016-08-19 16:23:14 -0400407
408/*
409 * fd.io coding-style-patch-verification: ON
410 *
411 * Local Variables:
412 * eval: (c-set-style "gnu")
413 * End:
414 */