2 *------------------------------------------------------------------
3 * Copyright (c) 2018 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
19 #include <sys/ioctl.h>
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vlib/pci/pci.h>
25 #include <vnet/ethernet/ethernet.h>
27 #include <vmxnet3/vmxnet3.h>
30 vmxnet3_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
31 vlib_cli_command_t * cmd)
33 unformat_input_t _line_input, *line_input = &_line_input;
34 vmxnet3_create_if_args_t args;
37 /* Get a line of input. */
38 if (!unformat_user (input, unformat_line_input, line_input))
41 clib_memset (&args, 0, sizeof (args));
42 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
44 if (unformat (line_input, "%U", unformat_vlib_pci_addr, &args.addr))
46 else if (unformat (line_input, "gso"))
48 else if (unformat (line_input, "elog"))
50 else if (unformat (line_input, "bind force"))
51 args.bind = VMXNET3_BIND_FORCE;
52 else if (unformat (line_input, "bind"))
53 args.bind = VMXNET3_BIND_DEFAULT;
54 else if (unformat (line_input, "rx-queue-size %u", &size))
56 else if (unformat (line_input, "tx-queue-size %u", &size))
58 else if (unformat (line_input, "num-tx-queues %u", &size))
60 else if (unformat (line_input, "num-rx-queues %u", &size))
64 unformat_free (line_input);
65 return clib_error_return (0, "unknown input `%U'",
66 format_unformat_error, input);
69 unformat_free (line_input);
71 vmxnet3_create_if (vm, &args);
73 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
74 vnet_get_main (), args.sw_if_index);
79 VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
80 .path = "create interface vmxnet3",
82 "create interface vmxnet3 <pci-address>"
83 " [rx-queue-size <size>] [tx-queue-size <size>]"
84 " [num-tx-queues <number>] [num-rx-queues <number>] [bind [force]]"
86 .function = vmxnet3_create_command_fn,
90 vmxnet3_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
91 vlib_cli_command_t * cmd)
93 unformat_input_t _line_input, *line_input = &_line_input;
95 vnet_hw_interface_t *hw;
96 vmxnet3_main_t *vmxm = &vmxnet3_main;
98 vnet_main_t *vnm = vnet_get_main ();
100 /* Get a line of input. */
101 if (!unformat_user (input, unformat_line_input, line_input))
104 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
106 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
108 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
112 return clib_error_return (0, "unknown input `%U'",
113 format_unformat_error, input);
115 unformat_free (line_input);
117 if (sw_if_index == ~0)
118 return clib_error_return (0,
119 "please specify interface name or sw_if_index");
121 hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
122 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
123 return clib_error_return (0, "not a vmxnet3 interface");
125 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
127 vmxnet3_delete_if (vm, vd);
132 VLIB_CLI_COMMAND (vmxnet3_delete_command, static) = {
133 .path = "delete interface vmxnet3",
134 .short_help = "delete interface vmxnet3 "
135 "{<interface> | sw_if_index <sw_idx>}",
136 .function = vmxnet3_delete_command_fn,
139 static clib_error_t *
140 vmxnet3_test_command_fn (vlib_main_t * vm, unformat_input_t * input,
141 vlib_cli_command_t * cmd)
143 unformat_input_t _line_input, *line_input = &_line_input;
144 u32 sw_if_index = ~0;
145 vnet_hw_interface_t *hw;
146 vmxnet3_main_t *vmxm = &vmxnet3_main;
147 vmxnet3_device_t *vd;
148 vnet_main_t *vnm = vnet_get_main ();
149 int enable_elog = 0, disable_elog = 0;
151 /* Get a line of input. */
152 if (!unformat_user (input, unformat_line_input, line_input))
155 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
157 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
159 else if (unformat (line_input, "elog-on"))
161 else if (unformat (line_input, "elog-off"))
163 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
167 return clib_error_return (0, "unknown input `%U'",
168 format_unformat_error, input);
170 unformat_free (line_input);
172 if (sw_if_index == ~0)
173 return clib_error_return (0,
174 "please specify interface name or sw_if_index");
176 hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
177 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
178 return clib_error_return (0, "not a vmxnet3 interface");
180 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
183 vd->flags |= VMXNET3_DEVICE_F_ELOG;
186 vd->flags &= ~VMXNET3_DEVICE_F_ELOG;
191 VLIB_CLI_COMMAND (vmxnet3_test_command, static) = {
192 .path = "test vmxnet3",
193 .short_help = "test vmxnet3 <interface> | sw_if_index <sw_idx> [irq] "
194 "[elog-on] [elog-off]",
195 .function = vmxnet3_test_command_fn,
199 show_vmxnet3 (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
200 u8 show_one_table, u32 which, u8 show_one_slot, u32 slot)
203 vmxnet3_device_t *vd;
204 vnet_main_t *vnm = &vnet_main;
205 vmxnet3_main_t *vmxm = &vmxnet3_main;
206 vnet_hw_interface_t *hi;
208 vmxnet3_rx_desc *rxd;
209 vmxnet3_rx_comp *rx_comp;
211 vmxnet3_tx_desc *txd;
212 vmxnet3_tx_comp *tx_comp;
215 vlib_cli_output (vm, "Global:");
216 for (u32 tid = 0; tid <= vlib_num_workers (); tid++)
218 vmxnet3_per_thread_data_t *ptd =
219 vec_elt_at_index (vmxm->per_thread_data, tid);
220 vlib_cli_output (vm, " Thread %u: polling queue count %u", tid,
221 ptd->polling_q_count);
227 for (i = 0; i < vec_len (hw_if_indices); i++)
229 hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
230 vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
231 vlib_cli_output (vm, "Interface: %U (ifindex %d)",
232 format_vnet_hw_if_index_name, vnm, hw_if_indices[i],
234 vlib_cli_output (vm, " Version: %u", vd->version);
235 vlib_cli_output (vm, " GSO enable: %u", vd->gso_enable);
236 vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
238 vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
240 vlib_cli_output (vm, " hw if index: %u", vd->hw_if_index);
241 vlib_cli_output (vm, " Device instance: %u", vd->dev_instance);
242 vlib_cli_output (vm, " Number of interrupts: %u", vd->num_intrs);
244 vec_foreach_index (qid, vd->rxqs)
246 rxq = vec_elt_at_index (vd->rxqs, qid);
249 vlib_cli_output (vm, " Queue %u (RX)", qid);
250 vlib_cli_output (vm, " RX completion next index %u",
251 rxq->rx_comp_ring.next);
252 vlib_cli_output (vm, " RX completion generation flag 0x%x",
253 rxq->rx_comp_ring.gen);
255 /* RX descriptors tables */
256 for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
258 vmxnet3_rx_ring *ring = &rxq->rx_ring[rid];
261 " ring %u size %u fill %u "
262 "consume %u produce %u", rid,
263 rxq->size, ring->fill, ring->consume,
267 vlib_cli_output (vm, "RX descriptors table");
268 vlib_cli_output (vm, " %5s %18s %10s",
269 "slot", "address", "flags");
270 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
272 rxd = &rxq->rx_desc[rid][desc_idx];
273 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
274 desc_idx, rxd->address, rxd->flags);
277 else if (show_one_table)
279 if (((which == VMXNET3_SHOW_RX_DESC0) && (rid == 0)) ||
280 ((which == VMXNET3_SHOW_RX_DESC1) && (rid == 1)))
282 vlib_cli_output (vm, "RX descriptors table");
283 vlib_cli_output (vm, " %5s %18s %10s",
284 "slot", "address", "flags");
287 rxd = &rxq->rx_desc[rid][slot];
288 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
289 slot, rxd->address, rxd->flags);
292 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
294 rxd = &rxq->rx_desc[rid][desc_idx];
295 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
296 desc_idx, rxd->address,
303 /* RX completion table */
306 vlib_cli_output (vm, "RX completion descriptors table");
307 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
308 "slot", "index", "rss", "len", "flags");
309 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
311 rx_comp = &rxq->rx_comp[desc_idx];
312 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
313 desc_idx, rx_comp->index, rx_comp->rss,
314 rx_comp->len, rx_comp->flags);
317 else if (show_one_table)
319 if (which == VMXNET3_SHOW_RX_COMP)
321 vlib_cli_output (vm, "RX completion descriptors table");
322 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
323 "slot", "index", "rss", "len", "flags");
326 rx_comp = &rxq->rx_comp[slot];
327 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
328 slot, rx_comp->index, rx_comp->rss,
329 rx_comp->len, rx_comp->flags);
332 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
334 rx_comp = &rxq->rx_comp[desc_idx];
336 " %5u 0x%08x %10u %10u 0x%08x",
337 desc_idx, rx_comp->index, rx_comp->rss,
338 rx_comp->len, rx_comp->flags);
344 vec_foreach_index (qid, vd->txqs)
346 txq = vec_elt_at_index (vd->txqs, qid);
347 vlib_cli_output (vm, " Queue %u (TX)", qid);
348 vlib_cli_output (vm, " TX completion next index %u",
349 txq->tx_comp_ring.next);
350 vlib_cli_output (vm, " TX completion generation flag 0x%x",
351 txq->tx_comp_ring.gen);
352 vlib_cli_output (vm, " size %u consume %u produce %u",
353 txq->size, txq->tx_ring.consume,
354 txq->tx_ring.produce);
357 vlib_cli_output (vm, "TX descriptors table");
358 vlib_cli_output (vm, " %5s %18s %10s %10s",
359 "slot", "address", "flags0", "flags1");
360 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
362 txd = &txq->tx_desc[desc_idx];
363 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
364 desc_idx, txd->address, txd->flags[0],
368 vlib_cli_output (vm, "TX completion descriptors table");
369 vlib_cli_output (vm, " %5s %10s %10s",
370 "slot", "index", "flags");
371 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
373 tx_comp = &txq->tx_comp[desc_idx];
374 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
375 desc_idx, tx_comp->index, tx_comp->flags);
378 else if (show_one_table)
380 if (which == VMXNET3_SHOW_TX_DESC)
382 vlib_cli_output (vm, "TX descriptors table");
383 vlib_cli_output (vm, " %5s %18s %10s %10s",
384 "slot", "address", "flags0", "flags1");
387 txd = &txq->tx_desc[slot];
388 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
389 slot, txd->address, txd->flags[0],
393 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
395 txd = &txq->tx_desc[desc_idx];
396 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
397 desc_idx, txd->address, txd->flags[0],
401 else if (which == VMXNET3_SHOW_TX_COMP)
403 vlib_cli_output (vm, "TX completion descriptors table");
404 vlib_cli_output (vm, " %5s %10s %10s",
405 "slot", "index", "flags");
408 tx_comp = &txq->tx_comp[slot];
409 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
410 slot, tx_comp->index, tx_comp->flags);
413 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
415 tx_comp = &txq->tx_comp[desc_idx];
416 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
417 desc_idx, tx_comp->index,
426 static clib_error_t *
427 show_vmxnet3_fn (vlib_main_t * vm, unformat_input_t * input,
428 vlib_cli_command_t * cmd)
430 vmxnet3_main_t *vmxm = &vmxnet3_main;
431 vnet_main_t *vnm = &vnet_main;
432 vmxnet3_device_t *vd;
433 clib_error_t *error = 0;
434 u32 hw_if_index, *hw_if_indices = 0;
435 vnet_hw_interface_t *hi = 0;
436 u8 show_descr = 0, show_one_table = 0, show_one_slot = 0;
437 u32 which = ~0, slot;
439 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
442 (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
444 hi = vnet_get_hw_interface (vnm, hw_if_index);
445 if (vmxnet3_device_class.index != hi->dev_class_index)
447 error = clib_error_return (0, "unknown input `%U'",
448 format_unformat_error, input);
451 vec_add1 (hw_if_indices, hw_if_index);
453 else if (unformat (input, "desc"))
457 vmxnet3_device_t *vd =
458 vec_elt_at_index (vmxm->devices, hi->dev_instance);
460 if (unformat (input, "rx-comp"))
463 which = VMXNET3_SHOW_RX_COMP;
464 if (unformat (input, "%u", &slot))
466 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
468 if (slot >= rxq->size)
470 error = clib_error_return (0,
471 "slot size must be < rx queue "
472 "size %u", rxq->size);
478 else if (unformat (input, "rx-desc-0"))
481 which = VMXNET3_SHOW_RX_DESC0;
482 if (unformat (input, "%u", &slot))
484 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
486 if (slot >= rxq->size)
488 error = clib_error_return (0,
489 "slot size must be < rx queue "
490 "size %u", rxq->size);
496 else if (unformat (input, "rx-desc-1"))
499 which = VMXNET3_SHOW_RX_DESC1;
500 if (unformat (input, "%u", &slot))
502 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
504 if (slot >= rxq->size)
506 error = clib_error_return (0,
507 "slot size must be < rx queue "
508 "size %u", rxq->size);
514 else if (unformat (input, "tx-comp"))
517 which = VMXNET3_SHOW_TX_COMP;
518 if (unformat (input, "%u", &slot))
520 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
522 if (slot >= txq->size)
524 error = clib_error_return (0,
525 "slot size must be < tx queue "
526 "size %u", txq->size);
532 else if (unformat (input, "tx-desc"))
535 which = VMXNET3_SHOW_TX_DESC;
536 if (unformat (input, "%u", &slot))
538 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
540 if (slot >= txq->size)
542 error = clib_error_return (0,
543 "slot size must be < tx queue "
544 "size %u", txq->size);
552 error = clib_error_return (0, "unknown input `%U'",
553 format_unformat_error, input);
559 error = clib_error_return (0, "unknown input `%U'",
560 format_unformat_error, input);
565 if (vec_len (hw_if_indices) == 0)
567 pool_foreach (vd, vmxm->devices)
568 vec_add1 (hw_if_indices, vd->hw_if_index);
571 show_vmxnet3 (vm, hw_if_indices, show_descr, show_one_table, which,
572 show_one_slot, slot);
575 vec_free (hw_if_indices);
579 VLIB_CLI_COMMAND (show_vmxnet3_command, static) = {
580 .path = "show vmxnet3",
581 .short_help = "show vmxnet3 [[<interface>] ([desc] | ([rx-comp] | "
582 "[rx-desc-0] | [rx-desc-1] | [tx-comp] | [tx-desc]) [<slot>])]",
583 .function = show_vmxnet3_fn,
587 vmxnet3_cli_init (vlib_main_t * vm)
589 vmxnet3_main_t *vmxm = &vmxnet3_main;
590 vlib_thread_main_t *tm = vlib_get_thread_main ();
592 /* initialize binary API */
593 vmxnet3_plugin_api_hookup (vm);
595 vmxm->log_default = vlib_log_register_class ("vmxnet3", 0);
597 vec_validate (vmxm->per_thread_data, tm->n_vlib_mains - 1);
601 VLIB_INIT_FUNCTION (vmxnet3_cli_init);
604 * fd.io coding-style-patch-verification: ON
607 * eval: (c-set-style "gnu")