pg: add GSO support
[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   /* Last packet length if packet size edit type is increment. */
127   u32 last_increment_packet_size;
128
129   /* Index into main interface pool for this stream. */
130   u32 pg_if_index;
131
132   /* Interface used to mark packets for this stream.  May be different
133      than hw/sw index from pg main interface pool.  They will be
134      different if this stream is being used generate buffers as if
135      they were received on a non-pg interface.  For example, suppose you
136      are trying to test vlan code and you want to generate buffers that
137      appear to come from an ethernet interface. */
138   u32 sw_if_index[VLIB_N_RX_TX];
139
140   /* Node where stream's buffers get put. */
141   u32 node_index;
142
143   /* Worker thread index */
144   u32 worker_index;
145
146   /* Output next index to reach output node from stream input node. */
147   u32 next_index;
148
149   u32 if_id;
150
151   /* Number of packets currently generated. */
152   u64 n_packets_generated;
153
154   /* Stream is disabled when packet limit is reached.
155      Zero means no packet limit. */
156   u64 n_packets_limit;
157
158   /* Rate for this stream in packets/second.
159      Zero means unlimited rate. */
160   f64 rate_packets_per_second;
161
162   f64 time_last_generate;
163
164   f64 packet_accumulator;
165
166   pg_buffer_index_t *buffer_indices;
167
168   u8 **replay_packet_templates;
169   u64 *replay_packet_timestamps;
170   u32 current_replay_packet_index;
171 } pg_stream_t;
172
173 always_inline void
174 pg_buffer_index_free (pg_buffer_index_t * bi)
175 {
176   vec_free (bi->edits);
177   clib_fifo_free (bi->buffer_fifo);
178 }
179
180 always_inline void
181 pg_edit_group_free (pg_edit_group_t * g)
182 {
183   pg_edit_t *e;
184   vec_foreach (e, g->edits) pg_edit_free (e);
185   vec_free (g->edits);
186   vec_free (g->fixed_packet_data);
187   vec_free (g->fixed_packet_data_mask);
188 }
189
190 always_inline void
191 pg_stream_free (pg_stream_t * s)
192 {
193   int i;
194   pg_edit_group_t *g;
195   pg_edit_t *e;
196   vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
197   vec_free (s->non_fixed_edits);
198   vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
199   vec_free (s->edit_groups);
200   vec_free (s->fixed_packet_data);
201   vec_free (s->fixed_packet_data_mask);
202   vec_free (s->name);
203   for (i = 0; i < vec_len (s->replay_packet_templates); i++)
204     vec_free (s->replay_packet_templates[i]);
205   vec_free (s->replay_packet_templates);
206   vec_free (s->replay_packet_timestamps);
207
208   {
209     pg_buffer_index_t *bi;
210     vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
211     vec_free (s->buffer_indices);
212   }
213 }
214
215 always_inline int
216 pg_stream_is_enabled (pg_stream_t * s)
217 {
218   return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
219 }
220
221 always_inline pg_edit_group_t *
222 pg_stream_get_group (pg_stream_t * s, u32 group_index)
223 {
224   return vec_elt_at_index (s->edit_groups, group_index);
225 }
226
227 always_inline void *
228 pg_create_edit_group (pg_stream_t * s,
229                       int n_edit_bytes, int n_packet_bytes, u32 * group_index)
230 {
231   pg_edit_group_t *g;
232   int n_edits;
233
234   vec_add2 (s->edit_groups, g, 1);
235   if (group_index)
236     *group_index = g - s->edit_groups;
237
238   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
239   n_edits = n_edit_bytes / sizeof (pg_edit_t);
240   vec_resize (g->edits, n_edits);
241
242   g->n_packet_bytes = n_packet_bytes;
243
244   return g->edits;
245 }
246
247 always_inline void *
248 pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
249               u32 group_index)
250 {
251   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
252   pg_edit_t *e;
253   int n_edits;
254   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
255   n_edits = n_edit_bytes / sizeof (pg_edit_t);
256   vec_add2 (g->edits, e, n_edits);
257   g->n_packet_bytes += n_packet_bytes;
258   return e;
259 }
260
261 always_inline void *
262 pg_get_edit_group (pg_stream_t * s, u32 group_index)
263 {
264   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
265   return g->edits;
266 }
267
268 /* Number of bytes for all groups >= given group. */
269 always_inline uword
270 pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
271 {
272   pg_edit_group_t *g;
273   uword n_bytes = 0;
274
275   for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
276     n_bytes += g->n_packet_bytes;
277   return n_bytes;
278 }
279
280 always_inline void
281 pg_free_edit_group (pg_stream_t * s)
282 {
283   uword i = vec_len (s->edit_groups) - 1;
284   pg_edit_group_t *g = pg_stream_get_group (s, i);
285
286   pg_edit_group_free (g);
287   clib_memset (g, 0, sizeof (g[0]));
288   _vec_len (s->edit_groups) = i;
289 }
290
291 typedef struct
292 {
293   /* TX lock */
294   volatile u32 *lockp;
295
296   /* VLIB interface indices. */
297   u32 hw_if_index, sw_if_index;
298
299   /* Identifies stream for this interface. */
300   u32 id;
301
302   u8 gso_enabled;
303   u32 gso_size;
304   pcap_main_t pcap_main;
305   u8 *pcap_file_name;
306 } pg_interface_t;
307
308 /* Per VLIB node data. */
309 typedef struct
310 {
311   /* Parser function indexed by node index. */
312   unformat_function_t *unformat_edit;
313 } pg_node_t;
314
315 typedef struct pg_main_t
316 {
317   /* Pool of streams. */
318   pg_stream_t *streams;
319
320   /* Bitmap indicating which streams are currently enabled. */
321   uword **enabled_streams;
322
323   /* Hash mapping name -> stream index. */
324   uword *stream_index_by_name;
325
326   /* Pool of interfaces. */
327   pg_interface_t *interfaces;
328   uword *if_index_by_if_id;
329
330   /* Vector of buffer indices for use in pg_stream_fill_replay, per thread */
331   u32 **replay_buffers_by_thread;
332
333   /* Per VLIB node information. */
334   pg_node_t *nodes;
335 } pg_main_t;
336
337 /* Global main structure. */
338 extern pg_main_t pg_main;
339
340 /* Global node. */
341 extern vlib_node_registration_t pg_input_node;
342
343 /* Buffer generator input, output node functions. */
344 vlib_node_function_t pg_input, pg_output;
345
346 /* Stream add/delete. */
347 void pg_stream_del (pg_main_t * pg, uword index);
348 void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
349 void pg_stream_change (pg_main_t * pg, pg_stream_t * s);
350
351 /* Enable/disable stream. */
352 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
353                                int is_enable);
354
355 /* Find/create free packet-generator interface index. */
356 u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index,
357                              u8 gso_enabled, u32 gso_size);
358
359 always_inline pg_node_t *
360 pg_get_node (uword node_index)
361 {
362   pg_main_t *pg = &pg_main;
363   vec_validate (pg->nodes, node_index);
364   return pg->nodes + node_index;
365 }
366
367 void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
368                                           u32 group_index,
369                                           void *fixed_packet_data,
370                                           void *fixed_packet_data_mask);
371
372 void pg_enable_disable (u32 stream_index, int is_enable);
373
374 typedef struct
375 {
376   u32 hw_if_index;
377   u32 dev_instance;
378   u8 is_enabled;
379   u8 *pcap_file_name;
380   u32 count;
381 } pg_capture_args_t;
382
383 clib_error_t *pg_capture (pg_capture_args_t * a);
384
385 typedef struct
386 {
387   vlib_buffer_t buffer;
388   u32 buffer_index;
389 }
390 pg_output_trace_t;
391
392 #endif /* included_vlib_pg_h */
393
394 /*
395  * fd.io coding-style-patch-verification: ON
396  *
397  * Local Variables:
398  * eval: (c-set-style "gnu")
399  * End:
400  */