pg: set vnet buffer flags in pg streams
[vpp.git] / src / 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 #include <vppinfra/pcap.h>
47 #include <vnet/interface.h>
48
49 extern vnet_device_class_t pg_dev_class;
50
51 struct pg_main_t;
52 struct pg_stream_t;
53
54 typedef struct pg_edit_group_t
55 {
56   /* Edits in this group. */
57   pg_edit_t *edits;
58
59   /* Vector of non-fixed edits for this group. */
60   pg_edit_t *non_fixed_edits;
61
62   /* Fixed edits for this group. */
63   u8 *fixed_packet_data;
64   u8 *fixed_packet_data_mask;
65
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, ...). */
73   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);
77
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. */
84 typedef struct
85 {
86   /* Vector of buffer edits for this stream and buffer index. */
87   pg_edit_t *edits;
88
89   /* Buffers pre-initialized with fixed buffer data for this stream. */
90   u32 *buffer_fifo;
91
92 } pg_buffer_index_t;
93
94 typedef struct pg_stream_t
95 {
96   /* Stream name. */
97   u8 *name;
98
99   u32 flags;
100
101   /* Stream is currently enabled. */
102 #define PG_STREAM_FLAGS_IS_ENABLED (1 << 0)
103
104   /* Edit groups are created by each protocol level (e.g. ethernet,
105      ip4, tcp, ...). */
106   pg_edit_group_t *edit_groups;
107
108   pg_edit_type_t packet_size_edit_type;
109
110   /* Min/max packet size. */
111   u32 min_packet_bytes, max_packet_bytes;
112
113   /* Vector of non-fixed edits for this stream.
114      All fixed edits are performed and placed into fixed_packet_data. */
115   pg_edit_t *non_fixed_edits;
116
117   /* Packet data with all fixed edits performed.
118      All packets in stream are initialized according with this data.
119      Mask specifies which bits of packet data are covered by fixed edits. */
120   u8 *fixed_packet_data, *fixed_packet_data_mask;
121
122   /* Size to use for buffers.  0 means use buffers big enough
123      for max_packet_bytes. */
124   u32 buffer_bytes;
125
126   /* Buffer flags to set in each packet e.g. checksum offload flags */
127   u32 buffer_flags;
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
146   /* Worker thread index */
147   u32 worker_index;
148
149   /* Output next index to reach output node from stream input node. */
150   u32 next_index;
151
152   u32 if_id;
153
154   /* 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   /* Only generate up to n_max_frame per frame. */
162   u32 n_max_frame;
163
164   /* Rate for this stream in packets/second.
165      Zero means unlimited rate. */
166   f64 rate_packets_per_second;
167
168   f64 time_last_generate;
169
170   f64 packet_accumulator;
171
172   pg_buffer_index_t *buffer_indices;
173
174   u8 **replay_packet_templates;
175   u64 *replay_packet_timestamps;
176   u32 current_replay_packet_index;
177 } pg_stream_t;
178
179 always_inline void
180 pg_buffer_index_free (pg_buffer_index_t * bi)
181 {
182   vec_free (bi->edits);
183   clib_fifo_free (bi->buffer_fifo);
184 }
185
186 always_inline void
187 pg_edit_group_free (pg_edit_group_t * g)
188 {
189   pg_edit_t *e;
190   vec_foreach (e, g->edits) pg_edit_free (e);
191   vec_free (g->edits);
192   vec_free (g->fixed_packet_data);
193   vec_free (g->fixed_packet_data_mask);
194 }
195
196 always_inline void
197 pg_stream_free (pg_stream_t * s)
198 {
199   int i;
200   pg_edit_group_t *g;
201   pg_edit_t *e;
202   vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
203   vec_free (s->non_fixed_edits);
204   vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
205   vec_free (s->edit_groups);
206   vec_free (s->fixed_packet_data);
207   vec_free (s->fixed_packet_data_mask);
208   vec_free (s->name);
209   for (i = 0; i < vec_len (s->replay_packet_templates); i++)
210     vec_free (s->replay_packet_templates[i]);
211   vec_free (s->replay_packet_templates);
212   vec_free (s->replay_packet_timestamps);
213
214   {
215     pg_buffer_index_t *bi;
216     vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
217     vec_free (s->buffer_indices);
218   }
219 }
220
221 always_inline int
222 pg_stream_is_enabled (pg_stream_t * s)
223 {
224   return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
225 }
226
227 always_inline pg_edit_group_t *
228 pg_stream_get_group (pg_stream_t * s, u32 group_index)
229 {
230   return vec_elt_at_index (s->edit_groups, group_index);
231 }
232
233 always_inline void *
234 pg_create_edit_group (pg_stream_t * s,
235                       int n_edit_bytes, int n_packet_bytes, u32 * group_index)
236 {
237   pg_edit_group_t *g;
238   int n_edits;
239
240   vec_add2 (s->edit_groups, g, 1);
241   if (group_index)
242     *group_index = g - s->edit_groups;
243
244   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
245   n_edits = n_edit_bytes / sizeof (pg_edit_t);
246   vec_resize (g->edits, n_edits);
247
248   g->n_packet_bytes = n_packet_bytes;
249
250   return g->edits;
251 }
252
253 always_inline void *
254 pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
255               u32 group_index)
256 {
257   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
258   pg_edit_t *e;
259   int n_edits;
260   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
261   n_edits = n_edit_bytes / sizeof (pg_edit_t);
262   vec_add2 (g->edits, e, n_edits);
263   g->n_packet_bytes += n_packet_bytes;
264   return e;
265 }
266
267 always_inline void *
268 pg_get_edit_group (pg_stream_t * s, u32 group_index)
269 {
270   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
271   return g->edits;
272 }
273
274 /* Number of bytes for all groups >= given group. */
275 always_inline uword
276 pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
277 {
278   pg_edit_group_t *g;
279   uword n_bytes = 0;
280
281   for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
282     n_bytes += g->n_packet_bytes;
283   return n_bytes;
284 }
285
286 always_inline void
287 pg_free_edit_group (pg_stream_t * s)
288 {
289   uword i = vec_len (s->edit_groups) - 1;
290   pg_edit_group_t *g = pg_stream_get_group (s, i);
291
292   pg_edit_group_free (g);
293   clib_memset (g, 0, sizeof (g[0]));
294   _vec_len (s->edit_groups) = i;
295 }
296
297 typedef struct
298 {
299   /* TX lock */
300   volatile u32 *lockp;
301
302   /* VLIB interface indices. */
303   u32 hw_if_index, sw_if_index;
304
305   /* Identifies stream for this interface. */
306   u32 id;
307
308   u8 gso_enabled;
309   u32 gso_size;
310   pcap_main_t pcap_main;
311   char *pcap_file_name;
312 } pg_interface_t;
313
314 /* Per VLIB node data. */
315 typedef struct
316 {
317   /* Parser function indexed by node index. */
318   unformat_function_t *unformat_edit;
319 } pg_node_t;
320
321 typedef struct pg_main_t
322 {
323   /* Pool of streams. */
324   pg_stream_t *streams;
325
326   /* Bitmap indicating which streams are currently enabled. */
327   uword **enabled_streams;
328
329   /* Hash mapping name -> stream index. */
330   uword *stream_index_by_name;
331
332   /* Pool of interfaces. */
333   pg_interface_t *interfaces;
334   uword *if_index_by_if_id;
335
336   /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
337   u32 **replay_buffers_by_thread;
338
339   /* Per VLIB node information. */
340   pg_node_t *nodes;
341 } pg_main_t;
342
343 /* Global main structure. */
344 extern pg_main_t pg_main;
345
346 /* Global node. */
347 extern vlib_node_registration_t pg_input_node;
348
349 /* Buffer generator input, output node functions. */
350 vlib_node_function_t pg_input, pg_output;
351
352 /* Stream add/delete. */
353 void pg_stream_del (pg_main_t * pg, uword index);
354 void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
355 void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
356
357 /* Enable/disable stream. */
358 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
359                                int is_enable);
360
361 /* Find/create free packet-generator interface index. */
362 u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index,
363                              u8 gso_enabled, u32 gso_size);
364
365 always_inline pg_node_t *
366 pg_get_node (uword node_index)
367 {
368   pg_main_t *pg = &pg_main;
369   vec_validate (pg->nodes, node_index);
370   return pg->nodes + node_index;
371 }
372
373 void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
374                                           u32 group_index,
375                                           void *fixed_packet_data,
376                                           void *fixed_packet_data_mask);
377
378 void pg_enable_disable (u32 stream_index, int is_enable);
379
380 typedef struct
381 {
382   u32 hw_if_index;
383   u32 dev_instance;
384   u8 is_enabled;
385   char *pcap_file_name;
386   u32 count;
387 } pg_capture_args_t;
388
389 clib_error_t *pg_capture (pg_capture_args_t * a);
390
391 typedef struct
392 {
393   vlib_buffer_t buffer;
394   u32 buffer_index;
395 }
396 pg_output_trace_t;
397
398 #endif /* included_vlib_pg_h */
399
400 /*
401  * fd.io coding-style-patch-verification: ON
402  *
403  * Local Variables:
404  * eval: (c-set-style "gnu")
405  * End:
406  */