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