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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 * pg.h: VLIB packet generator
18 * Copyright (c) 2008 Eliot Dresselhaus
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:
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
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.
40 #ifndef included_vlib_pg_h
41 #define included_vlib_pg_h
43 #include <vlib/vlib.h> /* for VLIB_N_RX_TX */
44 #include <vnet/pg/edit.h>
45 #include <vppinfra/fifo.h> /* for buffer_fifo */
50 typedef struct pg_edit_group_t {
51 /* Edits in this group. */
54 /* Vector of non-fixed edits for this group. */
55 pg_edit_t * non_fixed_edits;
57 /* Fixed edits for this group. */
58 u8 * fixed_packet_data;
59 u8 * fixed_packet_data_mask;
61 /* Byte offset where packet data begins. */
62 u32 start_byte_offset;
64 /* Number of packet bytes for this edit group. */
67 /* Function to perform miscellaneous edits (e.g. set IP checksum, ...). */
68 void (* edit_function) (struct pg_main_t * pg,
69 struct pg_stream_t * s,
70 struct pg_edit_group_t * g,
74 /* Opaque data for edit function's use. */
75 uword edit_function_opaque;
78 /* Packets are made of multiple buffers chained together.
79 This struct keeps track of data per-chain index. */
81 /* Vector of buffer edits for this stream and buffer index. */
84 /* Buffers pre-initialized with fixed buffer data for this stream. */
87 /* Buffer free list for this buffer index in stream. */
91 typedef struct pg_stream_t {
97 /* Stream is currently enabled. */
98 #define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
99 #define PG_STREAM_FLAGS_DISABLE_BUFFER_RECYCLE (1 << 1)
101 /* Edit groups are created by each protocol level (e.g. ethernet,
103 pg_edit_group_t * edit_groups;
105 pg_edit_type_t packet_size_edit_type;
107 /* Min/max packet size. */
108 u32 min_packet_bytes, max_packet_bytes;
110 /* Vector of non-fixed edits for this stream.
111 All fixed edits are performed and placed into fixed_packet_data. */
112 pg_edit_t * non_fixed_edits;
114 /* Packet data with all fixed edits performed.
115 All packets in stream are initialized according with this data.
116 Mask specifies which bits of packet data are covered by fixed edits. */
117 u8 * fixed_packet_data, * fixed_packet_data_mask;
119 /* Size to use for buffers. 0 means use buffers big enough
120 for max_packet_bytes. */
123 /* Last packet length if packet size edit type is increment. */
124 u32 last_increment_packet_size;
126 /* Index into main interface pool for this stream. */
129 /* Interface used to mark packets for this stream. May be different
130 than hw/sw index from pg main interface pool. They will be
131 different if this stream is being used generate buffers as if
132 they were received on a non-pg interface. For example, suppose you
133 are trying to test vlan code and you want to generate buffers that
134 appear to come from an ethernet interface. */
135 u32 sw_if_index[VLIB_N_RX_TX];
137 /* Node where stream's buffers get put. */
140 /* Output next index to reach output node from stream input node. */
143 /* Number of packets currently generated. */
144 u64 n_packets_generated;
146 /* Stream is disabled when packet limit is reached.
147 Zero means no packet limit. */
150 /* Rate for this stream in packets/second.
151 Zero means unlimited rate. */
152 f64 rate_packets_per_second;
154 f64 time_last_generate;
156 f64 packet_accumulator;
158 pg_buffer_index_t * buffer_indices;
160 u8 ** replay_packet_templates;
161 u32 current_replay_packet_index;
165 pg_buffer_index_free (pg_buffer_index_t * bi)
167 vec_free (bi->edits);
168 clib_fifo_free (bi->buffer_fifo);
172 pg_edit_group_free (pg_edit_group_t * g)
175 vec_foreach (e, g->edits)
178 vec_free (g->fixed_packet_data);
179 vec_free (g->fixed_packet_data_mask);
183 pg_stream_free (pg_stream_t * s)
187 vec_foreach (e, s->non_fixed_edits)
189 vec_free (s->non_fixed_edits);
190 vec_foreach (g, s->edit_groups)
191 pg_edit_group_free (g);
192 vec_free (s->edit_groups);
193 vec_free (s->fixed_packet_data);
194 vec_free (s->fixed_packet_data_mask);
198 pg_buffer_index_t * bi;
199 vec_foreach (bi, s->buffer_indices)
200 pg_buffer_index_free (bi);
201 vec_free (s->buffer_indices);
206 pg_stream_is_enabled (pg_stream_t * s)
207 { return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0; }
209 always_inline pg_edit_group_t *
210 pg_stream_get_group (pg_stream_t * s, u32 group_index)
211 { return vec_elt_at_index (s->edit_groups, group_index); }
214 pg_create_edit_group (pg_stream_t * s,
222 vec_add2 (s->edit_groups, g, 1);
224 *group_index = g - s->edit_groups;
226 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
227 n_edits = n_edit_bytes / sizeof (pg_edit_t);
228 vec_resize (g->edits, n_edits);
230 g->n_packet_bytes = n_packet_bytes;
236 pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
239 pg_edit_group_t * g = pg_stream_get_group (s, group_index);
242 ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
243 n_edits = n_edit_bytes / sizeof (pg_edit_t);
244 vec_add2 (g->edits, e, n_edits);
245 g->n_packet_bytes += n_packet_bytes;
250 pg_get_edit_group (pg_stream_t * s, u32 group_index)
252 pg_edit_group_t * g = pg_stream_get_group (s, group_index);
256 /* Number of bytes for all groups >= given group. */
258 pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
263 for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
264 n_bytes += g->n_packet_bytes;
269 pg_free_edit_group (pg_stream_t * s)
271 uword i = vec_len (s->edit_groups) - 1;
272 pg_edit_group_t * g = pg_stream_get_group (s, i);
274 pg_edit_group_free (g);
275 memset (g, 0, sizeof (g[0]));
276 _vec_len (s->edit_groups) = i;
280 /* VLIB interface indices. */
281 u32 hw_if_index, sw_if_index;
283 /* Identifies stream for this interface. */
287 /* Per VLIB node data. */
289 /* Parser function indexed by node index. */
290 unformat_function_t * unformat_edit;
293 typedef struct pg_main_t {
294 /* Back pointer to main structure. */
295 vlib_main_t * vlib_main;
297 /* Pool of streams. */
298 pg_stream_t * streams;
300 /* Bitmap indicating which streams are currently enabled. */
301 uword * enabled_streams;
303 /* Hash mapping name -> stream index. */
304 uword * stream_index_by_name;
306 /* Vector of interfaces. */
307 pg_interface_t * interfaces;
309 /* Per VLIB node information. */
312 u32 * free_interfaces;
315 /* Global main structure. */
316 extern pg_main_t pg_main;
319 extern vlib_node_registration_t pg_input_node;
321 /* Buffer generator input, output node functions. */
322 vlib_node_function_t pg_input, pg_output;
324 /* Stream add/delete. */
325 void pg_stream_del (pg_main_t * pg, uword index);
326 void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
328 /* Enable/disable stream. */
329 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s, int is_enable);
331 /* Find/create free packet-generator interface index. */
332 u32 pg_interface_find_free (pg_main_t * pg, uword stream_index);
334 always_inline pg_node_t *
335 pg_get_node (uword node_index)
337 pg_main_t * pg = &pg_main;
338 vec_validate (pg->nodes, node_index);
339 return pg->nodes + node_index;
342 void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
344 void * fixed_packet_data,
345 void * fixed_packet_data_mask);
347 #endif /* included_vlib_pg_h */