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