dpdk: Add support for Mellanox ConnectX-4 devices
[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 <vnet/unix/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   /* Buffer free list for this buffer index in stream. */
93   u32 free_list_index;
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 #define PG_STREAM_FLAGS_DISABLE_BUFFER_RECYCLE (1 << 1)
106
107   /* Edit groups are created by each protocol level (e.g. ethernet,
108      ip4, tcp, ...). */
109   pg_edit_group_t *edit_groups;
110
111   pg_edit_type_t packet_size_edit_type;
112
113   /* Min/max packet size. */
114   u32 min_packet_bytes, max_packet_bytes;
115
116   /* Vector of non-fixed edits for this stream.
117      All fixed edits are performed and placed into fixed_packet_data. */
118   pg_edit_t *non_fixed_edits;
119
120   /* Packet data with all fixed edits performed.
121      All packets in stream are initialized according with this data.
122      Mask specifies which bits of packet data are covered by fixed edits. */
123   u8 *fixed_packet_data, *fixed_packet_data_mask;
124
125   /* Size to use for buffers.  0 means use buffers big enough
126      for max_packet_bytes. */
127   u32 buffer_bytes;
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   /* Rate for this stream in packets/second.
162      Zero means unlimited rate. */
163   f64 rate_packets_per_second;
164
165   f64 time_last_generate;
166
167   f64 packet_accumulator;
168
169   pg_buffer_index_t *buffer_indices;
170
171   u8 **replay_packet_templates;
172   u32 current_replay_packet_index;
173 } pg_stream_t;
174
175 always_inline void
176 pg_buffer_index_free (pg_buffer_index_t * bi)
177 {
178   vec_free (bi->edits);
179   clib_fifo_free (bi->buffer_fifo);
180 }
181
182 always_inline void
183 pg_edit_group_free (pg_edit_group_t * g)
184 {
185   pg_edit_t *e;
186   vec_foreach (e, g->edits) pg_edit_free (e);
187   vec_free (g->edits);
188   vec_free (g->fixed_packet_data);
189   vec_free (g->fixed_packet_data_mask);
190 }
191
192 always_inline void
193 pg_stream_free (pg_stream_t * s)
194 {
195   pg_edit_group_t *g;
196   pg_edit_t *e;
197   vec_foreach (e, s->non_fixed_edits) pg_edit_free (e);
198   vec_free (s->non_fixed_edits);
199   vec_foreach (g, s->edit_groups) pg_edit_group_free (g);
200   vec_free (s->edit_groups);
201   vec_free (s->fixed_packet_data);
202   vec_free (s->fixed_packet_data_mask);
203   vec_free (s->name);
204
205   {
206     pg_buffer_index_t *bi;
207     vec_foreach (bi, s->buffer_indices) pg_buffer_index_free (bi);
208     vec_free (s->buffer_indices);
209   }
210 }
211
212 always_inline int
213 pg_stream_is_enabled (pg_stream_t * s)
214 {
215   return (s->flags & PG_STREAM_FLAGS_IS_ENABLED) != 0;
216 }
217
218 always_inline pg_edit_group_t *
219 pg_stream_get_group (pg_stream_t * s, u32 group_index)
220 {
221   return vec_elt_at_index (s->edit_groups, group_index);
222 }
223
224 always_inline void *
225 pg_create_edit_group (pg_stream_t * s,
226                       int n_edit_bytes, int n_packet_bytes, u32 * group_index)
227 {
228   pg_edit_group_t *g;
229   int n_edits;
230
231   vec_add2 (s->edit_groups, g, 1);
232   if (group_index)
233     *group_index = g - s->edit_groups;
234
235   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
236   n_edits = n_edit_bytes / sizeof (pg_edit_t);
237   vec_resize (g->edits, n_edits);
238
239   g->n_packet_bytes = n_packet_bytes;
240
241   return g->edits;
242 }
243
244 always_inline void *
245 pg_add_edits (pg_stream_t * s, int n_edit_bytes, int n_packet_bytes,
246               u32 group_index)
247 {
248   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
249   pg_edit_t *e;
250   int n_edits;
251   ASSERT (n_edit_bytes % sizeof (pg_edit_t) == 0);
252   n_edits = n_edit_bytes / sizeof (pg_edit_t);
253   vec_add2 (g->edits, e, n_edits);
254   g->n_packet_bytes += n_packet_bytes;
255   return e;
256 }
257
258 always_inline void *
259 pg_get_edit_group (pg_stream_t * s, u32 group_index)
260 {
261   pg_edit_group_t *g = pg_stream_get_group (s, group_index);
262   return g->edits;
263 }
264
265 /* Number of bytes for all groups >= given group. */
266 always_inline uword
267 pg_edit_group_n_bytes (pg_stream_t * s, u32 group_index)
268 {
269   pg_edit_group_t *g;
270   uword n_bytes = 0;
271
272   for (g = s->edit_groups + group_index; g < vec_end (s->edit_groups); g++)
273     n_bytes += g->n_packet_bytes;
274   return n_bytes;
275 }
276
277 always_inline void
278 pg_free_edit_group (pg_stream_t * s)
279 {
280   uword i = vec_len (s->edit_groups) - 1;
281   pg_edit_group_t *g = pg_stream_get_group (s, i);
282
283   pg_edit_group_free (g);
284   memset (g, 0, sizeof (g[0]));
285   _vec_len (s->edit_groups) = i;
286 }
287
288 typedef struct
289 {
290   /* TX lock */
291   volatile u32 *lockp;
292
293   /* VLIB interface indices. */
294   u32 hw_if_index, sw_if_index;
295
296   /* Identifies stream for this interface. */
297   u32 id;
298
299   pcap_main_t pcap_main;
300   u8 *pcap_file_name;
301 } pg_interface_t;
302
303 /* Per VLIB node data. */
304 typedef struct
305 {
306   /* Parser function indexed by node index. */
307   unformat_function_t *unformat_edit;
308 } pg_node_t;
309
310 typedef struct pg_main_t
311 {
312   /* Pool of streams. */
313   pg_stream_t *streams;
314
315   /* Bitmap indicating which streams are currently enabled. */
316   uword **enabled_streams;
317
318   /* Hash mapping name -> stream index. */
319   uword *stream_index_by_name;
320
321   /* Pool of interfaces. */
322   pg_interface_t *interfaces;
323   uword *if_index_by_if_id;
324
325   /* Per VLIB node information. */
326   pg_node_t *nodes;
327 } pg_main_t;
328
329 /* Global main structure. */
330 extern pg_main_t pg_main;
331
332 /* Global node. */
333 extern vlib_node_registration_t pg_input_node;
334
335 /* Buffer generator input, output node functions. */
336 vlib_node_function_t pg_input, pg_output;
337
338 /* Stream add/delete. */
339 void pg_stream_del (pg_main_t * pg, uword index);
340 void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init);
341
342 /* Enable/disable stream. */
343 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s,
344                                int is_enable);
345
346 /* Find/create free packet-generator interface index. */
347 u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index);
348
349 always_inline pg_node_t *
350 pg_get_node (uword node_index)
351 {
352   pg_main_t *pg = &pg_main;
353   vec_validate (pg->nodes, node_index);
354   return pg->nodes + node_index;
355 }
356
357 void pg_edit_group_get_fixed_packet_data (pg_stream_t * s,
358                                           u32 group_index,
359                                           void *fixed_packet_data,
360                                           void *fixed_packet_data_mask);
361
362 void pg_enable_disable (u32 stream_index, int is_enable);
363
364 typedef struct
365 {
366   u32 hw_if_index;
367   u32 dev_instance;
368   u8 is_enabled;
369   u8 *pcap_file_name;
370   u32 count;
371 } pg_capture_args_t;
372
373 clib_error_t *pg_capture (pg_capture_args_t * a);
374
375 #endif /* included_vlib_pg_h */
376
377 /*
378  * fd.io coding-style-patch-verification: ON
379  *
380  * Local Variables:
381  * eval: (c-set-style "gnu")
382  * End:
383  */