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;
36 /* Get a line of input. */
37 if (!unformat_user (input, unformat_line_input, line_input))
40 clib_memset (&args, 0, sizeof (args));
41 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
43 if (unformat (line_input, "%U", unformat_vlib_pci_addr, &args.addr))
45 else if (unformat (line_input, "elog"))
47 else if (unformat (line_input, "rx-queue-size %u", &args.rxq_size))
49 else if (unformat (line_input, "tx-queue-size %u", &args.txq_size))
51 else if (unformat (line_input, "num-tx-queues %u", &args.txq_num))
53 else if (unformat (line_input, "num-rx-queues %u", &args.rxq_num))
56 return clib_error_return (0, "unknown input `%U'",
57 format_unformat_error, input);
59 unformat_free (line_input);
62 vmxnet3_create_if (vm, &args);
68 VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
69 .path = "create interface vmxnet3",
70 .short_help = "create interface vmxnet3 <pci-address>"
71 "[rx-queue-size <size>] [tx-queue-size <size>]"
72 "[num-tx-queues <number>] [num-rx-queues <number>]",
73 .function = vmxnet3_create_command_fn,
78 vmxnet3_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
79 vlib_cli_command_t * cmd)
81 unformat_input_t _line_input, *line_input = &_line_input;
83 vnet_hw_interface_t *hw;
84 vmxnet3_main_t *vmxm = &vmxnet3_main;
86 vnet_main_t *vnm = vnet_get_main ();
88 /* Get a line of input. */
89 if (!unformat_user (input, unformat_line_input, line_input))
92 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
94 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
96 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
100 return clib_error_return (0, "unknown input `%U'",
101 format_unformat_error, input);
103 unformat_free (line_input);
105 if (sw_if_index == ~0)
106 return clib_error_return (0,
107 "please specify interface name or sw_if_index");
109 hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
110 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
111 return clib_error_return (0, "not a vmxnet3 interface");
113 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
115 vmxnet3_delete_if (vm, vd);
121 VLIB_CLI_COMMAND (vmxnet3_delete_command, static) = {
122 .path = "delete interface vmxnet3",
123 .short_help = "delete interface vmxnet3 "
124 "{<interface> | sw_if_index <sw_idx>}",
125 .function = vmxnet3_delete_command_fn,
129 static clib_error_t *
130 vmxnet3_test_command_fn (vlib_main_t * vm, unformat_input_t * input,
131 vlib_cli_command_t * cmd)
133 unformat_input_t _line_input, *line_input = &_line_input;
134 u32 sw_if_index = ~0;
135 vnet_hw_interface_t *hw;
136 vmxnet3_main_t *vmxm = &vmxnet3_main;
137 vmxnet3_device_t *vd;
138 vnet_main_t *vnm = vnet_get_main ();
139 int enable_elog = 0, disable_elog = 0;
141 /* Get a line of input. */
142 if (!unformat_user (input, unformat_line_input, line_input))
145 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
147 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
149 else if (unformat (line_input, "elog-on"))
151 else if (unformat (line_input, "elog-off"))
153 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
157 return clib_error_return (0, "unknown input `%U'",
158 format_unformat_error, input);
160 unformat_free (line_input);
162 if (sw_if_index == ~0)
163 return clib_error_return (0,
164 "please specify interface name or sw_if_index");
166 hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
167 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
168 return clib_error_return (0, "not a vmxnet3 interface");
170 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
173 vd->flags |= VMXNET3_DEVICE_F_ELOG;
176 vd->flags &= ~VMXNET3_DEVICE_F_ELOG;
182 VLIB_CLI_COMMAND (vmxnet3_test_command, static) = {
183 .path = "test vmxnet3",
184 .short_help = "test vmxnet3 <interface> | sw_if_index <sw_idx> [irq] "
185 "[elog-on] [elog-off]",
186 .function = vmxnet3_test_command_fn,
191 show_vmxnet3 (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
192 u8 show_one_table, u32 which, u8 show_one_slot, u32 slot)
195 vmxnet3_device_t *vd;
196 vnet_main_t *vnm = &vnet_main;
197 vmxnet3_main_t *vmxm = &vmxnet3_main;
198 vnet_hw_interface_t *hi;
200 vmxnet3_rx_desc *rxd;
201 vmxnet3_rx_comp *rx_comp;
203 vmxnet3_tx_desc *txd;
204 vmxnet3_tx_comp *tx_comp;
210 vlib_cli_output (vm, "LRO/TSO configured: %u", vmxm->lro_configured);
211 for (i = 0; i < vec_len (hw_if_indices); i++)
213 hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
214 vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
215 vlib_cli_output (vm, "Interface: %U (ifindex %d)",
216 format_vnet_hw_if_index_name, vnm, hw_if_indices[i],
218 vlib_cli_output (vm, " Version: %u", vd->version);
219 vlib_cli_output (vm, " LRO/TSO enable: %u", vd->lro_enable);
220 vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
222 vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
224 vlib_cli_output (vm, " hw if index: %u", vd->hw_if_index);
225 vlib_cli_output (vm, " Device instance: %u", vd->dev_instance);
226 vlib_cli_output (vm, " Number of interrupts: %u", vd->num_intrs);
228 vec_foreach_index (qid, vd->rxqs)
230 rxq = vec_elt_at_index (vd->rxqs, qid);
233 vlib_cli_output (vm, " Queue %u (RX)", qid);
234 vlib_cli_output (vm, " RX completion next index %u",
235 rxq->rx_comp_ring.next);
236 vlib_cli_output (vm, " RX completion generation flag 0x%x",
237 rxq->rx_comp_ring.gen);
239 /* RX descriptors tables */
240 for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
242 vmxnet3_rx_ring *ring = &rxq->rx_ring[rid];
245 " ring %u size %u fill %u "
246 "consume %u produce %u", rid,
247 rxq->size, ring->fill, ring->consume,
251 vlib_cli_output (vm, "RX descriptors table");
252 vlib_cli_output (vm, " %5s %18s %10s",
253 "slot", "address", "flags");
254 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
256 rxd = &rxq->rx_desc[rid][desc_idx];
257 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
258 desc_idx, rxd->address, rxd->flags);
261 else if (show_one_table)
263 if (((which == VMXNET3_SHOW_RX_DESC0) && (rid == 0)) ||
264 ((which == VMXNET3_SHOW_RX_DESC1) && (rid == 1)))
266 vlib_cli_output (vm, "RX descriptors table");
267 vlib_cli_output (vm, " %5s %18s %10s",
268 "slot", "address", "flags");
271 rxd = &rxq->rx_desc[rid][slot];
272 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
273 slot, rxd->address, rxd->flags);
276 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
278 rxd = &rxq->rx_desc[rid][desc_idx];
279 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
280 desc_idx, rxd->address,
287 /* RX completion table */
290 vlib_cli_output (vm, "RX completion descriptors table");
291 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
292 "slot", "index", "rss", "len", "flags");
293 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
295 rx_comp = &rxq->rx_comp[desc_idx];
296 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
297 desc_idx, rx_comp->index, rx_comp->rss,
298 rx_comp->len, rx_comp->flags);
301 else if (show_one_table)
303 if (which == VMXNET3_SHOW_RX_COMP)
305 vlib_cli_output (vm, "RX completion descriptors table");
306 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
307 "slot", "index", "rss", "len", "flags");
310 rx_comp = &rxq->rx_comp[slot];
311 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
312 slot, rx_comp->index, rx_comp->rss,
313 rx_comp->len, rx_comp->flags);
316 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
318 rx_comp = &rxq->rx_comp[desc_idx];
320 " %5u 0x%08x %10u %10u 0x%08x",
321 desc_idx, rx_comp->index, rx_comp->rss,
322 rx_comp->len, rx_comp->flags);
328 vec_foreach_index (qid, vd->txqs)
330 txq = vec_elt_at_index (vd->txqs, qid);
331 vlib_cli_output (vm, " Queue %u (TX)", qid);
332 vlib_cli_output (vm, " TX completion next index %u",
333 txq->tx_comp_ring.next);
334 vlib_cli_output (vm, " TX completion generation flag 0x%x",
335 txq->tx_comp_ring.gen);
336 vlib_cli_output (vm, " size %u consume %u produce %u",
337 txq->size, txq->tx_ring.consume,
338 txq->tx_ring.produce);
341 vlib_cli_output (vm, "TX descriptors table");
342 vlib_cli_output (vm, " %5s %18s %10s %10s",
343 "slot", "address", "flags0", "flags1");
344 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
346 txd = &txq->tx_desc[desc_idx];
347 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
348 desc_idx, txd->address, txd->flags[0],
352 vlib_cli_output (vm, "TX completion descriptors table");
353 vlib_cli_output (vm, " %5s %10s %10s",
354 "slot", "index", "flags");
355 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
357 tx_comp = &txq->tx_comp[desc_idx];
358 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
359 desc_idx, tx_comp->index, tx_comp->flags);
362 else if (show_one_table)
364 if (which == VMXNET3_SHOW_TX_DESC)
366 vlib_cli_output (vm, "TX descriptors table");
367 vlib_cli_output (vm, " %5s %18s %10s %10s",
368 "slot", "address", "flags0", "flags1");
371 txd = &txq->tx_desc[slot];
372 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
373 slot, txd->address, txd->flags[0],
377 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
379 txd = &txq->tx_desc[desc_idx];
380 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
381 desc_idx, txd->address, txd->flags[0],
385 else if (which == VMXNET3_SHOW_TX_COMP)
387 vlib_cli_output (vm, "TX completion descriptors table");
388 vlib_cli_output (vm, " %5s %10s %10s",
389 "slot", "index", "flags");
392 tx_comp = &txq->tx_comp[slot];
393 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
394 slot, tx_comp->index, tx_comp->flags);
397 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
399 tx_comp = &txq->tx_comp[desc_idx];
400 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
401 desc_idx, tx_comp->index,
410 static clib_error_t *
411 show_vmxnet3_fn (vlib_main_t * vm, unformat_input_t * input,
412 vlib_cli_command_t * cmd)
414 vmxnet3_main_t *vmxm = &vmxnet3_main;
415 vnet_main_t *vnm = &vnet_main;
416 vmxnet3_device_t *vd;
417 clib_error_t *error = 0;
418 u32 hw_if_index, *hw_if_indices = 0;
419 vnet_hw_interface_t *hi = 0;
420 u8 show_descr = 0, show_one_table = 0, show_one_slot = 0;
421 u32 which = ~0, slot;
423 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
426 (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
428 hi = vnet_get_hw_interface (vnm, hw_if_index);
429 if (vmxnet3_device_class.index != hi->dev_class_index)
431 error = clib_error_return (0, "unknown input `%U'",
432 format_unformat_error, input);
435 vec_add1 (hw_if_indices, hw_if_index);
437 else if (unformat (input, "desc"))
441 vmxnet3_device_t *vd =
442 vec_elt_at_index (vmxm->devices, hi->dev_instance);
444 if (unformat (input, "rx-comp"))
447 which = VMXNET3_SHOW_RX_COMP;
448 if (unformat (input, "%u", &slot))
450 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
452 if (slot >= rxq->size)
454 error = clib_error_return (0,
455 "slot size must be < rx queue "
456 "size %u", rxq->size);
462 else if (unformat (input, "rx-desc-0"))
465 which = VMXNET3_SHOW_RX_DESC0;
466 if (unformat (input, "%u", &slot))
468 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
470 if (slot >= rxq->size)
472 error = clib_error_return (0,
473 "slot size must be < rx queue "
474 "size %u", rxq->size);
480 else if (unformat (input, "rx-desc-1"))
483 which = VMXNET3_SHOW_RX_DESC1;
484 if (unformat (input, "%u", &slot))
486 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
488 if (slot >= rxq->size)
490 error = clib_error_return (0,
491 "slot size must be < rx queue "
492 "size %u", rxq->size);
498 else if (unformat (input, "tx-comp"))
501 which = VMXNET3_SHOW_TX_COMP;
502 if (unformat (input, "%u", &slot))
504 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
506 if (slot >= txq->size)
508 error = clib_error_return (0,
509 "slot size must be < tx queue "
510 "size %u", txq->size);
516 else if (unformat (input, "tx-desc"))
519 which = VMXNET3_SHOW_TX_DESC;
520 if (unformat (input, "%u", &slot))
522 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
524 if (slot >= txq->size)
526 error = clib_error_return (0,
527 "slot size must be < tx queue "
528 "size %u", txq->size);
536 error = clib_error_return (0, "unknown input `%U'",
537 format_unformat_error, input);
543 error = clib_error_return (0, "unknown input `%U'",
544 format_unformat_error, input);
549 if (vec_len (hw_if_indices) == 0)
551 pool_foreach (vd, vmxm->devices,
552 vec_add1 (hw_if_indices, vd->hw_if_index);
556 show_vmxnet3 (vm, hw_if_indices, show_descr, show_one_table, which,
557 show_one_slot, slot);
560 vec_free (hw_if_indices);
565 VLIB_CLI_COMMAND (show_vmxnet3_command, static) = {
566 .path = "show vmxnet3",
567 .short_help = "show vmxnet3 [[<interface>] ([desc] | ([rx-comp] | "
568 "[rx-desc-0] | [rx-desc-1] | [tx-comp] | [tx-desc]) [<slot>])]",
569 .function = show_vmxnet3_fn,
574 vmxnet3_cli_init (vlib_main_t * vm)
576 vmxnet3_main_t *vmxm = &vmxnet3_main;
578 /* initialize binary API */
579 vmxnet3_plugin_api_hookup (vm);
581 vmxm->log_default = vlib_log_register_class ("vmxnet3", 0);
585 VLIB_INIT_FUNCTION (vmxnet3_cli_init);
587 static clib_error_t *
588 vmxnet3_config (vlib_main_t * vm, unformat_input_t * input)
590 vmxnet3_main_t *vmxm = &vmxnet3_main;
592 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
594 if (unformat (input, "lro"))
595 vmxm->lro_configured = 1;
597 return clib_error_return (0, "unknown input `%U'",
598 format_unformat_error, input);
604 /* vmxnet3 { ... } configuration. */
605 VLIB_CONFIG_FUNCTION (vmxnet3_config, "vmxnet3");
608 * fd.io coding-style-patch-verification: ON
611 * eval: (c-set-style "gnu")