blob: 111df91ae99b169ec84ef1e73caf3718361d477d [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 */
Damjan Marion3d9c86e2016-07-04 21:04:40 +020046#include <vnet/unix/pcap.h>
47#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
92 /* Buffer free list for this buffer index in stream. */
93 u32 free_list_index;
94} 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)
105#define PG_STREAM_FLAGS_DISABLE_BUFFER_RECYCLE (1 << 1)
106
107 /* Edit groups are created by each protocol level (e.g. ethernet,
108 ip4, tcp, ...). */
Calvin71e97c62016-08-19 16:23:14 -0400109 pg_edit_group_t *edit_groups;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700110
111 pg_edit_type_t packet_size_edit_type;
112
113 /* Min/max packet size. */
114 u32 min_packet_bytes, max_packet_bytes;
115
116 /* Vector of non-fixed edits for this stream.
117 All fixed edits are performed and placed into fixed_packet_data. */
Calvin71e97c62016-08-19 16:23:14 -0400118 pg_edit_t *non_fixed_edits;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119
120 /* Packet data with all fixed edits performed.
121 All packets in stream are initialized according with this data.
122 Mask specifies which bits of packet data are covered by fixed edits. */
Calvin71e97c62016-08-19 16:23:14 -0400123 u8 *fixed_packet_data, *fixed_packet_data_mask;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124
125 /* Size to use for buffers. 0 means use buffers big enough
126 for max_packet_bytes. */
127 u32 buffer_bytes;
128
129 /* 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
161 /* Rate for this stream in packets/second.
162 Zero means unlimited rate. */
163 f64 rate_packets_per_second;
164
165 f64 time_last_generate;
166
167 f64 packet_accumulator;
168
Calvin71e97c62016-08-19 16:23:14 -0400169 pg_buffer_index_t *buffer_indices;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Calvin71e97c62016-08-19 16:23:14 -0400171 u8 **replay_packet_templates;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700172 u32 current_replay_packet_index;
173} pg_stream_t;
174
175always_inline void
176pg_buffer_index_free (pg_buffer_index_t * bi)
177{
178 vec_free (bi->edits);
179 clib_fifo_free (bi->buffer_fifo);
180}
181
182always_inline void
183pg_edit_group_free (pg_edit_group_t * g)
184{
Calvin71e97c62016-08-19 16:23:14 -0400185 pg_edit_t *e;
186 vec_foreach (e, g->edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187 vec_free (g->edits);
188 vec_free (g->fixed_packet_data);
189 vec_free (g->fixed_packet_data_mask);
190}
191
192always_inline void
193pg_stream_free (pg_stream_t * s)
194{
Calvin71e97c62016-08-19 16:23:14 -0400195 pg_edit_group_t *g;
196 pg_edit_t *e;
197 vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700198 vec_free (s->non_fixed_edits);
Calvin71e97c62016-08-19 16:23:14 -0400199 vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700200 vec_free (s->edit_groups);
201 vec_free (s->fixed_packet_data);
202 vec_free (s->fixed_packet_data_mask);
203 vec_free (s->name);
204
205 {
Calvin71e97c62016-08-19 16:23:14 -0400206 pg_buffer_index_t *bi;
207 vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208 vec_free (s->buffer_indices);
209 }
210}
211
212always_inline int
213pg_stream_is_enabled (pg_stream_t * s)
Calvin71e97c62016-08-19 16:23:14 -0400214{
215 return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
216}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217
218always_inline pg_edit_group_t *
219pg_stream_get_group (pg_stream_t * s, u32 group_index)
Calvin71e97c62016-08-19 16:23:14 -0400220{
221 return vec_elt_at_index (s->edit_groups, group_index);
222}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223
224always_inline void *
225pg_create_edit_group (pg_stream_t * s,
Calvin71e97c62016-08-19 16:23:14 -0400226 int n_edit_bytes, int n_packet_bytes, u32 * group_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227{
Calvin71e97c62016-08-19 16:23:14 -0400228 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229 int n_edits;
230
231 vec_add2 (s->edit_groups, g, 1);
232 if (group_index)
233 *group_index = g - s->edit_groups;
234
235 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
236 n_edits = n_edit_bytes / sizeof (pg_edit_t);
237 vec_resize (g->edits, n_edits);
238
239 g->n_packet_bytes = n_packet_bytes;
240
241 return g->edits;
242}
243
244always_inline void *
245pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
246 u32 group_index)
247{
Calvin71e97c62016-08-19 16:23:14 -0400248 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
249 pg_edit_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250 int n_edits;
251 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
252 n_edits = n_edit_bytes / sizeof (pg_edit_t);
253 vec_add2 (g->edits, e, n_edits);
254 g->n_packet_bytes += n_packet_bytes;
255 return e;
256}
257
258always_inline void *
259pg_get_edit_group (pg_stream_t * s, u32 group_index)
260{
Calvin71e97c62016-08-19 16:23:14 -0400261 pg_edit_group_t *g = pg_stream_get_group (s, group_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700262 return g->edits;
263}
264
265/* Number of bytes for all groups >= given group. */
266always_inline uword
267pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
268{
Calvin71e97c62016-08-19 16:23:14 -0400269 pg_edit_group_t *g;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700270 uword n_bytes = 0;
271
272 for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
273 n_bytes += g->n_packet_bytes;
274 return n_bytes;
275}
276
277always_inline void
278pg_free_edit_group (pg_stream_t * s)
279{
280 uword i = vec_len (s->edit_groups) - 1;
Calvin71e97c62016-08-19 16:23:14 -0400281 pg_edit_group_t *g = pg_stream_get_group (s, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282
283 pg_edit_group_free (g);
284 memset (g, 0, sizeof (g[0]));
285 _vec_len (s->edit_groups) = i;
286}
287
Calvin71e97c62016-08-19 16:23:14 -0400288typedef struct
289{
Damjan Marion64034362016-11-07 22:19:55 +0100290 /* TX lock */
291 volatile u32 *lockp;
292
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293 /* VLIB interface indices. */
294 u32 hw_if_index, sw_if_index;
295
296 /* Identifies stream for this interface. */
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200297 u32 id;
298
299 pcap_main_t pcap_main;
Calvin71e97c62016-08-19 16:23:14 -0400300 u8 *pcap_file_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700301} pg_interface_t;
302
303/* Per VLIB node data. */
Calvin71e97c62016-08-19 16:23:14 -0400304typedef struct
305{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306 /* Parser function indexed by node index. */
Calvin71e97c62016-08-19 16:23:14 -0400307 unformat_function_t *unformat_edit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308} pg_node_t;
309
Calvin71e97c62016-08-19 16:23:14 -0400310typedef struct pg_main_t
311{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700312 /* Pool of streams. */
Calvin71e97c62016-08-19 16:23:14 -0400313 pg_stream_t *streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314
315 /* Bitmap indicating which streams are currently enabled. */
Damjan Marion3a4ed392016-11-08 13:20:42 +0100316 uword **enabled_streams;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317
318 /* Hash mapping name -> stream index. */
Calvin71e97c62016-08-19 16:23:14 -0400319 uword *stream_index_by_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700320
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200321 /* Pool of interfaces. */
Calvin71e97c62016-08-19 16:23:14 -0400322 pg_interface_t *interfaces;
323 uword *if_index_by_if_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700324
325 /* Per VLIB node information. */
Calvin71e97c62016-08-19 16:23:14 -0400326 pg_node_t *nodes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327} pg_main_t;
328
329/* Global main structure. */
330extern pg_main_t pg_main;
331
332/* Global node. */
333extern vlib_node_registration_t pg_input_node;
334
335/* Buffer generator input, output node functions. */
336vlib_node_function_t pg_input, pg_output;
337
338/* Stream add/delete. */
339void pg_stream_del (pg_main_t * pg, uword index);
340void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
341
342/* Enable/disable stream. */
Calvin71e97c62016-08-19 16:23:14 -0400343void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
344 int is_enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700345
346/* Find/create free packet-generator interface index. */
Damjan Marion3d9c86e2016-07-04 21:04:40 +0200347u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348
349always_inline pg_node_t *
350pg_get_node (uword node_index)
351{
Calvin71e97c62016-08-19 16:23:14 -0400352 pg_main_t *pg = &pg_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353 vec_validate (pg->nodes, node_index);
354 return pg->nodes + node_index;
355}
356
357void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
358 u32 group_index,
Calvin71e97c62016-08-19 16:23:14 -0400359 void *fixed_packet_data,
360 void *fixed_packet_data_mask);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700361
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200362void pg_enable_disable (u32 stream_index, int is_enable);
363
Calvin71e97c62016-08-19 16:23:14 -0400364typedef struct
365{
366 u32 hw_if_index;
367 u32 dev_instance;
368 u8 is_enabled;
369 u8 *pcap_file_name;
370 u32 count;
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200371} pg_capture_args_t;
372
Calvin71e97c62016-08-19 16:23:14 -0400373clib_error_t *pg_capture (pg_capture_args_t * a);
Pavel Kotucek9e6ed6e2016-07-12 10:18:26 +0200374
Damjan Marionbfe4dfa2017-02-03 21:16:16 +0100375typedef struct
376{
377 vlib_buffer_t buffer;
378 u32 buffer_index;
379}
380pg_output_trace_t;
381
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382#endif /* included_vlib_pg_h */
Calvin71e97c62016-08-19 16:23:14 -0400383
384/*
385 * fd.io coding-style-patch-verification: ON
386 *
387 * Local Variables:
388 * eval: (c-set-style "gnu")
389 * End:
390 */