FD.io VPP  v16.06
Vector Packet Processing
cli.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 #include <vnet/vnet.h>
16 #include <vppinfra/vec.h>
17 #include <vppinfra/error.h>
18 #include <vppinfra/format.h>
19 #include <vppinfra/xxhash.h>
20 
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/devices/dpdk/dpdk.h>
24 #include <vnet/mpls-gre/packet.h>
25 
26 #include "dpdk_priv.h"
27 
28 static clib_error_t *
30  unformat_input_t * input,
31  vlib_cli_command_t * cmd)
32 {
33  dpdk_main_t * dm = &dpdk_main;
34  u8 * filename;
35  u32 max;
36  int matched = 0;
37  clib_error_t * error = 0;
38 
40  {
41  if (unformat (input, "on"))
42  {
43  if (dm->tx_pcap_enable == 0)
44  {
45  if (dm->pcap_filename == 0)
46  dm->pcap_filename = format (0, "/tmp/vpe.pcap%c", 0);
47 
48  memset (&dm->pcap_main, 0, sizeof (dm->pcap_main));
49  dm->pcap_main.file_name = (char *) dm->pcap_filename;
51  if (dm->pcap_pkts_to_capture)
53 
54  dm->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
55  dm->tx_pcap_enable = 1;
56  matched = 1;
57  vlib_cli_output (vm, "pcap tx capture on...");
58  }
59  else
60  {
61  vlib_cli_output (vm, "pcap tx capture already on...");
62  }
63  matched = 1;
64  }
65  else if (unformat (input, "off"))
66  {
67  if (dm->tx_pcap_enable)
68  {
69  vlib_cli_output (vm, "captured %d pkts...",
72  {
75  error = pcap_write (&dm->pcap_main);
76  if (error)
77  clib_error_report (error);
78  else
79  vlib_cli_output (vm, "saved to %s...", dm->pcap_filename);
80  }
81  }
82  else
83  {
84  vlib_cli_output (vm, "pcap tx capture already off...");
85  }
86 
87  dm->tx_pcap_enable = 0;
88  matched = 1;
89  }
90  else if (unformat (input, "max %d", &max))
91  {
92  dm->pcap_pkts_to_capture = max;
93  matched = 1;
94  }
95 
96  else if (unformat (input, "intfc %U",
98  &dm->pcap_sw_if_index))
99  matched = 1;
100  else if (unformat (input, "intfc any"))
101  {
102  dm->pcap_sw_if_index = 0;
103  matched = 1;
104  }
105  else if (unformat (input, "file %s", &filename))
106  {
107  u8 * chroot_filename;
108  /* Brain-police user path input */
109  if (strstr((char *)filename, "..") || index((char *)filename, '/'))
110  {
111  vlib_cli_output (vm, "illegal characters in filename '%s'",
112  filename);
113  continue;
114  }
115 
116  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
117  vec_free (filename);
118 
119  if (dm->pcap_filename)
120  vec_free (dm->pcap_filename);
121  vec_add1 (filename, 0);
122  dm->pcap_filename = chroot_filename;
123  matched = 1;
124  }
125  else if (unformat (input, "status"))
126  {
127  if (dm->tx_pcap_enable == 0)
128  {
129  vlib_cli_output (vm, "pcap tx capture is off...");
130  continue;
131  }
132 
133  vlib_cli_output (vm, "pcap tx capture: %d of %d pkts...",
136  matched = 1;
137  }
138 
139  else
140  break;
141  }
142 
143  if (matched == 0)
144  return clib_error_return (0, "unknown input `%U'",
145  format_unformat_error, input);
146 
147  return 0;
148 }
149 
150 VLIB_CLI_COMMAND (pcap_trace_command, static) = {
151  .path = "pcap tx trace",
152  .short_help =
153  "pcap tx trace on off max <nn> intfc <intfc> file <name> status",
154  .function = pcap_trace_command_fn,
155 };
156 
157 
158 static clib_error_t *
160  vlib_cli_command_t * cmd)
161 {
162  struct rte_mempool * rmp;
163  int i;
164 
165  for(i = 0; i < vec_len(vm->buffer_main->pktmbuf_pools); i++)
166  {
167  rmp = vm->buffer_main->pktmbuf_pools[i];
168  if (rmp)
169  {
170  unsigned count = rte_mempool_count(rmp);
171  unsigned free_count = rte_mempool_free_count(rmp);
172 
173  vlib_cli_output(vm, "name=\"%s\" available = %7d allocated = %7d total = %7d\n",
174  rmp->name, (u32)count, (u32)free_count,
175  (u32)(count+free_count));
176  }
177  else
178  {
179  vlib_cli_output(vm, "rte_mempool is NULL (!)\n");
180  }
181  }
182  return 0;
183 }
184 
185 VLIB_CLI_COMMAND (cmd_show_dpdk_bufferr,static) = {
186  .path = "show dpdk buffer",
187  .short_help = "show dpdk buffer state",
188  .function = show_dpdk_buffer,
189  .is_mp_safe = 1,
190 };
191 
192 static clib_error_t *
194  vlib_cli_command_t * cmd)
195 {
196  static u32 * allocated_buffers;
197  u32 n_alloc = 0;
198  u32 n_free = 0;
199  u32 first, actual_alloc;
200 
202  {
203  if (unformat (input, "allocate %d", &n_alloc))
204  ;
205  else if (unformat (input, "free %d", &n_free))
206  ;
207  else
208  break;
209  }
210 
211  if (n_free)
212  {
213  if (vec_len (allocated_buffers) < n_free)
214  return clib_error_return (0, "Can't free %d, only %d allocated",
215  n_free, vec_len (allocated_buffers));
216 
217  first = vec_len(allocated_buffers) - n_free;
218  vlib_buffer_free (vm, allocated_buffers + first, n_free);
219  _vec_len (allocated_buffers) = first;
220  }
221  if (n_alloc)
222  {
223  first = vec_len (allocated_buffers);
224  vec_validate (allocated_buffers,
225  vec_len (allocated_buffers) + n_alloc - 1);
226 
227  actual_alloc = vlib_buffer_alloc (vm, allocated_buffers + first,
228  n_alloc);
229  _vec_len (allocated_buffers) = first + actual_alloc;
230 
231  if (actual_alloc < n_alloc)
232  vlib_cli_output (vm, "WARNING: only allocated %d buffers",
233  actual_alloc);
234  }
235 
236  vlib_cli_output (vm, "Currently %d buffers allocated",
237  vec_len (allocated_buffers));
238 
239  if (allocated_buffers && vec_len(allocated_buffers) == 0)
240  vec_free(allocated_buffers);
241 
242  return 0;
243 }
244 
245 VLIB_CLI_COMMAND (cmd_test_dpdk_buffer,static) = {
246  .path = "test dpdk buffer",
247  .short_help = "test dpdk buffer [allocate <nn>][free <nn>]",
248  .function = test_dpdk_buffer,
249  .is_mp_safe = 1,
250 };
251 
252 static void
254 {
255  vlib_cli_output(vm,
256  "device_index %d\n"
257  " last_burst_sz %d\n"
258  " max_burst_sz %d\n"
259  " full_frames_cnt %u\n"
260  " consec_full_frames_cnt %u\n"
261  " congestion_cnt %d\n"
262  " last_poll_time %llu\n"
263  " max_poll_delay %llu\n"
264  " discard_cnt %u\n"
265  " total_packet_cnt %u\n",
266  xd->device_index,
276 
277  u32 device_queue_sz = rte_eth_rx_queue_count(xd->device_index,
278  0 /* queue_id */);
279  vlib_cli_output(vm,
280  " device_queue_sz %u\n",
281  device_queue_sz);
282 }
283 
284 
285 /*
286  * Trigger threads to grab frame queue trace data
287  */
288 static clib_error_t *
290  vlib_cli_command_t *cmd)
291 {
292  clib_error_t * error = NULL;
293  frame_queue_trace_t *fqt;
295  u32 num_fq;
296  u32 fqix;
297  u32 enable = 0;
298 
299  if (unformat(input, "on")) {
300  enable = 1;
301  } else if (unformat(input, "off")) {
302  enable = 0;
303  } else {
304  return clib_error_return(0, "expecting on or off");
305  }
306 
307  num_fq = vec_len(vlib_frame_queues);
308  if (num_fq == 0)
309  {
310  vlib_cli_output(vm, "No frame queues exist\n");
311  return error;
312  }
313 
314  // Allocate storage for trace if necessary
317 
318  for (fqix=0; fqix<num_fq; fqix++) {
319  fqt = &dpdk_main.frame_queue_traces[fqix];
320  fqh = &dpdk_main.frame_queue_histogram[fqix];
321 
322  memset(fqt->n_vectors, 0xff, sizeof(fqt->n_vectors));
323  fqt->written = 0;
324  memset(fqh, 0, sizeof(*fqh));
325  vlib_frame_queues[fqix]->trace = enable;
326  }
327  return error;
328 }
329 
330 VLIB_CLI_COMMAND (cmd_trace_frame_queue,static) = {
331  .path = "trace frame-queue",
332  .short_help = "trace frame-queue (on|off)",
333  .function = trace_frame_queue,
334  .is_mp_safe = 1,
335 };
336 
337 
338 /*
339  * Adding two counters and compute percent of total
340  * Round up, e.g. 0.000001 => 1%
341  */
342 static u32
343 compute_percent (u64 *two_counters, u64 total)
344 {
345  if (total == 0)
346  {
347  return 0;
348  }
349  else
350  {
351  return (((two_counters[0] + two_counters[1]) * 100) + (total-1)) / total;
352  }
353 }
354 
355 /*
356  * Display frame queue trace data gathered by threads.
357  */
358 static clib_error_t *
360  u32 histogram)
361 {
362  clib_error_t * error = NULL;
363  frame_queue_trace_t *fqt;
365  u32 num_fq;
366  u32 fqix;
367 
369  if (num_fq == 0)
370  {
371  vlib_cli_output(vm, "No trace data for frame queues\n");
372  return error;
373  }
374 
375  if (histogram)
376  {
377  vlib_cli_output(vm, "0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 "
378  "16-17 18-19 20-21 22-23 24-25 26-27 28-29 30-31\n");
379  }
380 
381  for (fqix=0; fqix<num_fq; fqix++) {
382  fqt = &(dpdk_main.frame_queue_traces[fqix]);
383 
384  vlib_cli_output(vm, "Thread %d %v\n", fqix, vlib_worker_threads[fqix].name);
385 
386  if (fqt->written == 0)
387  {
388  vlib_cli_output(vm, " no trace data\n");
389  continue;
390  }
391 
392  if (histogram)
393  {
394  fqh = &(dpdk_main.frame_queue_histogram[fqix]);
395  u32 nelt;
396  u64 total = 0;
397 
398  for (nelt=0; nelt<MAX_NELTS; nelt++) {
399  total += fqh->count[nelt];
400  }
401 
402  /*
403  * Print in pairs to condense the output.
404  * Allow entries with 0 counts to be clearly identified, by rounding up.
405  * Any non-zero value will be displayed as at least one percent. This
406  * also means the sum of percentages can be > 100, but that is fine. The
407  * histogram is counted from the last time "trace frame on" was issued.
408  */
409  vlib_cli_output(vm,
410  "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% "
411  "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%%\n",
412  compute_percent(&fqh->count[ 0], total),
413  compute_percent(&fqh->count[ 2], total),
414  compute_percent(&fqh->count[ 4], total),
415  compute_percent(&fqh->count[ 6], total),
416  compute_percent(&fqh->count[ 8], total),
417  compute_percent(&fqh->count[10], total),
418  compute_percent(&fqh->count[12], total),
419  compute_percent(&fqh->count[14], total),
420  compute_percent(&fqh->count[16], total),
421  compute_percent(&fqh->count[18], total),
422  compute_percent(&fqh->count[20], total),
423  compute_percent(&fqh->count[22], total),
424  compute_percent(&fqh->count[24], total),
425  compute_percent(&fqh->count[26], total),
426  compute_percent(&fqh->count[28], total),
427  compute_percent(&fqh->count[30], total));
428  }
429  else
430  {
431  vlib_cli_output(vm, " vector-threshold %d ring size %d in use %d\n",
432  fqt->threshold, fqt->nelts, fqt->n_in_use);
433  vlib_cli_output(vm, " head %12d head_hint %12d tail %12d\n",
434  fqt->head, fqt->head_hint, fqt->tail);
435  vlib_cli_output(vm, " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
436  fqt->n_vectors[0], fqt->n_vectors[1], fqt->n_vectors[2], fqt->n_vectors[3],
437  fqt->n_vectors[4], fqt->n_vectors[5], fqt->n_vectors[6], fqt->n_vectors[7],
438  fqt->n_vectors[8], fqt->n_vectors[9], fqt->n_vectors[10], fqt->n_vectors[11],
439  fqt->n_vectors[12], fqt->n_vectors[13], fqt->n_vectors[14], fqt->n_vectors[15]);
440 
441  if (fqt->nelts > 16)
442  {
443  vlib_cli_output(vm, " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
444  fqt->n_vectors[16], fqt->n_vectors[17], fqt->n_vectors[18], fqt->n_vectors[19],
445  fqt->n_vectors[20], fqt->n_vectors[21], fqt->n_vectors[22], fqt->n_vectors[23],
446  fqt->n_vectors[24], fqt->n_vectors[25], fqt->n_vectors[26], fqt->n_vectors[27],
447  fqt->n_vectors[28], fqt->n_vectors[29], fqt->n_vectors[30], fqt->n_vectors[31]);
448  }
449  }
450 
451  }
452  return error;
453 }
454 
455 static clib_error_t *
457  vlib_cli_command_t *cmd)
458 {
459  return show_frame_queue_internal (vm, 0);
460 }
461 
462 static clib_error_t *
464  vlib_cli_command_t *cmd)
465 {
466  return show_frame_queue_internal (vm, 1);
467 }
468 
469 VLIB_CLI_COMMAND (cmd_show_frame_queue_trace,static) = {
470  .path = "show frame-queue",
471  .short_help = "show frame-queue trace",
472  .function = show_frame_queue_trace,
473 };
474 
475 VLIB_CLI_COMMAND (cmd_show_frame_queue_histogram,static) = {
476  .path = "show frame-queue histogram",
477  .short_help = "show frame-queue histogram",
478  .function = show_frame_queue_histogram,
479 };
480 
481 
482 /*
483  * Modify the number of elements on the frame_queues
484  */
485 static clib_error_t *
487  vlib_cli_command_t *cmd)
488 {
489  clib_error_t * error = NULL;
490  u32 num_fq;
491  u32 fqix;
492  u32 nelts = 0;
493 
494  unformat(input, "%d", &nelts);
495  if ((nelts != 4) && (nelts != 8) && (nelts != 16) && (nelts != 32)) {
496  return clib_error_return(0, "expecting 4,8,16,32");
497  }
498 
499  num_fq = vec_len(vlib_frame_queues);
500  if (num_fq == 0)
501  {
502  vlib_cli_output(vm, "No frame queues exist\n");
503  return error;
504  }
505 
506  for (fqix=0; fqix<num_fq; fqix++) {
507  vlib_frame_queues[fqix]->nelts = nelts;
508  }
509 
510  return error;
511 }
512 
513 VLIB_CLI_COMMAND (cmd_test_frame_queue_nelts,static) = {
514  .path = "test frame-queue nelts",
515  .short_help = "test frame-queue nelts (4,8,16,32)",
516  .function = test_frame_queue_nelts,
517 };
518 
519 
520 /*
521  * Modify the max number of packets pulled off the frame queues
522  */
523 static clib_error_t *
525  vlib_cli_command_t *cmd)
526 {
527  clib_error_t * error = NULL;
528  u32 num_fq;
529  u32 fqix;
530  u32 threshold = 0;
531 
532  if (unformat(input, "%d", &threshold)) {
533  } else {
534  vlib_cli_output(vm, "expecting threshold value\n");
535  return error;
536  }
537 
538  if (threshold == 0)
539  threshold = ~0;
540 
541  num_fq = vec_len(vlib_frame_queues);
542  if (num_fq == 0)
543  {
544  vlib_cli_output(vm, "No frame queues exist\n");
545  return error;
546  }
547 
548  for (fqix=0; fqix<num_fq; fqix++) {
549  vlib_frame_queues[fqix]->vector_threshold = threshold;
550  }
551 
552  return error;
553 }
554 
555 VLIB_CLI_COMMAND (cmd_test_frame_queue_threshold,static) = {
556  .path = "test frame-queue threshold",
557  .short_help = "test frame-queue threshold N (0=no limit)",
558  .function = test_frame_queue_threshold,
559 };
560 
561 static void
563 {
565  dpdk_main_t * dm = &dpdk_main;
566 
567  vlib_cli_output(vm,
568  "dpdk: (0x%04x) enabled:%d monitor:%d drop_all:%d\n"
569  " dpdk_queue_hi_thresh %d\n"
570  " consec_full_frames_hi_thresh %d\n"
571  "---------\n"
572  "worker: (0x%04x) enabled:%d monitor:%d\n"
573  " worker_queue_hi_thresh %d\n",
574  dm->efd.enabled,
575  ((dm->efd.enabled & DPDK_EFD_DISCARD_ENABLED) ? 1:0),
576  ((dm->efd.enabled & DPDK_EFD_MONITOR_ENABLED) ? 1:0),
577  ((dm->efd.enabled & DPDK_EFD_DROPALL_ENABLED) ? 1:0),
578  dm->efd.queue_hi_thresh,
580  tm->efd.enabled,
581  ((tm->efd.enabled & VLIB_EFD_DISCARD_ENABLED) ? 1:0),
582  ((dm->efd.enabled & VLIB_EFD_MONITOR_ENABLED) ? 1:0),
583  tm->efd.queue_hi_thresh);
584  vlib_cli_output(vm,
585  "---------\n"
586  "ip_prec_bitmap 0x%02x\n"
587  "mpls_exp_bitmap 0x%02x\n"
588  "vlan_cos_bitmap 0x%02x\n",
589  tm->efd.ip_prec_bitmap,
590  tm->efd.mpls_exp_bitmap,
591  tm->efd.vlan_cos_bitmap);
592 }
593 
594 static clib_error_t *
596  unformat_input_t * input,
597  vlib_cli_command_t * cmd)
598 {
599 
600  if (unformat(input, "config")) {
601  show_efd_config(vm);
602  } else if (unformat(input, "dpdk")) {
603  dpdk_main_t * dm = &dpdk_main;
604  dpdk_device_t * xd;
605  u32 device_id = ~0;
606 
607  unformat(input, "device %d", &device_id);
608  vec_foreach (xd, dm->devices) {
609  if ((xd->device_index == device_id) || (device_id == ~0)) {
610  show_dpdk_device_stats(vm, xd);
611  }
612  }
613  } else if (unformat(input, "worker")) {
615  vlib_frame_queue_t *fq;
617  int thread_id;
618  u32 num_workers = 0;
619  u32 first_worker_index = 0;
620  uword * p;
621 
622  p = hash_get_mem (tm->thread_registrations_by_name, "workers");
623  ASSERT (p);
624  tr = (vlib_thread_registration_t *) p[0];
625  if (tr)
626  {
627  num_workers = tr->count;
628  first_worker_index = tr->first_index;
629  }
630 
631  vlib_cli_output(vm,
632  "num_workers %d\n"
633  "first_worker_index %d\n"
634  "vlib_frame_queues[%d]:\n",
635  num_workers,
636  first_worker_index,
637  tm->n_vlib_mains);
638 
639  for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++) {
640  fq = vlib_frame_queues[thread_id];
641  if (fq) {
642  vlib_cli_output(vm,
643  "%2d: frames_queued %u\n"
644  " frames_queued_hint %u\n"
645  " enqueue_full_events %u\n"
646  " enqueue_efd_discards %u\n",
647  thread_id,
648  (fq->tail - fq->head),
649  (fq->tail - fq->head_hint),
652  }
653  }
654  } else if (unformat(input, "help")) {
655  vlib_cli_output(vm, "Usage: show efd config | "
656  "dpdk [device <id>] | worker\n");
657  } else {
658  show_efd_config(vm);
659  }
660 
661  return 0;
662 }
663 
664 VLIB_CLI_COMMAND (show_efd_command, static) = {
665  .path = "show efd",
666  .short_help = "Show efd [device <id>] | [config]",
667  .function = show_efd,
668 };
669 
670 static clib_error_t *
672  unformat_input_t * input,
673  vlib_cli_command_t * cmd)
674 {
675  dpdk_main_t * dm = &dpdk_main;
676  dpdk_device_t * xd;
678  vlib_frame_queue_t *fq;
679  int thread_id;
680 
681  vec_foreach (xd, dm->devices) {
682  xd->efd_agent.last_burst_sz = 0;
683  xd->efd_agent.max_burst_sz = 0;
684  xd->efd_agent.full_frames_cnt = 0;
686  xd->efd_agent.congestion_cnt = 0;
687  xd->efd_agent.last_poll_time = 0;
688  xd->efd_agent.max_poll_delay = 0;
689  xd->efd_agent.discard_cnt = 0;
690  xd->efd_agent.total_packet_cnt = 0;
691  }
692 
693  for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++) {
694  fq = vlib_frame_queues[thread_id];
695  if (fq) {
696  fq->enqueue_full_events = 0;
697  fq->enqueue_efd_discards = 0;
698  }
699  }
700 
701  return 0;
702 }
703 
704 VLIB_CLI_COMMAND (clear_efd_command,static) = {
705  .path = "clear efd",
706  .short_help = "Clear early-fast-discard counters",
707  .function = clear_efd,
708 };
709 
710 static clib_error_t *
712  vlib_cli_command_t *cmd,
713  char *prec_type, u8 *prec_bitmap)
714 {
715  clib_error_t * error = NULL;
716  u8 op = 0;
717  u8 prec = 0;
718 
719  if (unformat(input, "ge")) {
721  } else if (unformat(input, "lt")) {
723  } else if (unformat(input, "help")) {
724  vlib_cli_output(vm,
725  "enter operation [ge | lt] and precedence <0-7>)");
726  return (error);
727  } else {
728  return clib_error_return(0, "unknown input `%U'",
729  format_unformat_error, input);
730  }
731 
732  if (unformat (input, "%u", &prec)) {
733  if (prec > 7) {
734  return clib_error_return(0, "precedence %d is out of range <0-7>",
735  prec);
736  }
737  } else {
738  return clib_error_return(0, "unknown input `%U'",
739  format_unformat_error, input);
740  }
741 
742  set_efd_bitmap(prec_bitmap, prec, op);
743 
744  vlib_cli_output(vm,
745  "EFD will be set for %s precedence %s%u%s.",
746  prec_type,
747  (op == EFD_OPERATION_LESS_THAN) ? "less than " : "",
748  prec,
749  (op == EFD_OPERATION_GREATER_OR_EQUAL) ? " and greater" : "");
750 
751  return (error);
752 }
753 
754 
755 static clib_error_t *
757  vlib_cli_command_t *cmd)
758 {
759  dpdk_main_t * dm = &dpdk_main;
761  clib_error_t * error = NULL;
762 
763  if (unformat(input, "enable")) {
764  if (unformat(input, "dpdk")) {
766  } else if (unformat(input, "worker")) {
768  } else if (unformat(input, "monitor")) {
771  } else if (unformat(input, "drop_all")) {
773  } else if (unformat(input, "default")) {
778  } else {
779  return clib_error_return(0, "Usage: set efd enable [dpdk | "
780  "worker | monitor | drop_all | default]");
781  }
782  } else if (unformat(input, "disable")) {
783  if (unformat(input, "dpdk")) {
785  } else if (unformat(input, "worker")) {
787  } else if (unformat(input, "monitor")) {
790  } else if (unformat(input, "drop_all")) {
792  } else if (unformat(input, "all")) {
793  dm->efd.enabled = 0;
794  tm->efd.enabled = 0;
795  } else {
796  return clib_error_return(0, "Usage: set efd disable [dpdk | "
797  "worker | monitor | drop_all | all]");
798  }
799  } else if (unformat(input, "worker_queue_hi_thresh")) {
800  u32 mark;
801  if (unformat (input, "%u", &mark)) {
802  tm->efd.queue_hi_thresh = mark;
803  } else {
804  return clib_error_return(0, "unknown input `%U'",
805  format_unformat_error, input);
806  }
807  } else if (unformat(input, "dpdk_device_hi_thresh")) {
808  u32 thresh;
809  if (unformat (input, "%u", &thresh)) {
810  dm->efd.queue_hi_thresh = thresh;
811  } else {
812  return clib_error_return(0, "unknown input `%U'",
813  format_unformat_error, input);
814  }
815  } else if (unformat(input, "consec_full_frames_hi_thresh")) {
816  u32 thresh;
817  if (unformat (input, "%u", &thresh)) {
818  dm->efd.consec_full_frames_hi_thresh = thresh;
819  } else {
820  return clib_error_return(0, "unknown input `%U'",
821  format_unformat_error, input);
822  }
823  } else if (unformat(input, "ip-prec")) {
824  return (parse_op_and_prec(vm, input, cmd,
825  "ip", &tm->efd.ip_prec_bitmap));
826  } else if (unformat(input, "mpls-exp")) {
827  return (parse_op_and_prec(vm, input, cmd,
828  "mpls", &tm->efd.mpls_exp_bitmap));
829  } else if (unformat(input, "vlan-cos")) {
830  return (parse_op_and_prec(vm, input, cmd,
831  "vlan", &tm->efd.vlan_cos_bitmap));
832  } else if (unformat(input, "help")) {
833  vlib_cli_output(vm,
834  "Usage:\n"
835  " set efd enable <dpdk | worker | monitor | drop_all | default> |\n"
836  " set efd disable <dpdk | worker | monitor | drop_all | all> |\n"
837  " set efd <ip-prec | mpls-exp | vlan-cos> <ge | lt> <0-7>\n"
838  " set efd worker_queue_hi_thresh <0-32> |\n"
839  " set efd dpdk_device_hi_thresh <0-%d> |\n"
840  " set efd consec_full_frames_hi_thresh <count> |\n",
842  } else {
843  return clib_error_return(0, "unknown input `%U'",
844  format_unformat_error, input);
845  }
846 
847  return error;
848 }
849 
850 VLIB_CLI_COMMAND (cmd_set_efd,static) = {
851  .path = "set efd",
852  .short_help = "set early-fast-discard commands",
853  .function = set_efd,
854 };
855 
856 static clib_error_t *
858  vlib_cli_command_t *cmd)
859 {
860  unformat_input_t _line_input, * line_input = &_line_input;
861  dpdk_main_t * dm = &dpdk_main;
862  vnet_hw_interface_t * hw;
863  dpdk_device_t * xd;
864  u32 hw_if_index = (u32) ~0;
865  u32 nb_rx_desc = (u32) ~0;
866  u32 nb_tx_desc = (u32) ~0;
867  clib_error_t * rv;
868 
869  if (! unformat_user (input, unformat_line_input, line_input))
870  return 0;
871 
872  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
873  if (unformat (line_input, "%U", unformat_vnet_hw_interface, dm->vnet_main,
874  &hw_if_index))
875  ;
876  else if (unformat (line_input, "tx %d", &nb_tx_desc))
877  ;
878  else if (unformat (line_input, "rx %d", &nb_rx_desc))
879  ;
880  else
881  return clib_error_return (0, "parse error: '%U'",
882  format_unformat_error, line_input);
883  }
884 
885  unformat_free (line_input);
886 
887  if (hw_if_index == (u32) ~0)
888  return clib_error_return (0, "please specify valid interface name");
889 
890  hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
891  xd = vec_elt_at_index (dm->devices, hw->dev_instance);
892 
893  if (xd->dev_type != VNET_DPDK_DEV_ETH)
894  return clib_error_return (0, "number of descriptors can be set only for "
895  "physical devices");
896 
897  if ((nb_rx_desc == (u32) ~0 || nb_rx_desc == xd->nb_rx_desc) &&
898  (nb_tx_desc == (u32) ~0 || nb_tx_desc == xd->nb_tx_desc))
899  return clib_error_return (0, "nothing changed");
900 
901  if (nb_rx_desc != (u32) ~0)
902  xd->nb_rx_desc = nb_rx_desc;
903 
904  if (nb_tx_desc != (u32) ~0)
905  xd->nb_rx_desc = nb_rx_desc;
906 
907  rv = dpdk_port_setup(dm, xd);
908 
909  return rv < 0 ? rv : 0;
910 }
911 
912 VLIB_CLI_COMMAND (cmd_set_dpdk_if_desc,static) = {
913  .path = "set dpdk interface descriptors",
914  .short_help = "set dpdk interface descriptors <if-name> [rx <n>] [tx <n>]",
915  .function = set_dpdk_if_desc,
916 };
917 
918 static clib_error_t *
920  vlib_cli_command_t *cmd)
921 {
923  dpdk_main_t * dm = &dpdk_main;
925  int cpu;
926 
927  if (tm->n_vlib_mains == 1)
928  vlib_cli_output(vm, "All interfaces are handled by main thread");
929 
930  for(cpu = 0; cpu < vec_len(dm->devices_by_cpu); cpu++)
931  {
932  if (vec_len(dm->devices_by_cpu[cpu]))
933  vlib_cli_output(vm, "Thread %u (%s at lcore %u):", cpu,
934  vlib_worker_threads[cpu].name,
935  vlib_worker_threads[cpu].dpdk_lcore_id);
936 
937  vec_foreach(dq, dm->devices_by_cpu[cpu])
938  {
939  u32 hw_if_index = dm->devices[dq->device].vlib_hw_if_index;
941  vlib_cli_output(vm, " %v queue %u", hi->name, dq->queue_id);
942  }
943  }
944  return 0;
945 }
946 
947 VLIB_CLI_COMMAND (cmd_show_dpdk_if_placement,static) = {
948  .path = "show dpdk interface placement",
949  .short_help = "show dpdk interface placement",
950  .function = show_dpdk_if_placement,
951 };
952 
953 static int
954 dpdk_device_queue_sort(void * a1, void * a2)
955 {
956  dpdk_device_and_queue_t * dq1 = a1;
957  dpdk_device_and_queue_t * dq2 = a2;
958 
959  if (dq1->device > dq2->device)
960  return 1;
961  else if (dq1->device < dq2->device)
962  return -1;
963  else if (dq1->queue_id > dq2->queue_id)
964  return 1;
965  else if (dq1->queue_id < dq2->queue_id)
966  return -1;
967  else
968  return 0;
969 }
970 
971 static clib_error_t *
973  vlib_cli_command_t *cmd)
974 {
975  unformat_input_t _line_input, * line_input = &_line_input;
976  dpdk_main_t * dm = &dpdk_main;
978  vnet_hw_interface_t * hw;
979  dpdk_device_t * xd;
980  u32 hw_if_index = (u32) ~0;
981  u32 queue = (u32) 0;
982  u32 cpu = (u32) ~0;
983  int i;
984 
985  if (! unformat_user (input, unformat_line_input, line_input))
986  return 0;
987 
988  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
989  if (unformat (line_input, "%U", unformat_vnet_hw_interface, dm->vnet_main,
990  &hw_if_index))
991  ;
992  else if (unformat (line_input, "queue %d", &queue))
993  ;
994  else if (unformat (line_input, "thread %d", &cpu))
995  ;
996  else
997  return clib_error_return (0, "parse error: '%U'",
998  format_unformat_error, line_input);
999  }
1000 
1001  unformat_free (line_input);
1002 
1003  if (hw_if_index == (u32) ~0)
1004  return clib_error_return (0, "please specify valid interface name");
1005 
1006  if (cpu < dm->input_cpu_first_index ||
1007  cpu >= (dm->input_cpu_first_index + dm->input_cpu_count))
1008  return clib_error_return (0, "please specify valid thread id");
1009 
1010  hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
1011  xd = vec_elt_at_index (dm->devices, hw->dev_instance);
1012 
1013  for(i = 0; i < vec_len(dm->devices_by_cpu); i++)
1014  {
1015  vec_foreach(dq, dm->devices_by_cpu[i])
1016  {
1017  if (hw_if_index == dm->devices[dq->device].vlib_hw_if_index &&
1018  queue == dq->queue_id)
1019  {
1020  if (cpu == i) /* nothing to do */
1021  return 0;
1022 
1023  vec_del1(dm->devices_by_cpu[i], dq - dm->devices_by_cpu[i]);
1024  vec_add2(dm->devices_by_cpu[cpu], dq, 1);
1025  dq->queue_id = queue;
1026  dq->device = xd->device_index;
1027  xd->cpu_socket_id_by_queue[queue] =
1028  rte_lcore_to_socket_id(vlib_worker_threads[cpu].dpdk_lcore_id);
1029 
1032 
1035 
1036  if (vec_len(dm->devices_by_cpu[i]) == 0)
1038  VLIB_NODE_STATE_DISABLED);
1039 
1040  if (vec_len(dm->devices_by_cpu[cpu]) == 1)
1042  VLIB_NODE_STATE_POLLING);
1043 
1044  return 0;
1045  }
1046  }
1047  }
1048 
1049  return clib_error_return (0, "not found");
1050 }
1051 
1052 VLIB_CLI_COMMAND (cmd_set_dpdk_if_placement,static) = {
1053  .path = "set dpdk interface placement",
1054  .short_help = "set dpdk interface placement <if-name> [queue <n>] thread <n>",
1055  .function = set_dpdk_if_placement,
1056 };
1057 
1058 clib_error_t *
1060 {
1061  return 0;
1062 }
1063 
u64 count[MAX_NELTS]
Definition: dpdk.h:274
unformat_function_t unformat_vnet_hw_interface
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
vmrglw vmrglh hi
u16 enabled
Definition: dpdk.h:307
char * file_name
Definition: pcap.h:107
always_inline vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
static void show_dpdk_device_stats(vlib_main_t *vm, dpdk_device_t *xd)
Definition: cli.c:253
u32 n_packets_to_capture
Definition: pcap.h:110
u16 max_burst_sz
Definition: dpdk.h:129
static clib_error_t * test_frame_queue_nelts(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:486
dpdk_main_t dpdk_main
Definition: dpdk.h:415
static clib_error_t * show_dpdk_if_placement(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:919
u64 last_poll_time
Definition: dpdk.h:133
static clib_error_t * set_dpdk_if_placement(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:972
always_inline void unformat_free(unformat_input_t *i)
Definition: format.h:160
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
static clib_error_t * show_frame_queue_trace(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:456
#define NULL
Definition: clib.h:55
#define MAX_NELTS
Definition: dpdk.h:260
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
static clib_error_t * parse_op_and_prec(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, char *prec_type, u8 *prec_bitmap)
Definition: cli.c:711
vlib_buffer_main_t * buffer_main
Definition: main.h:103
unformat_function_t unformat_vnet_sw_interface
static clib_error_t * show_dpdk_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:159
#define clib_error_report(e)
Definition: error.h:126
u32 congestion_cnt
Definition: dpdk.h:132
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:405
u8 * pcap_filename
Definition: dpdk.h:368
static clib_error_t * trace_frame_queue(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:289
clib_error_t * dpdk_port_setup(dpdk_main_t *dm, dpdk_device_t *xd)
Definition: init.c:66
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
u8 mpls_exp_bitmap
Definition: threads.h:251
static clib_error_t * test_frame_queue_threshold(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:524
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
vlib_node_registration_t dpdk_input_node
(constructor) VLIB_REGISTER_NODE (dpdk_input_node)
Definition: node.c:829
u32 pcap_pkts_to_capture
Definition: dpdk.h:370
u16 queue_hi_thresh
Definition: threads.h:249
int input_cpu_first_index
Definition: dpdk.h:399
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Definition: node_funcs.h:100
static clib_error_t * show_frame_queue_histogram(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:463
static u32 compute_percent(u64 *two_counters, u64 total)
Definition: cli.c:343
unsigned long u64
Definition: types.h:89
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:953
u32 device_index
Definition: dpdk.h:193
always_inline heap_elt_t * first(heap_header_t *h)
Definition: heap.c:54
u32 pcap_sw_if_index
Definition: dpdk.h:369
u16 consec_full_frames_hi_thresh
Definition: dpdk.h:309
char * name
Definition: main.h:97
static clib_error_t * pcap_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:29
#define VLIB_EFD_DISCARD_ENABLED
Definition: threads.h:241
volatile u64 head
Definition: threads.h:121
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer.c:1060
dpdk_device_and_queue_t ** devices_by_cpu
Definition: dpdk.h:317
u64 max_poll_delay
Definition: dpdk.h:134
static clib_error_t * clear_efd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:671
u32 consec_full_frames_cnt
Definition: dpdk.h:131
u32 vlib_hw_if_index
Definition: dpdk.h:195
#define DPDK_EFD_DISCARD_ENABLED
Definition: dpdk.h:299
pcap_main_t pcap_main
Definition: dpdk.h:367
u16 last_burst_sz
Definition: dpdk.h:128
#define DPDK_EFD_MONITOR_ENABLED
Definition: dpdk.h:300
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:763
u32 full_frames_cnt
Definition: dpdk.h:130
int input_cpu_count
Definition: dpdk.h:400
vlib_frame_queue_t ** vlib_frame_queues
Definition: threads.h:139
u16 nb_rx_desc
Definition: dpdk.h:226
frame_queue_nelt_counter_t * frame_queue_histogram
Definition: dpdk.h:408
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
volatile u64 tail
Definition: threads.h:110
dpdk_device_t * devices
Definition: dpdk.h:316
u8 ip_prec_bitmap
Definition: threads.h:250
u16 * cpu_socket_id_by_queue
Definition: dpdk.h:228
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
static clib_error_t * test_dpdk_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:193
u16 queue_hi_thresh
Definition: dpdk.h:308
u8 vlan_cos_bitmap
Definition: threads.h:252
static int dpdk_device_queue_sort(void *a1, void *a2)
Definition: cli.c:954
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
clib_error_t * pcap_write(pcap_main_t *pm)
Definition: pcap.c:62
static clib_error_t * set_dpdk_if_desc(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:857
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
#define EFD_OPERATION_GREATER_OR_EQUAL
Definition: dpdk.h:546
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.h:106
u32 discard_cnt
Definition: dpdk.h:135
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
dpdk_efd_t efd
Definition: dpdk.h:388
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer.c:770
uword * thread_registrations_by_name
Definition: threads.h:263
#define VLIB_EFD_MONITOR_ENABLED
Definition: threads.h:242
#define DPDK_NB_RX_DESC_10GE
Definition: dpdk_priv.h:20
frame_queue_trace_t * frame_queue_traces
Definition: dpdk.h:407
u64 uword
Definition: types.h:112
static clib_error_t * show_efd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:595
pcap_packet_type_t packet_type
Definition: pcap.h:112
u32 enqueue_full_events
Definition: threads.h:114
static clib_error_t * set_efd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:756
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
dpdk_device_type_t dev_type
Definition: dpdk.h:214
unsigned char u8
Definition: types.h:56
dpdk_efd_agent_t efd_agent
Definition: dpdk.h:256
#define DPDK_EFD_DROPALL_ENABLED
Definition: dpdk.h:301
void set_efd_bitmap(u8 *bitmap, u32 value, u32 op)
Definition: node.c:1963
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:898
u32 enqueue_efd_discards
Definition: threads.h:115
volatile u64 head_hint
Definition: threads.h:131
#define hash_get_mem(h, key)
Definition: hash.h:251
static clib_error_t * show_frame_queue_internal(vlib_main_t *vm, u32 histogram)
Definition: cli.c:359
#define vec_foreach(var, vec)
Vector iterator.
#define EFD_OPERATION_LESS_THAN
Definition: dpdk.h:545
u32 total_packet_cnt
Definition: dpdk.h:136
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
int tx_pcap_enable
Definition: dpdk.h:366
vnet_main_t * vnet_main
Definition: dpdk.h:412
u16 nb_tx_desc
Definition: dpdk.h:227
unformat_function_t unformat_line_input
Definition: format.h:279
i32 n_vectors[MAX_NELTS]
Definition: dpdk.h:270
static void show_efd_config(vlib_main_t *vm)
Definition: cli.c:562
u32 n_packets_captured
Definition: pcap.h:115
u16 enabled
Definition: threads.h:248
vlib_efd_t efd
Definition: threads.h:303
vlib_main_t ** vlib_mains
Definition: buffer.c:244
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
clib_error_t * dpdk_cli_init(vlib_main_t *vm)
Definition: cli.c:1059