Initial commit of vpp code.
[vpp.git] / vnet / vnet / pg / pg.h
1 /*
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>
45 #include <vppinfra/fifo.h>              /* for buffer_fifo */
46
47 struct pg_main_t;
48 struct pg_stream_t;
49
50 typedef struct pg_edit_group_t {
51   /* Edits in this group. */
52   pg_edit_t * edits;
53
54   /* Vector of non-fixed edits for this group. */
55   pg_edit_t * non_fixed_edits;
56
57   /* Fixed edits for this group. */
58   u8 * fixed_packet_data;
59   u8 * fixed_packet_data_mask;
60
61   /* Byte offset where packet data begins. */
62   u32 start_byte_offset;
63
64   /* Number of packet bytes for this edit group. */
65   u32 n_packet_bytes;
66
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,
71                           u32 * buffers,
72                           u32 n_buffers);
73
74   /* Opaque data for edit function's use. */
75   uword edit_function_opaque;
76 } pg_edit_group_t;
77
78 /* Packets are made of multiple buffers chained together.
79    This struct keeps track of data per-chain index. */
80 typedef struct {
81   /* Vector of buffer edits for this stream and buffer index. */
82   pg_edit_t * edits;
83
84   /* Buffers pre-initialized with fixed buffer data for this stream. */
85   u32 * buffer_fifo;
86
87   /* Buffer free list for this buffer index in stream. */
88   u32 free_list_index;
89 } pg_buffer_index_t;
90
91 typedef struct pg_stream_t {
92   /* Stream name. */
93   u8 * name;
94
95   u32 flags;
96
97   /* Stream is currently enabled. */
98 #define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
99 #define PG_STREAM_FLAGS_DISABLE_BUFFER_RECYCLE (1 << 1)
100
101   /* Edit groups are created by each protocol level (e.g. ethernet,
102      ip4, tcp, ...). */
103   pg_edit_group_t * edit_groups;
104
105   pg_edit_type_t packet_size_edit_type;
106
107   /* Min/max packet size. */
108   u32 min_packet_bytes, max_packet_bytes;
109
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;
113
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;
118
119   /* Size to use for buffers.  0 means use buffers big enough
120      for max_packet_bytes. */
121   u32 buffer_bytes;
122
123   /* Last packet length if packet size edit type is increment. */
124   u32 last_increment_packet_size;
125
126   /* Index into main interface pool for this stream. */
127   u32 pg_if_index;
128
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];
136
137   /* Node where stream's buffers get put. */
138   u32 node_index;
139
140   /* Output next index to reach output node from stream input node. */
141   u32 next_index;
142
143   /* Number of packets currently generated. */
144   u64 n_packets_generated;
145
146   /* Stream is disabled when packet limit is reached.
147      Zero means no packet limit. */
148   u64 n_packets_limit;
149
150   /* Rate for this stream in packets/second.
151      Zero means unlimited rate. */
152   f64 rate_packets_per_second;
153
154   f64 time_last_generate;
155
156   f64 packet_accumulator;
157
158   pg_buffer_index_t * buffer_indices;
159
160   u8 ** replay_packet_templates;
161   u32 current_replay_packet_index;
162 } pg_stream_t;
163
164 always_inline void
165 pg_buffer_index_free (pg_buffer_index_t * bi)
166 {
167   vec_free (bi->edits);
168   clib_fifo_free (bi->buffer_fifo);
169 }
170
171 always_inline void
172 pg_edit_group_free (pg_edit_group_t * g)
173 {
174   pg_edit_t * e;
175   vec_foreach (e, g->edits)
176     pg_edit_free (e);
177   vec_free (g->edits);
178   vec_free (g->fixed_packet_data);
179   vec_free (g->fixed_packet_data_mask);
180 }
181
182 always_inline void
183 pg_stream_free (pg_stream_t * s)
184 {
185   pg_edit_group_t * g;
186   pg_edit_t * e;
187   vec_foreach (e, s->non_fixed_edits)
188     pg_edit_free (e);
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);
195   vec_free (s->name);
196
197   {
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);
202   }
203 }
204
205 always_inline int
206 pg_stream_is_enabled (pg_stream_t * s)
207 { return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0; }
208
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); }
212
213 always_inline void *
214 pg_create_edit_group (pg_stream_t * s,
215                       int n_edit_bytes,
216                       int n_packet_bytes,
217                       u32 * group_index)
218 {
219   pg_edit_group_t * g;
220   int n_edits;
221
222   vec_add2 (s->edit_groups, g, 1);
223   if (group_index)
224     *group_index = g - s->edit_groups;
225
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);
229
230   g->n_packet_bytes = n_packet_bytes;
231
232   return g->edits;
233 }
234
235 always_inline void *
236 pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
237               u32 group_index)
238 {
239   pg_edit_group_t * g = pg_stream_get_group (s, group_index);
240   pg_edit_t * e;
241   int n_edits;
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;
246   return e;
247 }
248
249 always_inline void *
250 pg_get_edit_group (pg_stream_t * s, u32 group_index)
251 {
252   pg_edit_group_t * g = pg_stream_get_group (s, group_index);
253   return g->edits;
254 }
255
256 /* Number of bytes for all groups >= given group. */
257 always_inline uword
258 pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
259 {
260   pg_edit_group_t * g;
261   uword n_bytes = 0;
262
263   for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
264     n_bytes += g->n_packet_bytes;
265   return n_bytes;
266 }
267
268 always_inline void
269 pg_free_edit_group (pg_stream_t * s)
270 {
271   uword i = vec_len (s->edit_groups) - 1;
272   pg_edit_group_t * g = pg_stream_get_group (s, i);
273
274   pg_edit_group_free (g);
275   memset (g, 0, sizeof (g[0]));
276   _vec_len (s->edit_groups) = i;
277 }
278
279 typedef struct {
280   /* VLIB interface indices. */
281   u32 hw_if_index, sw_if_index;
282
283   /* Identifies stream for this interface. */
284   u32 stream_index;
285 } pg_interface_t;
286
287 /* Per VLIB node data. */
288 typedef struct {
289   /* Parser function indexed by node index. */
290   unformat_function_t * unformat_edit;
291 } pg_node_t;
292
293 typedef struct pg_main_t {
294   /* Back pointer to main structure. */
295   vlib_main_t * vlib_main;
296
297   /* Pool of streams. */
298   pg_stream_t * streams;
299
300   /* Bitmap indicating which streams are currently enabled. */
301   uword * enabled_streams;
302
303   /* Hash mapping name -> stream index. */
304   uword * stream_index_by_name;
305
306   /* Vector of interfaces. */
307   pg_interface_t * interfaces;
308
309   /* Per VLIB node information. */
310   pg_node_t * nodes;
311
312   u32 * free_interfaces;
313 } pg_main_t;
314
315 /* Global main structure. */
316 extern pg_main_t pg_main;
317
318 /* Global node. */
319 extern vlib_node_registration_t pg_input_node;
320
321 /* Buffer generator input, output node functions. */
322 vlib_node_function_t pg_input, pg_output;
323
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);
327
328 /* Enable/disable stream. */
329 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s, int is_enable);
330
331 /* Find/create free packet-generator interface index. */
332 u32 pg_interface_find_free (pg_main_t * pg, uword stream_index);
333
334 always_inline pg_node_t *
335 pg_get_node (uword node_index)
336 {
337   pg_main_t * pg = &pg_main;
338   vec_validate (pg->nodes, node_index);
339   return pg->nodes + node_index;
340 }
341
342 void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
343                                           u32 group_index,
344                                           void * fixed_packet_data,
345                                           void * fixed_packet_data_mask);
346
347 #endif /* included_vlib_pg_h */