summaryrefslogtreecommitdiffstats
path: root/src/plugins/vmxnet3/cli.c
diff options
context:
space:
mode:
authorSteven Luong <sluong@cisco.com>2018-03-18 08:01:27 -0700
committerSteven <sluong@cisco.com>2018-09-14 14:27:41 -0700
commitdf7f8e8cffcc43531f7daeda44d436b60e538141 (patch)
tree1ff98cd205995a3c499048c5f93b11c9feda39c6 /src/plugins/vmxnet3/cli.c
parentef90ed08fbcde7535b4a789349b39dc25798c77d (diff)
vmxnet3 device driver
Implemented vmxnet3 deivice driver for VMWare ESXi. Tested with Ubuntu 18.04 connected to ESXi 6.0 Ubuntu-18.04 (VPP) --- ESXi-6.0 Change-Id: I85fbc86f2d8532b017bc4271612d17e24e498e4d Signed-off-by: Steven Luong <sluong@cisco.com>
Diffstat (limited to 'src/plugins/vmxnet3/cli.c')
-rw-r--r--src/plugins/vmxnet3/cli.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/plugins/vmxnet3/cli.c b/src/plugins/vmxnet3/cli.c
new file mode 100644
index 00000000000..3e3ab9d74f7
--- /dev/null
+++ b/src/plugins/vmxnet3/cli.c
@@ -0,0 +1,371 @@
+/*
+ *------------------------------------------------------------------
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *------------------------------------------------------------------
+ */
+#include <stdint.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+
+#include <vlib/vlib.h>
+#include <vlib/unix/unix.h>
+#include <vlib/pci/pci.h>
+#include <vnet/ethernet/ethernet.h>
+
+#include <vmxnet3/vmxnet3.h>
+
+static clib_error_t *
+vmxnet3_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ vmxnet3_create_if_args_t args = { 0 };
+ u32 tmp;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%U", unformat_vlib_pci_addr, &args.addr))
+ ;
+ else if (unformat (line_input, "elog"))
+ args.enable_elog = 1;
+ else if (unformat (line_input, "rx-queue-size %u", &tmp))
+ args.rxq_size = tmp;
+ else if (unformat (line_input, "tx-queue-size %u", &tmp))
+ args.txq_size = tmp;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ unformat_free (line_input);
+
+
+ vmxnet3_create_if (vm, &args);
+
+ return args.error;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
+ .path = "create interface vmxnet3",
+ .short_help = "create interface vmxnet3 <pci-address>"
+ "[rx-queue-size <size>] [tx-queue-size <size>]",
+ .function = vmxnet3_create_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+vmxnet3_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ u32 sw_if_index = ~0;
+ vnet_hw_interface_t *hw;
+ vmxnet3_main_t *vmxm = &vmxnet3_main;
+ vmxnet3_device_t *vd;
+ vnet_main_t *vnm = vnet_get_main ();
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
+ vnm, &sw_if_index))
+ ;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ unformat_free (line_input);
+
+ if (sw_if_index == ~0)
+ return clib_error_return (0,
+ "please specify interface name or sw_if_index");
+
+ hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
+ return clib_error_return (0, "not a vmxnet3 interface");
+
+ vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
+
+ vmxnet3_delete_if (vm, vd);
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (vmxnet3_delete_command, static) = {
+ .path = "delete interface vmxnet3",
+ .short_help = "delete interface vmxnet3 "
+ "{<interface> | sw_if_index <sw_idx>}",
+ .function = vmxnet3_delete_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+vmxnet3_test_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ u32 sw_if_index = ~0;
+ vnet_hw_interface_t *hw;
+ vmxnet3_main_t *vmxm = &vmxnet3_main;
+ vmxnet3_device_t *vd;
+ vnet_main_t *vnm = vnet_get_main ();
+ int enable_elog = 0, disable_elog = 0;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (line_input, "elog-on"))
+ enable_elog = 1;
+ else if (unformat (line_input, "elog-off"))
+ disable_elog = 1;
+ else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
+ vnm, &sw_if_index))
+ ;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ unformat_free (line_input);
+
+ if (sw_if_index == ~0)
+ return clib_error_return (0,
+ "please specify interface name or sw_if_index");
+
+ hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
+ return clib_error_return (0, "not a vmxnet3 interface");
+
+ vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
+
+ if (enable_elog)
+ vd->flags |= VMXNET3_DEVICE_F_ELOG;
+
+ if (disable_elog)
+ vd->flags &= ~VMXNET3_DEVICE_F_ELOG;
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (vmxnet3_test_command, static) = {
+ .path = "test vmxnet3",
+ .short_help = "test vmxnet3 <interface> | sw_if_index <sw_idx> [irq] "
+ "[elog-on] [elog-off]",
+ .function = vmxnet3_test_command_fn,
+};
+/* *INDENT-ON* */
+
+static void
+show_vmxnet3 (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr)
+{
+ u32 i, desc_idx;
+ vmxnet3_device_t *vd;
+ vnet_main_t *vnm = &vnet_main;
+ vmxnet3_main_t *vmxm = &vmxnet3_main;
+ vnet_hw_interface_t *hi;
+ vmxnet3_rxq_t *rxq;
+ vmxnet3_rx_desc *rxd;
+ vmxnet3_rx_comp *rx_comp;
+ vmxnet3_txq_t *txq;
+ vmxnet3_tx_desc *txd;
+ vmxnet3_tx_comp *tx_comp;
+ u16 qid;
+
+ if (!hw_if_indices)
+ return;
+
+ for (i = 0; i < vec_len (hw_if_indices); i++)
+ {
+ hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
+ vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
+ vlib_cli_output (vm, "Interface: %s (ifindex %d)",
+ hi->name, hw_if_indices[i]);
+ vlib_cli_output (vm, " Version: %u", vd->version);
+ vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
+ &vd->pci_addr);
+ vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
+ vd->mac_addr);
+ vlib_cli_output (vm, " hw if index: %u", vd->hw_if_index);
+ vlib_cli_output (vm, " Device instance: %u", vd->dev_instance);
+ vlib_cli_output (vm, " Number of interrupts: %u", vd->num_intrs);
+
+ vec_foreach_index (qid, vd->rxqs)
+ {
+ rxq = vec_elt_at_index (vd->rxqs, qid);
+ u16 rid;
+
+ vlib_cli_output (vm, " Queue %u (RX)", qid);
+ vlib_cli_output (vm, " RX completion next index %u",
+ rxq->rx_comp_ring.next);
+ for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
+ {
+ vmxnet3_rx_ring *ring = &rxq->rx_ring[rid];
+
+ vlib_cli_output (vm,
+ " ring %u size %u fill %u "
+ "consume %u produce %u", rid,
+ rxq->size, ring->fill, ring->consume,
+ ring->produce);
+ if (show_descr)
+ {
+ vlib_cli_output (vm, "RX descriptors table");
+ vlib_cli_output (vm, " %5s %18s %10s",
+ "slot", "address", "flags");
+ for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
+ {
+ rxd = &rxq->rx_desc[rid][desc_idx];
+ vlib_cli_output (vm, " %5u 0x%016llx 0x%08x",
+ desc_idx, rxd->address, rxd->flags);
+ }
+ vlib_cli_output (vm, "RX completion descriptors table");
+ vlib_cli_output (vm, " %5s %10s %10s %10s %10s",
+ "slot", "index", "rss", "len", "flags");
+ for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
+ {
+ rx_comp = &rxq->rx_comp[desc_idx];
+ vlib_cli_output (vm, " %5u 0x%08x %10u %10u 0x%08x",
+ desc_idx, rx_comp->index, rx_comp->rss,
+ rx_comp->len, rx_comp->flags);
+ }
+ }
+ }
+ }
+
+ vec_foreach_index (qid, vd->rxqs)
+ {
+ txq = vec_elt_at_index (vd->txqs, 0);
+ vlib_cli_output (vm, " Queue %u (TX)", qid);
+ vlib_cli_output (vm, " TX completion next index %u",
+ txq->tx_comp_ring.next);
+ vlib_cli_output (vm, " size %u consume %u produce %u",
+ txq->size, txq->tx_ring.consume,
+ txq->tx_ring.produce);
+ if (show_descr)
+ {
+ vlib_cli_output (vm, "TX descriptors table");
+ vlib_cli_output (vm, " %5s %18s %10s %10s",
+ "slot", "address", "flags0", "flags1");
+ for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
+ {
+ txd = &txq->tx_desc[desc_idx];
+ vlib_cli_output (vm, " %5u 0x%016llx 0x%08x 0x%08x",
+ desc_idx, txd->address, txd->flags[0],
+ txd->flags[1]);
+ }
+ vlib_cli_output (vm, "TX completion descriptors table");
+ vlib_cli_output (vm, " %5s %10s %10s",
+ "slot", "index", "flags");
+ for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
+ {
+ tx_comp = &txq->tx_comp[desc_idx];
+ vlib_cli_output (vm, " %5u 0x%08x 0x%08x",
+ desc_idx, tx_comp->index, tx_comp->flags);
+ }
+ }
+ }
+ }
+}
+
+static clib_error_t *
+show_vmxnet3_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vmxnet3_main_t *vmxm = &vmxnet3_main;
+ vnet_main_t *vnm = &vnet_main;
+ vmxnet3_device_t *vd;
+ clib_error_t *error = 0;
+ u32 hw_if_index, *hw_if_indices = 0;
+ vnet_hw_interface_t *hi;
+ u8 show_descr = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat
+ (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
+ {
+ hi = vnet_get_hw_interface (vnm, hw_if_index);
+ if (vmxnet3_device_class.index != hi->dev_class_index)
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ vec_add1 (hw_if_indices, hw_if_index);
+ }
+ else if (unformat (input, "descriptors") || unformat (input, "desc"))
+ show_descr = 1;
+ else
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ }
+
+ if (vec_len (hw_if_indices) == 0)
+ {
+ pool_foreach (vd, vmxm->devices,
+ vec_add1 (hw_if_indices, vd->hw_if_index);
+ );
+ }
+
+ show_vmxnet3 (vm, hw_if_indices, show_descr);
+
+done:
+ vec_free (hw_if_indices);
+ return error;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_vmxnet3_command, static) = {
+ .path = "show vmxnet3",
+ .short_help = "show vmxnet3 [<interface>]",
+ .function = show_vmxnet3_fn,
+};
+/* *INDENT-ON* */
+
+clib_error_t *
+vmxnet3_cli_init (vlib_main_t * vm)
+{
+ /* initialize binary API */
+ vmxnet3_plugin_api_hookup (vm);
+
+ return 0;
+}
+
+VLIB_INIT_FUNCTION (vmxnet3_cli_init);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */