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"))
52 else if (unformat (line_input, "rx-queue-size %u", &size))
54 else if (unformat (line_input, "tx-queue-size %u", &size))
56 else if (unformat (line_input, "num-tx-queues %u", &size))
58 else if (unformat (line_input, "num-rx-queues %u", &size))
62 unformat_free (line_input);
63 return clib_error_return (0, "unknown input `%U'",
64 format_unformat_error, input);
67 unformat_free (line_input);
69 vmxnet3_create_if (vm, &args);
71 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
72 vnet_get_main (), args.sw_if_index);
78 VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
79 .path = "create interface vmxnet3",
80 .short_help = "create interface vmxnet3 <pci-address>"
81 " [rx-queue-size <size>] [tx-queue-size <size>]"
82 " [num-tx-queues <number>] [num-rx-queues <number>] [bind]"
84 .function = vmxnet3_create_command_fn,
89 vmxnet3_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
90 vlib_cli_command_t * cmd)
92 unformat_input_t _line_input, *line_input = &_line_input;
94 vnet_hw_interface_t *hw;
95 vmxnet3_main_t *vmxm = &vmxnet3_main;
97 vnet_main_t *vnm = vnet_get_main ();
99 /* Get a line of input. */
100 if (!unformat_user (input, unformat_line_input, line_input))
103 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
105 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
107 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
111 return clib_error_return (0, "unknown input `%U'",
112 format_unformat_error, input);
114 unformat_free (line_input);
116 if (sw_if_index == ~0)
117 return clib_error_return (0,
118 "please specify interface name or sw_if_index");
120 hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
121 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
122 return clib_error_return (0, "not a vmxnet3 interface");
124 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
126 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,
140 static clib_error_t *
141 vmxnet3_test_command_fn (vlib_main_t * vm, unformat_input_t * input,
142 vlib_cli_command_t * cmd)
144 unformat_input_t _line_input, *line_input = &_line_input;
145 u32 sw_if_index = ~0;
146 vnet_hw_interface_t *hw;
147 vmxnet3_main_t *vmxm = &vmxnet3_main;
148 vmxnet3_device_t *vd;
149 vnet_main_t *vnm = vnet_get_main ();
150 int enable_elog = 0, disable_elog = 0;
152 /* Get a line of input. */
153 if (!unformat_user (input, unformat_line_input, line_input))
156 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
158 if (unformat (line_input, "sw_if_index %d", &sw_if_index))
160 else if (unformat (line_input, "elog-on"))
162 else if (unformat (line_input, "elog-off"))
164 else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
168 return clib_error_return (0, "unknown input `%U'",
169 format_unformat_error, input);
171 unformat_free (line_input);
173 if (sw_if_index == ~0)
174 return clib_error_return (0,
175 "please specify interface name or sw_if_index");
177 hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
178 if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
179 return clib_error_return (0, "not a vmxnet3 interface");
181 vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
184 vd->flags |= VMXNET3_DEVICE_F_ELOG;
187 vd->flags &= ~VMXNET3_DEVICE_F_ELOG;
193 VLIB_CLI_COMMAND (vmxnet3_test_command, static) = {
194 .path = "test vmxnet3",
195 .short_help = "test vmxnet3 <interface> | sw_if_index <sw_idx> [irq] "
196 "[elog-on] [elog-off]",
197 .function = vmxnet3_test_command_fn,
202 show_vmxnet3 (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
203 u8 show_one_table, u32 which, u8 show_one_slot, u32 slot)
206 vmxnet3_device_t *vd;
207 vnet_main_t *vnm = &vnet_main;
208 vmxnet3_main_t *vmxm = &vmxnet3_main;
209 vnet_hw_interface_t *hi;
211 vmxnet3_rx_desc *rxd;
212 vmxnet3_rx_comp *rx_comp;
214 vmxnet3_tx_desc *txd;
215 vmxnet3_tx_comp *tx_comp;
218 vlib_cli_output (vm, "Global:");
219 for (u32 tid = 0; tid <= vlib_num_workers (); tid++)
221 vmxnet3_per_thread_data_t *ptd =
222 vec_elt_at_index (vmxm->per_thread_data, tid);
223 vlib_cli_output (vm, " Thread %u: polling queue count %u", tid,
224 ptd->polling_q_count);
230 for (i = 0; i < vec_len (hw_if_indices); i++)
232 hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
233 vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
234 vlib_cli_output (vm, "Interface: %U (ifindex %d)",
235 format_vnet_hw_if_index_name, vnm, hw_if_indices[i],
237 vlib_cli_output (vm, " Version: %u", vd->version);
238 vlib_cli_output (vm, " GSO enable: %u", vd->gso_enable);
239 vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
241 vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
243 vlib_cli_output (vm, " hw if index: %u", vd->hw_if_index);
244 vlib_cli_output (vm, " Device instance: %u", vd->dev_instance);
245 vlib_cli_output (vm, " Number of interrupts: %u", vd->num_intrs);
247 vec_foreach_index (qid, vd->rxqs)
249 rxq = vec_elt_at_index (vd->rxqs, qid);
252 vlib_cli_output (vm, " Queue %u (RX)", qid);
253 vlib_cli_output (vm, " RX completion next index %u",
254 rxq->rx_comp_ring.next);
255 vlib_cli_output (vm, " RX completion generation flag 0x%x",
256 rxq->rx_comp_ring.gen);
258 /* RX descriptors tables */
259 for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
261 vmxnet3_rx_ring *ring = &rxq->rx_ring[rid];
264 " ring %u size %u fill %u "
265 "consume %u produce %u", rid,
266 rxq->size, ring->fill, ring->consume,
270 vlib_cli_output (vm, "RX descriptors table");
271 vlib_cli_output (vm, " %5s %18s %10s",
272 "slot", "address", "flags");
273 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
275 rxd = &rxq->rx_desc[rid][desc_idx];
276 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
277 desc_idx, rxd->address, rxd->flags);
280 else if (show_one_table)
282 if (((which == VMXNET3_SHOW_RX_DESC0) && (rid == 0)) ||
283 ((which == VMXNET3_SHOW_RX_DESC1) && (rid == 1)))
285 vlib_cli_output (vm, "RX descriptors table");
286 vlib_cli_output (vm, " %5s %18s %10s",
287 "slot", "address", "flags");
290 rxd = &rxq->rx_desc[rid][slot];
291 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
292 slot, rxd->address, rxd->flags);
295 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
297 rxd = &rxq->rx_desc[rid][desc_idx];
298 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
299 desc_idx, rxd->address,
306 /* RX completion table */
309 vlib_cli_output (vm, "RX completion descriptors table");
310 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
311 "slot", "index", "rss", "len", "flags");
312 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
314 rx_comp = &rxq->rx_comp[desc_idx];
315 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
316 desc_idx, rx_comp->index, rx_comp->rss,
317 rx_comp->len, rx_comp->flags);
320 else if (show_one_table)
322 if (which == VMXNET3_SHOW_RX_COMP)
324 vlib_cli_output (vm, "RX completion descriptors table");
325 vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
326 "slot", "index", "rss", "len", "flags");
329 rx_comp = &rxq->rx_comp[slot];
330 vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
331 slot, rx_comp->index, rx_comp->rss,
332 rx_comp->len, rx_comp->flags);
335 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
337 rx_comp = &rxq->rx_comp[desc_idx];
339 " %5u 0x%08x %10u %10u 0x%08x",
340 desc_idx, rx_comp->index, rx_comp->rss,
341 rx_comp->len, rx_comp->flags);
347 vec_foreach_index (qid, vd->txqs)
349 txq = vec_elt_at_index (vd->txqs, qid);
350 vlib_cli_output (vm, " Queue %u (TX)", qid);
351 vlib_cli_output (vm, " TX completion next index %u",
352 txq->tx_comp_ring.next);
353 vlib_cli_output (vm, " TX completion generation flag 0x%x",
354 txq->tx_comp_ring.gen);
355 vlib_cli_output (vm, " size %u consume %u produce %u",
356 txq->size, txq->tx_ring.consume,
357 txq->tx_ring.produce);
360 vlib_cli_output (vm, "TX descriptors table");
361 vlib_cli_output (vm, " %5s %18s %10s %10s",
362 "slot", "address", "flags0", "flags1");
363 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
365 txd = &txq->tx_desc[desc_idx];
366 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
367 desc_idx, txd->address, txd->flags[0],
371 vlib_cli_output (vm, "TX completion descriptors table");
372 vlib_cli_output (vm, " %5s %10s %10s",
373 "slot", "index", "flags");
374 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
376 tx_comp = &txq->tx_comp[desc_idx];
377 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
378 desc_idx, tx_comp->index, tx_comp->flags);
381 else if (show_one_table)
383 if (which == VMXNET3_SHOW_TX_DESC)
385 vlib_cli_output (vm, "TX descriptors table");
386 vlib_cli_output (vm, " %5s %18s %10s %10s",
387 "slot", "address", "flags0", "flags1");
390 txd = &txq->tx_desc[slot];
391 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
392 slot, txd->address, txd->flags[0],
396 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
398 txd = &txq->tx_desc[desc_idx];
399 vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
400 desc_idx, txd->address, txd->flags[0],
404 else if (which == VMXNET3_SHOW_TX_COMP)
406 vlib_cli_output (vm, "TX completion descriptors table");
407 vlib_cli_output (vm, " %5s %10s %10s",
408 "slot", "index", "flags");
411 tx_comp = &txq->tx_comp[slot];
412 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
413 slot, tx_comp->index, tx_comp->flags);
416 for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
418 tx_comp = &txq->tx_comp[desc_idx];
419 vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
420 desc_idx, tx_comp->index,
429 static clib_error_t *
430 show_vmxnet3_fn (vlib_main_t * vm, unformat_input_t * input,
431 vlib_cli_command_t * cmd)
433 vmxnet3_main_t *vmxm = &vmxnet3_main;
434 vnet_main_t *vnm = &vnet_main;
435 vmxnet3_device_t *vd;
436 clib_error_t *error = 0;
437 u32 hw_if_index, *hw_if_indices = 0;
438 vnet_hw_interface_t *hi = 0;
439 u8 show_descr = 0, show_one_table = 0, show_one_slot = 0;
440 u32 which = ~0, slot;
442 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
445 (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
447 hi = vnet_get_hw_interface (vnm, hw_if_index);
448 if (vmxnet3_device_class.index != hi->dev_class_index)
450 error = clib_error_return (0, "unknown input `%U'",
451 format_unformat_error, input);
454 vec_add1 (hw_if_indices, hw_if_index);
456 else if (unformat (input, "desc"))
460 vmxnet3_device_t *vd =
461 vec_elt_at_index (vmxm->devices, hi->dev_instance);
463 if (unformat (input, "rx-comp"))
466 which = VMXNET3_SHOW_RX_COMP;
467 if (unformat (input, "%u", &slot))
469 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
471 if (slot >= rxq->size)
473 error = clib_error_return (0,
474 "slot size must be < rx queue "
475 "size %u", rxq->size);
481 else if (unformat (input, "rx-desc-0"))
484 which = VMXNET3_SHOW_RX_DESC0;
485 if (unformat (input, "%u", &slot))
487 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
489 if (slot >= rxq->size)
491 error = clib_error_return (0,
492 "slot size must be < rx queue "
493 "size %u", rxq->size);
499 else if (unformat (input, "rx-desc-1"))
502 which = VMXNET3_SHOW_RX_DESC1;
503 if (unformat (input, "%u", &slot))
505 vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
507 if (slot >= rxq->size)
509 error = clib_error_return (0,
510 "slot size must be < rx queue "
511 "size %u", rxq->size);
517 else if (unformat (input, "tx-comp"))
520 which = VMXNET3_SHOW_TX_COMP;
521 if (unformat (input, "%u", &slot))
523 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
525 if (slot >= txq->size)
527 error = clib_error_return (0,
528 "slot size must be < tx queue "
529 "size %u", txq->size);
535 else if (unformat (input, "tx-desc"))
538 which = VMXNET3_SHOW_TX_DESC;
539 if (unformat (input, "%u", &slot))
541 vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
543 if (slot >= txq->size)
545 error = clib_error_return (0,
546 "slot size must be < tx queue "
547 "size %u", txq->size);
555 error = clib_error_return (0, "unknown input `%U'",
556 format_unformat_error, input);
562 error = clib_error_return (0, "unknown input `%U'",
563 format_unformat_error, input);
568 if (vec_len (hw_if_indices) == 0)
570 pool_foreach (vd, vmxm->devices)
571 vec_add1 (hw_if_indices, vd->hw_if_index);
574 show_vmxnet3 (vm, hw_if_indices, show_descr, show_one_table, which,
575 show_one_slot, slot);
578 vec_free (hw_if_indices);
583 VLIB_CLI_COMMAND (show_vmxnet3_command, static) = {
584 .path = "show vmxnet3",
585 .short_help = "show vmxnet3 [[<interface>] ([desc] | ([rx-comp] | "
586 "[rx-desc-0] | [rx-desc-1] | [tx-comp] | [tx-desc]) [<slot>])]",
587 .function = show_vmxnet3_fn,
592 vmxnet3_cli_init (vlib_main_t * vm)
594 vmxnet3_main_t *vmxm = &vmxnet3_main;
595 vlib_thread_main_t *tm = vlib_get_thread_main ();
597 /* initialize binary API */
598 vmxnet3_plugin_api_hookup (vm);
600 vmxm->log_default = vlib_log_register_class ("vmxnet3", 0);
602 vec_validate (vmxm->per_thread_data, tm->n_vlib_mains - 1);
606 VLIB_INIT_FUNCTION (vmxnet3_cli_init);
609 * fd.io coding-style-patch-verification: ON
612 * eval: (c-set-style "gnu")