FD.io VPP  v16.09
Vector Packet Processing
stream.c
Go to the documentation of this file.
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_stream.c: packet generator streams
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 #include <vnet/vnet.h>
41 #include <vnet/pg/pg.h>
42 #include <vnet/ethernet/ethernet.h>
43 
44 /* Mark stream active or inactive. */
45 void pg_stream_enable_disable (pg_main_t * pg, pg_stream_t * s, int want_enabled)
46 {
47  vnet_main_t * vnm = vnet_get_main();
49 
50  want_enabled = want_enabled != 0;
51 
52  if (pg_stream_is_enabled (s) == want_enabled)
53  /* No change necessary. */
54  return;
55 
56  if (want_enabled)
57  s->n_packets_generated = 0;
58 
59  /* Toggle enabled flag. */
61 
62  ASSERT (! pool_is_free (pg->streams, s));
63 
64  pg->enabled_streams
65  = clib_bitmap_set (pg->enabled_streams, s - pg->streams, want_enabled);
66 
67  if (want_enabled)
68  {
71 
74  }
75 
77  pg_input_node.index,
79  ? VLIB_NODE_STATE_DISABLED
80  : VLIB_NODE_STATE_POLLING));
81 
82  s->packet_accumulator = 0;
83  s->time_last_generate = 0;
84 }
85 
86 static u8 * format_pg_interface_name (u8 * s, va_list * args)
87 {
88  pg_main_t * pg = &pg_main;
89  u32 if_index = va_arg (*args, u32);
90  pg_interface_t * pi;
91 
92  pi = pool_elt_at_index (pg->interfaces, if_index);
93  s = format (s, "pg%d", pi->id);
94 
95  return s;
96 }
97 
98 static clib_error_t *
100 {
101  u32 hw_flags = 0;
102 
105 
106  vnet_hw_interface_set_flags(vnm, hw_if_index, hw_flags);
107 
108  return 0;
109 }
110 
112  .name = "pg",
113  .tx_function = pg_output,
114  .format_device_name = format_pg_interface_name,
115  .admin_up_down_function = pg_interface_admin_up_down,
116 };
117 
119  u32 sw_if_index,
120  u32 l3_type,
121  void * dst_address,
122  void * rewrite,
123  uword max_rewrite_bytes)
124 {
125  u16 * h = rewrite;
126 
127  if (max_rewrite_bytes < sizeof (h[0]))
128  return 0;
129 
130  h[0] = clib_host_to_net_u16 (l3_type);
131  return sizeof (h[0]);
132 }
133 
134 VNET_HW_INTERFACE_CLASS (pg_interface_class,static) = {
135  .name = "Packet generator",
136  .set_rewrite = pg_set_rewrite,
137 };
138 
139 static u32
141 {
142  /* nothing for now */
143  return 0;
144 }
145 
147 {
148  vnet_main_t * vnm = vnet_get_main();
149  vlib_main_t * vm = vlib_get_main();
150  pg_interface_t * pi;
152  uword *p;
153  u32 i;
154 
155  p = hash_get (pg->if_index_by_if_id, if_id);
156 
157  if (p)
158  {
159  return p[0];
160  }
161  else
162  {
163  u8 hw_addr[6];
164  f64 now = vlib_time_now(vm);
165  u32 rnd;
166 
167  pool_get (pg->interfaces, pi);
168  i = pi - pg->interfaces;
169 
170  rnd = (u32) (now * 1e6);
171  rnd = random_u32 (&rnd);
172  clib_memcpy (hw_addr+2, &rnd, sizeof(rnd));
173  hw_addr[0] = 2;
174  hw_addr[1] = 0xfe;
175 
176  pi->id = if_id;
177  ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
179  hi = vnet_get_hw_interface (vnm, pi->hw_if_index);
180  pi->sw_if_index = hi->sw_if_index;
181 
182  hash_set (pg->if_index_by_if_id, if_id, i);
183  }
184 
185  return i;
186 }
187 
188 static void do_edit (pg_stream_t * stream,
189  pg_edit_group_t * g,
190  pg_edit_t * e,
191  uword want_commit)
192 {
193  u32 i, i0, i1, mask, n_bits_left;
194  u8 * v, * s, * m;
195 
196  i0 = e->lsb_bit_offset / BITS (u8);
197 
198  /* Make space for edit in value and mask. */
201 
202  if (e->type != PG_EDIT_FIXED)
203  {
204  switch (e->type)
205  {
206  case PG_EDIT_RANDOM:
207  case PG_EDIT_INCREMENT:
209  break;
210 
211  default:
212  break;
213  }
214 
215  if (want_commit)
216  {
218  vec_add1 (g->non_fixed_edits, e[0]);
219  }
220  return;
221  }
222 
223  s = g->fixed_packet_data;
224  m = g->fixed_packet_data_mask;
225 
226  n_bits_left = e->n_bits;
227  i0 = e->lsb_bit_offset / BITS (u8);
228  i1 = e->lsb_bit_offset % BITS (u8);
229 
230  v = e->values[PG_EDIT_LO];
231  i = pg_edit_n_alloc_bytes (e) - 1;
232 
233  /* Odd low order bits?. */
234  if (i1 != 0 && n_bits_left > 0)
235  {
236  u32 n = clib_min (n_bits_left, BITS (u8) - i1);
237 
238  mask = pow2_mask (n) << i1;
239 
240  ASSERT (i0 < vec_len (s));
241  ASSERT (i < vec_len (v));
242  ASSERT ((v[i] &~ mask) == 0);
243 
244  s[i0] |= v[i] & mask;
245  m[i0] |= mask;
246 
247  i0--;
248  i--;
249  n_bits_left -= n;
250  }
251 
252  /* Even bytes. */
253  while (n_bits_left >= 8)
254  {
255  ASSERT (i0 < vec_len (s));
256  ASSERT (i < vec_len (v));
257 
258  s[i0] = v[i];
259  m[i0] = ~0;
260 
261  i0--;
262  i--;
263  n_bits_left -= 8;
264  }
265 
266  /* Odd high order bits. */
267  if (n_bits_left > 0)
268  {
269  mask = pow2_mask (n_bits_left);
270 
271  ASSERT (i0 < vec_len (s));
272  ASSERT (i < vec_len (v));
273  ASSERT ((v[i] &~ mask) == 0);
274 
275  s[i0] |= v[i] & mask;
276  m[i0] |= mask;
277  }
278 
279  if (want_commit)
280  pg_edit_free (e);
281 }
282 
284  u32 group_index,
285  void * packet_data,
286  void * packet_data_mask)
287 {
288  pg_edit_group_t * g = pg_stream_get_group (s, group_index);
289  pg_edit_t * e;
290 
291  vec_foreach (e, g->edits)
292  do_edit (s, g, e, /* want_commit */ 0);
293 
294  clib_memcpy (packet_data, g->fixed_packet_data, vec_len (g->fixed_packet_data));
296 }
297 
299 {
300  pg_edit_group_t * g;
301  pg_edit_t * e;
302  word i;
303 
304  for (i = vec_len (s->edit_groups) - 1; i >= 0; i--)
305  {
306  g = vec_elt_at_index (s->edit_groups, i);
307  vec_foreach (e, g->edits)
308  do_edit (s, g, e, /* want_commit */ 1);
309 
310  /* All edits have either been performed or added to
311  g->non_fixed_edits. So, we can delete the vector. */
312  vec_free (g->edits);
313  }
314 
317  vec_foreach (g, s->edit_groups)
318  {
319  int i;
321 
322  /* Relocate and copy non-fixed edits from group to stream. */
325 
326  for (i = 0; i < vec_len (g->non_fixed_edits); i++)
328 
330  g->non_fixed_edits,
331  vec_len (g->non_fixed_edits));
333 
336  vec_len (g->fixed_packet_data));
339  vec_len (g->fixed_packet_data_mask));
340  }
341 }
342 
343 void pg_stream_add (pg_main_t * pg, pg_stream_t * s_init)
344 {
345  vlib_main_t * vm = pg->vlib_main;
346  pg_stream_t * s;
347  uword * p;
348 
349  if (! pg->stream_index_by_name)
351  = hash_create_vec (0, sizeof (s->name[0]), sizeof (uword));
352 
353  /* Delete any old stream with the same name. */
354  if (s_init->name
355  && (p = hash_get_mem (pg->stream_index_by_name, s_init->name)))
356  {
357  pg_stream_del (pg, p[0]);
358  }
359 
360  pool_get (pg->streams, s);
361  s[0] = s_init[0];
362 
363  /* Give it a name. */
364  if (! s->name)
365  s->name = format (0, "stream%d", s - pg->streams);
366  else
367  s->name = vec_dup (s->name);
368 
369  hash_set_mem (pg->stream_index_by_name, s->name, s - pg->streams);
370 
371  /* Get fixed part of buffer data. */
372  if (s->edit_groups)
374 
375  /* Determine packet size. */
376  switch (s->packet_size_edit_type)
377  {
378  case PG_EDIT_INCREMENT:
379  case PG_EDIT_RANDOM:
380  if (s->min_packet_bytes == s->max_packet_bytes)
382  break;
383 
384  default:
385  /* Get packet size from fixed edits. */
387  if (! s->replay_packet_templates)
389  break;
390  }
391 
393 
394  {
395  pg_buffer_index_t * bi;
396  int n;
397 
398  if (! s->buffer_bytes)
400 
402 
403  n = s->max_packet_bytes / s->buffer_bytes;
404  n += (s->max_packet_bytes % s->buffer_bytes) != 0;
405 
406  vec_resize (s->buffer_indices, n);
407 
408  vec_foreach (bi, s->buffer_indices)
410  "pg stream %d buffer #%d",
411  s - pg->streams,
412  1 + (bi - s->buffer_indices));
413  }
414 
415  /* Find an interface to use. */
417 
418  {
420  vlib_rx_or_tx_t rx_or_tx;
421 
422  vlib_foreach_rx_tx (rx_or_tx)
423  {
424  if (s->sw_if_index[rx_or_tx] == ~0)
425  s->sw_if_index[rx_or_tx] = pi->sw_if_index;
426  }
427  }
428 
429  /* Connect the graph. */
431 }
432 
433 void pg_stream_del (pg_main_t * pg, uword index)
434 {
435  vlib_main_t * vm = pg->vlib_main;
436  pg_stream_t * s;
437  pg_buffer_index_t * bi;
438 
439  s = pool_elt_at_index (pg->streams, index);
440 
441  pg_stream_enable_disable (pg, s, /* want_enabled */ 0);
443 
444  vec_foreach (bi, s->buffer_indices)
445  {
448  }
449 
450  pg_stream_free (s);
451  pool_put (pg->streams, s);
452 }
453 
u32 sw_if_index
Definition: pg.h:287
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
Definition: edit.h:63
u32 next_index
Definition: pg.h:145
static int pg_stream_is_enabled(pg_stream_t *s)
Definition: pg.h:212
vmrglw vmrglh hi
#define PG_EDIT_LO
Definition: edit.h:81
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_min(x, y)
Definition: clib.h:326
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:513
u8 * fixed_packet_data
Definition: pg.h:121
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
Definition: pg.h:302
static uword pg_set_rewrite(vnet_main_t *vnm, u32 sw_if_index, u32 l3_type, void *dst_address, void *rewrite, uword max_rewrite_bytes)
Definition: stream.c:118
pg_edit_group_t * edit_groups
Definition: pg.h:107
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
uword * stream_index_by_name
Definition: pg.h:313
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
VNET_DEVICE_CLASS(pg_dev_class)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
static clib_error_t * pg_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: stream.c:99
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
#define hash_set_mem(h, key, value)
Definition: hash.h:274
u64 last_increment_value
Definition: edit.h:85
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:203
pg_buffer_index_t * buffer_indices
Definition: pg.h:164
u32 hw_if_index
Definition: pg.h:287
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:273
pg_edit_type_t packet_size_edit_type
Definition: pg.h:109
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1061
VNET_HW_INTERFACE_CLASS(pg_interface_class, static)
u8 * fixed_packet_data_mask
Definition: pg.h:121
u32 start_byte_offset
Definition: pg.h:66
static pg_edit_group_t * pg_stream_get_group(pg_stream_t *s, u32 group_index)
Definition: pg.h:216
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
vlib_rx_or_tx_t
Definition: defs.h:44
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
vlib_node_registration_t pg_input_node
(constructor) VLIB_REGISTER_NODE (pg_input_node)
Definition: input.c:1736
static u8 * format_pg_interface_name(u8 *s, va_list *args)
Definition: stream.c:86
static uword pow2_mask(uword x)
Definition: clib.h:251
u8 * fixed_packet_data_mask
Definition: pg.h:63
static uword clib_bitmap_is_zero(uword *ai)
predicate function; is an entire bitmap empty?
Definition: bitmap.h:57
pg_edit_type_t type
Definition: edit.h:64
u8 * fixed_packet_data
Definition: pg.h:62
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
i32 lsb_bit_offset
Definition: edit.h:71
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:201
void pg_stream_del(pg_main_t *pg, uword index)
Definition: stream.c:433
#define PG_STREAM_FLAGS_IS_ENABLED
Definition: pg.h:102
uword * if_index_by_if_id
Definition: pg.h:317
u32 buffer_bytes
Definition: pg.h:125
static u32 pg_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: stream.c:140
u8 * values[2]
Definition: edit.h:80
f64 packet_accumulator
Definition: pg.h:162
#define hash_get(h, key)
Definition: hash.h:248
u32 last_increment_packet_size
Definition: pg.h:128
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
#define hash_unset_mem(h, key)
Definition: hash.h:280
u32 pg_if_index
Definition: pg.h:131
pg_edit_t * non_fixed_edits
Definition: pg.h:59
u8 * name
Definition: pg.h:97
static u64 pg_edit_get_value(pg_edit_t *e, int hi_or_lo)
Definition: edit.h:169
static void pg_stream_free(pg_stream_t *s)
Definition: pg.h:189
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
vlib_node_function_t pg_output
Definition: pg.h:330
u32 n_bits
Definition: edit.h:77
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
u32 min_packet_bytes
Definition: pg.h:112
u32 max_packet_bytes
Definition: pg.h:112
u32 pg_interface_add_or_get(pg_main_t *pg, uword if_id)
Definition: stream.c:146
#define clib_memcpy(a, b, c)
Definition: string.h:63
void pg_edit_group_get_fixed_packet_data(pg_stream_t *s, u32 group_index, void *packet_data, void *packet_data_mask)
Definition: stream.c:283
pg_edit_t * non_fixed_edits
Definition: pg.h:116
u8 ** replay_packet_templates
Definition: pg.h:166
static void perform_fixed_edits(pg_stream_t *s)
Definition: stream.c:298
pg_stream_t * streams
Definition: pg.h:307
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:415
#define ASSERT(truth)
vlib_main_t * vlib_main
Definition: pg.h:304
unsigned int u32
Definition: types.h:88
#define vlib_foreach_rx_tx(v)
Definition: defs.h:51
u32 free_list_index
Definition: pg.h:92
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
uword * enabled_streams
Definition: pg.h:310
void pg_stream_enable_disable(pg_main_t *pg, pg_stream_t *s, int want_enabled)
Definition: stream.c:45
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:181
void pg_stream_add(pg_main_t *pg, pg_stream_t *s_init)
Definition: stream.c:343
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:144
#define clib_fifo_free(f)
Definition: fifo.h:257
Definition: pg.h:95
pg_main_t pg_main
Definition: init.c:44
void vlib_buffer_delete_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: dpdk_buffer.c:434
u64 uword
Definition: types.h:112
static uword pg_edit_n_alloc_bytes(pg_edit_t *e)
Definition: edit.h:118
u32 node_index
Definition: pg.h:142
u32 sw_if_index[VLIB_N_RX_TX]
Definition: pg.h:139
unsigned short u16
Definition: types.h:57
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:633
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
u32 id
Definition: pg.h:290
unsigned char u8
Definition: types.h:56
u32 if_id
Definition: pg.h:147
pg_edit_t * edits
Definition: pg.h:56
#define hash_get_mem(h, key)
Definition: hash.h:268
static void do_edit(pg_stream_t *stream, pg_edit_group_t *g, pg_edit_t *e, uword want_commit)
Definition: stream.c:188
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u64 n_packets_generated
Definition: pg.h:150
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:521
static void pg_edit_free(pg_edit_t *e)
Definition: edit.h:89
vnet_device_class_t pg_dev_class
u32 flags
Definition: vhost-user.h:76
#define BITS(x)
Definition: clib.h:58
f64 time_last_generate
Definition: pg.h:160
pg_interface_t * interfaces
Definition: pg.h:316
u32 vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: dpdk_buffer.c:366
static u32 vlib_buffer_round_size(u32 size)
Definition: buffer_funcs.h:271
u32 flags
Definition: pg.h:99
u32 * buffer_fifo
Definition: pg.h:89