summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Wiles <keith.wiles@intel.com>2017-09-09 17:57:49 -0500
committerKeith Wiles <keith.wiles@intel.com>2017-11-25 07:41:30 -0600
commita703810866cce1e0d5c66c9ba34563d8edaf8f51 (patch)
tree5e3602a7e32dedbdccf5ba96be41d2022ebb8540
parent5acd82537190698c45814f69137e1ac59bdfc85d (diff)
downloaddpdk-draft-cli-a703810866cce1e0d5c66c9ba34563d8edaf8f51.zip
dpdk-draft-cli-a703810866cce1e0d5c66c9ba34563d8edaf8f51.tar.gz
dpdk-draft-cli-a703810866cce1e0d5c66c9ba34563d8edaf8f51.tar.xz
test-pmd: include cli changes
-rw-r--r--app/test-pmd/Makefile5
-rw-r--r--app/test-pmd/cli_cmds.c4964
-rw-r--r--app/test-pmd/parameters.c38
-rw-r--r--app/test-pmd/testpmd.c22
-rw-r--r--app/test-pmd/testpmd.h3
5 files changed, 5030 insertions, 2 deletions
diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index d21308f..15463f0 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -46,10 +46,15 @@ CFLAGS += $(WERROR_FLAGS)
#
SRCS-y := testpmd.c
SRCS-y += parameters.c
+ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y)
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_tm.c
+endif
+ifeq ($(CONFIG_RTE_LIBRTE_CLI),y)
+SRCS-$(CONFIG_RTE_LIBRTE_CLI) += cli_cmds.c
+endif
SRCS-y += config.c
SRCS-y += iofwd.c
SRCS-y += macfwd.c
diff --git a/app/test-pmd/cli_cmds.c b/app/test-pmd/cli_cmds.c
new file mode 100644
index 0000000..e9cc547
--- /dev/null
+++ b/app/test-pmd/cli_cmds.c
@@ -0,0 +1,4964 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Created 2016 by Keith Wiles @ intel.com */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <libgen.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_devargs.h>
+#include <rte_eth_ctrl.h>
+#include <rte_flow.h>
+#include <rte_ip.h>
+#include <rte_net.h>
+#include <rte_string_fns.h>
+
+#ifdef RTE_LIBRTE_PMD_BOND
+#include <rte_eth_bond.h>
+#endif
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
+
+#include <cli.h>
+#include <cli_map.h>
+#include <cli_string_fns.h>
+
+#include "testpmd.h"
+
+static struct cli_map help_map[] = {
+ { 0, "help" },
+ { 10, "help %s" },
+ { -1, NULL }
+};
+
+#define STR_TOKEN_SIZE 128
+
+static uint32_t
+parse_list(char *str, const char *item_name, uint32_t max_items,
+ uint32_t *parsed_items, int check_unique_values)
+{
+ uint32_t nb_item, value, i, j;
+ int value_ok;
+ char c;
+
+ if (!str || !*str || !item_name || !parsed_items || !max_items)
+ return 0;
+
+ value = 0;
+ nb_item = 0;
+ value_ok = 0;
+
+ for (i = 0; i < strlen(str); i++) {
+ c = str[i];
+
+ if ((c >= '0') && (c <= '9')) {
+ value = (unsigned int)(value * 10 + (c - '0'));
+ value_ok = 1;
+ continue;
+ }
+
+ if (c != ',') {
+ printf("character %c is not a decimal digit\n", c);
+ return 0;
+ }
+
+ if (!value_ok) {
+ printf("No valid value before comma\n");
+ return 0;
+ }
+
+ if (nb_item < max_items) {
+ parsed_items[nb_item] = value;
+ value_ok = 0;
+ value = 0;
+ }
+
+ nb_item++;
+ }
+
+ if (nb_item >= max_items) {
+ printf("Number of %s = %u > %u (maximum items)\n",
+ item_name, nb_item + 1, max_items);
+ return 0;
+ }
+
+ parsed_items[nb_item++] = value;
+
+ if (check_unique_values)
+ /*
+ * Then, check that all values in the list are different.
+ * No optimization here...
+ */
+ for (i = 0; i < nb_item; i++) {
+ for (j = i + 1; j < nb_item; j++)
+ if (parsed_items[j] == parsed_items[i]) {
+ printf("duplicated %s %u at index %u and %u\n",
+ item_name, parsed_items[i], i, j);
+ return 0;
+ }
+ }
+ return nb_item;
+}
+
+static int
+help_cmd(int argc, char **argv)
+{
+ int control = 0, misc = 0, config = 0, ports = 0;
+ int registers = 0, filters = 0, hash = 0, show_all = 0;
+ int n = -1;
+
+ RTE_SET_USED(help_map);
+ if (argc > 1)
+ n = rte_stropt(
+ "control|misc|config|ports|registers|filters|hash|all",
+ argv[1], "|");
+
+ switch(n) {
+ case 0:
+ control = 1;
+ break;
+ case 1:
+ misc = 1;
+ break;
+ case 2:
+ config = 1;
+ break;
+ case 3:
+ ports = 1;
+ break;
+ case 4:
+ registers = 1;
+ break;
+ case 5:
+ filters = 1;
+ break;
+ case 6:
+ hash = 1;
+ break;
+ case 7:
+ show_all = 1;
+ break;
+ default:
+ cli_printf(
+ "\n"
+ "Help is available for the following sections:\n\n"
+ " help control : Start and stop forwarding.\n"
+ " help misc : debug and other commands.\n"
+ " help config : Configuration information.\n"
+ " help ports : Configuring ports.\n"
+ " help registers : Reading and setting port registers.\n"
+ " help filters : Filters configuration help.\n"
+ " help all : All of the above sections.\n\n"
+ );
+ return 0;
+ }
+
+ if (show_all || control)
+
+ cli_printf(
+ "\n"
+ "Control forwarding:\n"
+ "-------------------\n\n"
+
+ "start\n"
+ " Start packet forwarding with current configuration.\n\n"
+
+ "start tx_first\n"
+ " Start packet forwarding with current config"
+ " after sending one burst of packets.\n\n"
+
+ "stop\n"
+ " Stop packet forwarding, and display accumulated"
+ " statistics.\n\n"
+
+ "quit\n"
+ " Quit to prompt.\n\n"
+ );
+
+ if (show_all || misc)
+
+ cli_printf(
+ "\n"
+ "Misc:\n"
+ "--------\n\n"
+ "misc global_config (port-id) gre-key-len (len)\n\n"
+ "misc dump (physmen|memzone|struct_sizes|ring|mempool|devargs)\n\n"
+ "misc dump (ring|mempool) (name)\n\n"
+ "misc mcast_addr (add|remove) (port-id) (mac adddress)\n\n"
+ );
+
+ if (show_all || config) {
+ cli_printf(
+ "\n"
+ "Configuration:\n"
+ "--------------\n"
+ "Configuration changes only become active when"
+ " forwarding is started/restarted.\n\n"
+
+ "set default\n"
+ " Reset forwarding to the default configuration.\n\n"
+
+ "set verbose (level)\n"
+ " Set the debug verbosity level X.\n\n"
+
+ "set nbport (num)\n"
+ " Set number of ports.\n\n"
+
+ "set nbcore (num)\n"
+ " Set number of cores.\n\n"
+
+ "set coremask (mask)\n"
+ " Set the forwarding cores hexadecimal mask.\n\n"
+
+ "set portmask (mask)\n"
+ " Set the forwarding ports hexadecimal mask.\n\n"
+
+ "set burst (num)\n"
+ " Set number of packets per burst.\n\n"
+
+ "set burst tx delay (microseconds) retry (num)\n"
+ " Set the transmit delay time and number of retries,"
+ " effective when retry is enabled.\n\n"
+
+ "set txpkts (x[,y]*)\n"
+ " Set the length of each segment of TXONLY"
+ " and optionally CSUM packets.\n\n"
+
+ "set txsplit (off|on|rand)\n"
+ " Set the split policy for the TX packets."
+ " Right now only applicable for CSUM and TXONLY"
+ " modes\n\n"
+
+ "set corelist (x[,y]*)\n"
+ " Set the list of forwarding cores.\n\n"
+
+ "set portlist (x[,y]*)\n"
+ " Set the list of forwarding ports.\n\n"
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ "set tx loopback (port_id) (on|off)\n"
+ " Enable or disable tx loopback.\n\n"
+
+ "set all queues drop (port_id) (on|off)\n"
+ " Set drop enable bit for all queues.\n\n"
+
+ "set vf split drop (port_id) (vf_id) (on|off)\n"
+ " Set split drop enable bit for a VF from the PF.\n\n"
+
+ "set vf mac antispoof (port_id) (vf_id) (on|off).\n"
+ " Set MAC antispoof for a VF from the PF.\n\n"
+#endif
+
+ "set vlan strip (on|off) (port_id)\n"
+ " Set the VLAN strip on a port.\n\n"
+
+ "set vlan stripq (on|off) (port_id,queue_id)\n"
+ " Set the VLAN strip for a queue on a port.\n\n"
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ "set vf vlan stripq (port_id) (vf_id) (on|off)\n"
+ " Set the VLAN strip for all queues in a pool for a VF from the PF.\n\n"
+
+ "set vf vlan insert (port_id) (vf_id) (vlan_id)\n"
+ " Set VLAN insert for a VF from the PF.\n\n"
+
+ "set vf vlan antispoof (port_id) (vf_id) (on|off)\n"
+ " Set VLAN antispoof for a VF from the PF.\n\n"
+#endif
+
+ "set vlan filter (on|off) (port_id)\n"
+ " Set the VLAN filter on a port.\n\n"
+
+ "set vlan qinq (on|off) (port_id)\n"
+ " Set the VLAN QinQ (extended queue in queue)"
+ " on a port.\n\n"
+
+ "set vlan (inner|outer) tpid (value) (port_id)\n"
+ " Set the VLAN TPID for Packet Filtering on"
+ " a port\n\n"
+
+ "set rx_vlan add (vlan_id|all) (port_id)\n"
+ " Add a vlan_id, or all identifiers, to the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "set rx_vlan rm (vlan_id|all) (port_id)\n"
+ " Remove a vlan_id, or all identifiers, from the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "set rx_vlan add (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Add a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "set rx_vlan rm (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Remove a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "set rx_vxlan_port add (udp_port) (port_id)\n"
+ " Add an UDP port for VXLAN packet filter on a port\n\n"
+
+ "set rx_vxlan_port rm (udp_port) (port_id)\n"
+ " Remove an UDP port for VXLAN packet filter on a port\n\n"
+
+ "set tx_vlan (port_id) vlan_id[, vlan_id_outer]\n"
+ " Set hardware insertion of VLAN IDs (single or double VLAN "
+ "depends on the number of VLAN IDs) in packets sent on a port.\n\n"
+
+ "set tx_vlan pvid (port_id) (vlan_id) (on|off)\n"
+ " Set port based TX VLAN insertion.\n\n"
+
+ "set tx_vlan reset (port_id)\n"
+ " Disable hardware insertion of a VLAN header in"
+ " packets sent on a port.\n\n"
+
+ "set csum (ip|udp|tcp|sctp|outer-ip) (hw|sw) (port_id)\n"
+ " Select hardware or software calculation of the"
+ " checksum when transmitting a packet using the"
+ " csum forward engine.\n"
+ " ip|udp|tcp|sctp always concern the inner layer.\n"
+ " outer-ip concerns the outer IP layer in"
+ " case the packet is recognized as a tunnel packet by"
+ " the forward engine (vxlan, gre and ipip are supported)\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "set csum parse-tunnel (on|off) (tx_port_id)\n"
+ " If disabled, treat tunnel packets as non-tunneled"
+ " packets (treat inner headers as payload). The port\n"
+ " argument is the port used for TX in csum forward"
+ " engine.\n\n"
+
+ "show csum (port_id)\n"
+ " Display tx checksum offload configuration\n\n"
+
+ "set tso (segsize) (portid)\n"
+ " Enable TCP Segmentation Offload in csum forward"
+ " engine.\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "show tso (portid)"
+ " Display the status of TCP Segmentation Offload.\n\n"
+
+ "set fwd (%s)\n"
+ " Set packet forwarding mode.\n\n"
+
+ "set mac_addr add (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Add a MAC address on port_id.\n\n"
+
+ "set mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Remove a MAC address from port_id.\n\n"
+
+ "set mac_addr add port (port_id) vf (vf_id) (mac_address)\n"
+ " Add a MAC address for a VF on the port.\n\n"
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ "set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Set the MAC address for a VF from the PF.\n\n"
+#endif
+
+ "set port (port_id) uta (mac_address|all) (on|off)\n"
+ " Add/Remove a or all unicast hash filter(s)"
+ "from port X.\n\n"
+
+ "set promisc (port_id|all) (on|off)\n"
+ " Set the promiscuous mode on port_id, or all.\n\n"
+
+ "set allmulti (port_id|all) (on|off)\n"
+ " Set the allmulti mode on port_id, or all.\n\n"
+
+ "set flow_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd"
+ " (on|off) autoneg (on|off) (port_id)\n"
+ "set flow_ctrl rx (on|off) (portid)\n"
+ "set flow_ctrl tx (on|off) (portid)\n"
+ "set flow_ctrl high_water (high_water) (portid)\n"
+ "set flow_ctrl low_water (low_water) (portid)\n"
+ "set flow_ctrl pause_time (pause_time) (portid)\n"
+ "set flow_ctrl send_xon (send_xon) (portid)\n"
+ "set flow_ctrl mac_ctrl_frame_fwd (on|off) (portid)\n"
+ "set flow_ctrl autoneg (on|off) (port_id)\n"
+ " Set the link flow control parameter on a port.\n\n"
+
+ "set pfc_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (priority) (port_id)\n"
+ " Set the priority flow control parameter on a"
+ " port.\n\n"
+
+ "set stat_qmap (tx|rx) (port_id) (queue_id) (qmapping)\n"
+ " Set statistics mapping (qmapping 0..15) for RX/TX"
+ " queue on port.\n"
+ " e.g., 'set stat_qmap rx 0 2 5' sets rx queue 2"
+ " on port 0 to mapping 5.\n\n"
+
+ "set link-up port (port_id)\n"
+ " Set link up for a port.\n\n"
+
+ "set link-down port (port_id)\n"
+ " Set link down for a port.\n\n"
+
+ "set E-tag insertion on port-tag-id (value)"
+ " port (port_id) vf (vf_id)\n"
+ " Enable E-tag insertion for a VF on a port\n\n"
+
+ "set E-tag insertion off port (port_id) vf (vf_id)\n"
+ " Disable E-tag insertion for a VF on a port\n\n"
+
+ "set E-tag stripping (on|off) port (port_id)\n"
+ " Enable/disable E-tag stripping on a port\n\n"
+
+ "set E-tag forwarding (on|off) port (port_id)\n"
+ " Enable/disable E-tag based forwarding"
+ " on a port\n\n"
+
+ "set E-tag filter add e-tag-id (value) dst-pool"
+ " (pool_id) port (port_id)\n"
+ " Add an E-tag forwarding filter on a port\n\n"
+
+ "set E-tag filter del e-tag-id (value) port (port_id)\n"
+ " Delete an E-tag forwarding filter on a port\n\n"
+
+ ,
+ list_pkt_forwarding_modes()
+ );
+ }
+
+ if (show_all || ports) {
+
+ cli_printf(
+ "\n"
+ "Port Operations:\n"
+ "----------------\n\n"
+
+ "port start (port_id|all)\n"
+ " Start all ports or port_id.\n\n"
+
+ "port stop (port_id|all)\n"
+ " Stop all ports or port_id.\n\n"
+
+ "port close (port_id|all)\n"
+ " Close all ports or port_id.\n\n"
+
+ "port show|clear (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n"
+ " Clear information for port_id, or all.\n\n"
+
+ "port attach (ident)\n"
+ " Attach physical or virtual dev by pci address or virtual device name\n\n"
+
+ "port detach (port_id)\n"
+ " Detach physical or virtual dev by port_id\n\n"
+
+ "port config (port_id|all)"
+ " speed (10|100|1000|10000|25000|40000|50000|100000|auto)"
+ " duplex (half|full|auto)\n"
+ " Set speed and duplex for all ports or port_id\n\n"
+
+ "port config all (rxq|txq|rxd|txd) (value)\n"
+ " Set number for rxq/txq/rxd/txd.\n\n"
+
+ "port config all max-pkt-len (value)\n"
+ " Set the max packet length.\n\n"
+
+ "port config all (crc-strip|scatter|rx-cksum|hw-vlan|hw-vlan-filter|"
+ "hw-vlan-strip|hw-vlan-extend|drop-en)"
+ " (on|off)\n"
+ " Set crc-strip/scatter/rx-checksum/hardware-vlan/drop_en"
+ " for ports.\n\n"
+
+ "port config all rss (all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none)\n"
+ " Set the RSS mode.\n\n"
+
+ "port config port-id rss reta (hash,queue)[,(hash,queue)]\n"
+ " Set the RSS redirection table.\n\n"
+
+ "port config (port_id) dcb vt (on|off) (traffic_class)"
+ " pfc (on|off)\n"
+ " Set the DCB mode.\n\n"
+
+ "port config all burst (value)\n"
+ " Set the number of packets per burst.\n\n"
+
+ "port config all (txpt|txht|txwt|rxpt|rxht|rxwt)"
+ " (value)\n"
+ " Set the ring prefetch/host/writeback threshold"
+ " for tx/rx queue.\n\n"
+
+ "port config all (txfreet|txrst|rxfreet) (value)\n"
+ " Set free threshold for rx/tx, or set"
+ " tx rs bit threshold.\n\n"
+ "port config mtu X value\n"
+ " Set the MTU of port X to a given value\n\n"
+
+ "port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
+ " Start/stop a rx/tx queue of port X. Only take effect"
+ " when port X is started\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag ether-type"
+ " (value)\n"
+ " Set the value of E-tag ether-type.\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag"
+ " (enable|disable)\n"
+ " Enable/disable the E-tag support.\n\n"
+
+ "port show (info|stats|xstats|fdir|stat_qmap|dcb_tc) (port_id|all)\n"
+ " Display information for port_id, or all.\n\n"
+
+ "port show X rss reta (size) (mask0,mask1,...)\n"
+ " Display the rss redirection table entry indicated"
+ " by masks on port X. size is used to indicate the"
+ " hardware supported reta size\n\n"
+
+ "port show rss-hash ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|"
+ "ipv4-sctp|ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|"
+ "ipv6-other|l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex [key]\n"
+ " Display the RSS hash functions and RSS hash key"
+ " of port X\n\n"
+
+ "port set (port_id) vf (vf_id) rx|tx on|off\n"
+ " Enable/Disable a VF receive/tranmit from a port\n\n"
+
+ "port set (port_id) vf (vf_id) (mac_addr)"
+ " (exact-mac|exact-mac-vlan|hashmac|hashmac-vlan) on|off\n"
+ " Add/Remove unicast or multicast MAC addr filter"
+ " for a VF.\n\n"
+
+ "port set (port_id) vf (vf_id) rxmode (AUPE|ROPE|BAM"
+ "|MPE) (on|off)\n"
+ " AUPE:accepts untagged VLAN;"
+ "ROPE:accept unicast hash\n\n"
+ " BAM:accepts broadcast packets;"
+ "MPE:accepts all multicast packets\n\n"
+ " Enable/Disable a VF receive mode of a port\n\n"
+
+ "port set (port_id) queue (queue_id) rate (rate_num)\n"
+ " Set rate limit for a queue of a port\n\n"
+
+ "port set (port_id) vf (vf_id) rate (rate_num) "
+ "queue_mask (queue_mask_value)\n"
+ " Set rate limit for queues in VF of a port\n\n"
+
+ "port set (port_id) mirror-rule (rule_id)"
+ " (pool-mirror-up|pool-mirror-down|vlan-mirror)"
+ " (poolmask|vlanid[,vlanid]*) dst-pool (pool_id) (on|off)\n"
+ " Set pool or vlan type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 vlan-mirror 0,1"
+ " dst-pool 0 on' enable mirror traffic with vlan 0,1"
+ " to pool 0.\n\n"
+
+ "port set (port_id) mirror-rule (rule_id)"
+ " (uplink-mirror|downlink-mirror) dst-pool"
+ " (pool_id) (on|off)\n"
+ " Set uplink or downlink type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 uplink-mirror dst-pool"
+ " 0 on' enable mirror income traffic to pool 0.\n\n"
+
+ "port reset (port_id) mirror-rule (rule_id)\n"
+ " Reset a mirror rule.\n\n"
+
+ "port set flush_rx (on|off)\n"
+ " Flush (default) or don't flush RX streams before"
+ " forwarding. Mainly used with PCAP drivers.\n\n"
+
+#ifdef RTE_LIBRTE_PMD_BOND
+ "port bonding create device (mode) (socket)\n"
+ " Create a new bonded device with specific bonding mode and socket.\n\n"
+
+ "port bonding add slave (slave_id) (port_id)\n"
+ " Add a slave device to a bonded device.\n\n"
+
+ "port bonding remove slave (slave_id) (port_id)\n"
+ " Remove a slave device from a bonded device.\n\n"
+
+ "port bonding set mode (value) (port_id)\n"
+ " Set the bonding mode on a bonded device.\n\n"
+
+ "port bonding set primary (slave_id) (port_id)\n"
+ " Set the primary slave for a bonded device.\n\n"
+
+ "port bonding show config (port_id)\n"
+ " Show the bonding config for port_id.\n\n"
+
+ "port bonding set mac_addr (port_id) (address)\n"
+ " Set the MAC address of a bonded device.\n\n"
+
+ "port bonding set xmit_balance_policy (port_id) (l2|l23|l34)\n"
+ " Set the transmit balance policy for bonded device running in balance mode.\n\n"
+
+ "port bonding set mon_period (port_id) (value)\n"
+ " Set the bonding link status monitoring polling period in ms.\n\n"
+#endif
+#ifdef RTE_NIC_BYPASS
+ "port bypass set mode (normal|bypass|isolate) (port_id)\n"
+ " Set the bypass mode for the lowest port on bypass enabled"
+ " NIC.\n\n"
+
+ "port bypass set event (timeout|os_on|os_off|power_on|power_off) "
+ "mode (normal|bypass|isolate) (port_id)\n"
+ " Set the event required to initiate specified bypass mode for"
+ " the lowest port on a bypass enabled NIC where:\n"
+ " timeout = enable bypass after watchdog timeout.\n"
+ " os_on = enable bypass when OS/board is powered on.\n"
+ " os_off = enable bypass when OS/board is powered off.\n"
+ " power_on = enable bypass when power supply is turned on.\n"
+ " power_off = enable bypass when power supply is turned off."
+ "\n\n"
+
+ "port bypass set timeout (0|1.5|2|3|4|8|16|32)\n"
+ " Set the bypass watchdog timeout to 'n' seconds"
+ " where 0 = instant.\n\n"
+
+ "port bypass show config (port_id)\n"
+ " Show the bypass configuration for a bypass enabled NIC"
+ " using the lowest port on the NIC.\n\n"
+#endif
+ );
+ }
+
+ if (show_all || registers)
+
+ cli_printf(
+ "\n"
+ "Registers:\n"
+ "----------\n\n"
+
+ "reg read rxd (port_id) (queue_id) (rxd_id)\n"
+ " Display an RX descriptor of a port RX queue.\n\n"
+
+ "reg read txd (port_id) (queue_id) (txd_id)\n"
+ " Display a TX descriptor of a port TX queue.\n\n"
+
+ "reg read (port_id) (address)\n"
+ " Display value of a port register.\n\n"
+
+ "reg read field (port_id) (address) (bit_x) (bit_y)\n"
+ " Display a port register bit field.\n\n"
+
+ "reg read bit (port_id) (address) (bit_x)\n"
+ " Display a single port register bit.\n\n"
+
+ "reg write (port_id) (address) (value)\n"
+ " Set value of a port register.\n\n"
+
+ "reg write field (port_id) (address) (bit_x) (bit_y)"
+ " (value)\n"
+ " Set bit field of a port register.\n\n"
+
+ "reg write bit (port_id) (address) (bit_x) (value)\n"
+ " Set single bit value of a port register.\n\n"
+ );
+
+ if (show_all || filters)
+ cli_printf(
+ "\n"
+ "filters:\n"
+ "--------\n\n"
+
+ "filter ethertype (port_id) (add|del)"
+ " (mac_addr|mac_ignr) (mac_address) ethertype"
+ " (ether_type) (drop|fwd) queue (queue_id)\n"
+ " Add/Del an ethertype filter.\n\n"
+
+ "filter 2tuple (port_id) (add|del)"
+ " dst_port (dst_port_value) protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 2tuple filter.\n\n"
+
+ "filter 5tuple (port_id) (add|del)"
+ " dst_ip (dst_address) src_ip (src_address)"
+ " dst_port (dst_port_value) src_port (src_port_value)"
+ " protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 5tuple filter.\n\n"
+
+ "filter syn (port_id) (add|del) priority (high|low) queue (queue_id)"
+ " Add/Del syn filter.\n\n"
+
+ "filter flex (port_id) (add|del) len (len_value)"
+ " bytes (bytes_value) mask (mask_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a flex filter.\n\n"
+
+ "filter flow_director (port_id) mode IP (add|del|update)"
+ " flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag)"
+ " src (src_ip_address) dst (dst_ip_address)"
+ " tos (tos_value) proto (proto_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an IP type flow director filter.\n\n"
+
+ "filter flow_director (port_id) mode IP (add|del|update)"
+ " flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an UDP/TCP type flow director filter.\n\n"
+
+ "filter flow_director (port_id) mode IP (add|del|update)"
+ " flow (ipv4-sctp|ipv6-sctp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tag (verification_tag) "
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a SCTP type flow director filter.\n\n"
+
+ "filter flow_director (port_id) mode IP (add|del|update)"
+ " flow l2_payload ether (ethertype)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a l2 payload type flow director filter.\n\n"
+
+ "filter flow_director (port_id) mode MAC-VLAN (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a MAC-VLAN flow director filter.\n\n"
+
+ "filter flow_director (port_id) mode Tunnel (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " tunnel (NVGRE|VxLAN) tunnel-id (tunnel_id_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a Tunnel flow director filter.\n\n"
+
+ "filter flow_director flush (port_id)\n"
+ " Flush all flow director entries of a device.\n\n"
+
+ "filter flow_director mask (port_id) mode IP vlan (vlan_value)"
+ " src_mask (ipv4_src) (ipv6_src) (src_port)"
+ " dst_mask (ipv4_dst) (ipv6_dst) (dst_port)\n"
+ " Set flow director IP mask.\n\n"
+
+ "filter flow_director mask (port_id) mode MAC-VLAN"
+ " vlan (vlan_value)\n"
+ " Set flow director MAC-VLAN mask.\n\n"
+
+ "filter flow_director mask (port_id) mode Tunnel"
+ " vlan (vlan_value) mac (mac_value)"
+ " tunnel-type (tunnel_type_value)"
+ " tunnel-id (tunnel_id_value)\n"
+ " Set flow director Tunnel mask.\n\n"
+
+ "filter flow_director flex_mask (port_id)"
+ " flow (none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
+ "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload|all)"
+ " (mask)\n"
+ " Configure mask of flex payload.\n\n"
+
+ "filter flow_director flex_payload (port_id)"
+ " (raw|l2|l3|l4) (config)\n"
+ " Configure flex payload selection.\n\n"
+
+ "filter tunnel add (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " add a tunnel filter of a port.\n\n"
+
+ "filter tunnel rm (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " remove a tunnel filter of a port.\n\n"
+ );
+
+ if (show_all || hash)
+ cli_printf(
+ "\n"
+ "Hash:\n"
+ "----------\n\n"
+ "hash get sym_hash_ena_per_port (port_id)\n"
+ " get symmetric hash enable configuration per port.\n\n"
+
+ "hash set sym_hash_ena_per_port (port_id) (enable|disable)\n"
+ " set symmetric hash enable configuration per port"
+ " to enable or disable.\n\n"
+
+ "hash get hash_global_config (port_id)\n"
+ " Get the global configurations of hash filters.\n\n"
+
+ "hash set hash_global_config (port_id) (toeplitz|simple_xor|default)"
+ " (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)"
+ " (enable|disable)\n"
+ " Set the global configurations of hash filters.\n\n"
+
+ "hash set hash_input (port_id) (ipv4|ipv4-frag|"
+ "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|"
+ "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|"
+ "ipv6-next-header|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|"
+ "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|"
+ "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|"
+ "fld-8th|none) (select|add)\n"
+ " Set the input set for hash.\n\n"
+
+ "hash set fdir_input (port_id) "
+ "(ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload) (ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|"
+ "dst-ipv6|ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|"
+ "ipv6-next-header|ipv6-hop-limits|udp-src-port|"
+ "udp-dst-port|tcp-src-port|tcp-dst-port|"
+ "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)"
+ " (select|add)\n"
+ " Set the input set for FDir.\n\n"
+ );
+ return 0;
+}
+
+static struct cli_map control_map[] = {
+ { 0, "start" },
+ { 10, "start tx_first" },
+ { 11, "start tx_first %d" },
+ { 20, "stop" },
+ { -1, NULL }
+};
+
+static int
+control_cmd(int argc, char **argv)
+{
+ char *base = basename(argv[0]);
+ struct cli_map *m;
+
+ m = cli_mapping(control_map, argc, argv);
+ if (!m) {
+ cli_printf("Invalid command (%s)\n", base);
+ return -1;
+ }
+
+ switch(m->index) {
+ case 0:
+ start_packet_forwarding(0);
+ break;
+ case 10:
+ start_packet_forwarding(1);
+ break;
+ case 11:
+ start_packet_forwarding(atoi(argv[2]));
+ break;
+ case 20:
+ stop_packet_forwarding();
+ break;
+ default:
+ cli_printf("Invalid arg %s:%s\n", base, argv[1]);
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct cli_map set_map[] = {
+ { 0, "set default" },
+ { 10, "set %|nbport|nbcore|burst|verbose %d" },
+ { 20, "set %|coremask|portmask %H" },
+ { 30, "set burst tx delay %d retry %d" },
+ { 40, "set txpkts %l" },
+ { 50, "set txsplit %|on|off|rand" },
+ { 60, "set %|corelist|portlist %s" },
+ { 70, "set tx loopback %d %|on|off" },
+ { 80, "set all queues drop %d %|on|off" },
+ { 90, "set vf split drop %d %d %|on|off" },
+
+ { 100, "set vf mac antispoof %d %d %|on|off" },
+ { 110, "set vf vlan stripq %d %d %|on|off" },
+ { 120, "set vf vlan insert %d %d %d" },
+ { 130, "set vf vlan antispoof %d %d %|on|off" },
+ { 140, "set rx_vlan %|add|rm all %d" },
+ { 141, "set rx_vlan %|add|rm %d %d" },
+ { 150, "set rx_vlan %|add|rm %d port %d vf %D" },
+ { 160, "set rx_vxlan_port %|add|rm %d %d" },
+
+ { 200, "set tx_vlan %d %l" },
+ { 210, "set tx_vlan pvid %d %d %|on|off" },
+ { 220, "set tx_vlan reset %d" },
+ { 230, "set csum %|ip|udp|tcp|sctp|outer-ip %|hw|sw %d" },
+ { 240, "set csum parse-tunnel %|on|off %d" },
+ { 250, "set tso %d %d" },
+ {
+ 260,
+ "set fwd %|io|mac|macswap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588"
+ },
+ {
+ 261,
+ "set fwd %|io|mac|macswap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588 retry"
+ },
+ { 270, "set mac_addr %|add|remove %d %m" },
+ { 280, "set mac_addr add port %d vf %d %m" },
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ { 300, "set vf mac addr %d %d %m" },
+#endif
+ { 310, "set port %d uta %m %|on|off" },
+ { 320, "set port %d uta all %|on|off" },
+ { 330, "set promisc %d %|on|off" },
+ { 340, "set promisc all %|on|off" },
+ { 350, "set allmulti %d %|on|off" },
+ { 360, "set allmulti all %|on|off" },
+ { 370, "set flow_ctrl %|rx|tx %|on|off %d" },
+ { 380, "set flow_ctrl high_water %d %d" },
+
+ { 400, "set flow_ctrl low_water %d %d" },
+ { 410, "set flow_ctrl pause_time %d %d" },
+ { 420, "set flow_ctrl send_xon %d" },
+ { 430, "set flow_ctrl max_ctrl_frame_fwd %|on|off %d" },
+ { 440, "set flow_ctrl autoneg %|on|off %d" },
+ { 450, "set pfc_ctrl rx %|on|off tx %|on|off %d %d %d %d %d" },
+ { 460, "set stat_qmap %|tx|rx %d %d %d" },
+ { 470, "set flush_rx %|on|off" },
+ { 480, "set %|link-up|link-down port %d" },
+ { 490, "set E-tag insertion on port-tag-id %d port %d vf %d" },
+
+ { 500, "set E-tag insertion off port %d vf %d" },
+ { 510, "set E-tag stripping %|on|off port %d vf %d" },
+ { 520, "set E-tag forwarding %|on|off port %d vf %d" },
+ { 530, "set E-tag filter add e-tag-id %d dst-pool %d port %d" },
+ { 531, "set E-tag filter del e-tag-id %d port %d" },
+ { 540, "set vlan %|strip|filter|qinq|stripq %|on|off %l" },
+ { 550, "set vlan %|inner|outer tpid %d %d" },
+ { -1, NULL }
+};
+
+static void
+csum_show(int port_id)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t ol_flags;
+
+ ol_flags = ports[port_id].tx_ol_flags;
+ cli_printf("Parse tunnel is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_PARSE_TUNNEL) ? "on" : "off");
+ cli_printf("IP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) ? "hw" : "sw");
+ cli_printf("UDP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) ? "hw" : "sw");
+ cli_printf("TCP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) ? "hw" : "sw");
+ cli_printf("SCTP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) ? "hw" : "sw");
+ cli_printf("Outer-Ip checksum offload is %s\n",
+ (ol_flags &
+ TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ? "hw" : "sw");
+
+ /* display warnings if configuration is not supported by the NIC */
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0)
+ cli_printf("Warning: hardware IP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0)
+ cli_printf("Warning: hardware UDP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0)
+ cli_printf("Warning: hardware TCP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) == 0)
+ cli_printf("Warning: hardware SCTP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) == 0)
+ cli_printf("Warning: hardware outer IP checksum enabled but not "
+ "supported by port %d\n",
+ port_id);
+}
+
+static void
+cmd_link_flow_ctrl_set_parsed(int idx, uint8_t pid,
+ char *type, char *on_off,
+ uint32_t val)
+{
+ struct rte_eth_fc_conf fc_conf;
+ int rx_fc_en = 0;
+ int tx_fc_en = 0;
+ int ret;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_lfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL}
+ };
+
+ /* Partial command line, retrieve current configuration */
+ if (idx) {
+ ret = rte_eth_dev_flow_ctrl_get(pid, &fc_conf);
+ if (ret != 0) {
+ cli_printf("cannot get current flow ctrl parameters, return"
+ "code = %d\n", ret);
+ return;
+ }
+
+ if ((fc_conf.mode == RTE_FC_RX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ rx_fc_en = 1;
+ if ((fc_conf.mode == RTE_FC_TX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ tx_fc_en = 1;
+ }
+
+ if (idx == 370 && !strcmp("rx", type))
+ rx_fc_en = (!strcmp(on_off, "on")) ? 1 : 0;
+
+ if (idx == 370)
+ tx_fc_en = (!strcmp(on_off, "on")) ? 1 : 0;
+
+ fc_conf.mode = rx_tx_onoff_2_lfc_mode[rx_fc_en][tx_fc_en];
+
+ if (idx == 380)
+ fc_conf.high_water = val;
+
+ if (idx == 400)
+ fc_conf.low_water = val;
+
+ if (idx == 410)
+ fc_conf.pause_time = val;
+
+ if (idx == 420)
+ fc_conf.send_xon = val;
+
+ if (idx == 430) {
+ if (!strcmp(on_off, "on"))
+ fc_conf.mac_ctrl_frame_fwd = 1;
+ else
+ fc_conf.mac_ctrl_frame_fwd = 0;
+ }
+
+ if (idx == 440)
+ fc_conf.autoneg = (!strcmp(on_off, "on")) ? 1 : 0;
+
+ ret = rte_eth_dev_flow_ctrl_set(pid, &fc_conf);
+ if (ret != 0)
+ cli_printf("bad flow contrl parameter, return code = %d \n",
+ ret);
+}
+
+static void
+_err1(int err, uint8_t pid, int val)
+{
+ switch (err) {
+ case 0:
+ break;
+ case -EINVAL:
+ cli_printf("invalid is_on %d\n", val);
+ break;
+ case -ENODEV:
+ cli_printf("invalid port_id %d\n", pid);
+ break;
+ default:
+ cli_printf("programming error: (%s)\n", strerror(-err));
+ }
+}
+
+static void
+_err2(int err, uint8_t pid, int vid, int val)
+{
+ switch (err) {
+ case 0:
+ break;
+ case -EINVAL:
+ cli_printf("invalid vf %d is_on %d\n", vid, val);
+ break;
+ case -ENODEV:
+ cli_printf("invalid port_id %d\n", pid);
+ break;
+ default:
+ cli_printf("programming error: (%s)\n", strerror(-err));
+ }
+}
+
+static int
+set_cmd(int argc, char **argv)
+{
+ int val, n;
+ uint8_t pid;
+ uint16_t qid, vid, mask, eid, tid;
+ struct cli_map *m;
+ union {
+ unsigned segs[RTE_MAX_SEGS_PER_PKT];
+ unsigned int lcorelist[RTE_MAX_LCORE];
+ unsigned int portlist[RTE_MAX_ETHPORTS];
+ } parsed_items;
+ struct rte_eth_dev_info dev_info;
+ unsigned int nb_item;
+ char *opts[CLI_MAX_ARGVS+1];
+ uint64_t hex;
+
+ memset(opts, '\0', sizeof(opts));
+
+ m = cli_mapping(set_map, argc, argv);
+ if (!m)
+ return -1;
+
+ /* split up the format string into opts, do not modify original */
+ strcpy(this_cli->scratch, m->fmt);
+ rte_strtok(this_cli->scratch, " ", opts, CLI_MAX_ARGVS);
+
+ switch(m->index) {
+ case 0: /* Set default */
+ cli_printf("Reset to default forwarding configuration...\n");
+ set_def_fwd_config();
+ break;
+ case 10: /* set %|nbport|nbcore|burst|verbose %d */
+ val = atoi(argv[2]);
+
+ /* Skip the %| in the string options */
+ n = rte_stropt(&opts[1][2], argv[1], "|");
+
+ switch(n) {
+ case 0:
+ set_fwd_ports_number(val);
+ fwd_config_setup();
+ break;
+ case 1:
+ set_fwd_lcores_number(val);
+ fwd_config_setup();
+ break;
+ case 2:
+ set_nb_pkt_per_burst(val);
+ break;
+ case 3:
+ set_verbose_level(val);
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case 20: /* set %|coremask|portmask %H */
+ hex = strtoull(argv[2], NULL, 16);
+
+ /* Skip the %| in the string options */
+ n = rte_stropt(&opts[1][2], argv[1], "|");
+ switch(n) {
+ case 0:
+ set_fwd_lcores_mask(hex);
+ break;
+ case 1:
+ set_fwd_ports_mask(hex);
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case 30: /* set burst tx delay %d retry %d */
+ for (n = 3; n < argc; n++) {
+ if (!strcmp(argv[n], "delay"))
+ burst_tx_delay_time =
+ strtol(argv[n+1], NULL, 10);
+ if (!strcmp(argv[n], "retry"))
+ burst_tx_retry_num =
+ strtol(argv[n+1], NULL, 10);
+ }
+ break;
+ case 40: /* set txpkts %l */
+ nb_item = parse_list(argv[2], "segment_lengths",
+ RTE_MAX_SEGS_PER_PKT, parsed_items.segs,
+ 0);
+ if (nb_item)
+ set_tx_pkt_segments(parsed_items.segs, nb_item);
+ break;
+ case 50: /* set txsplit %|on|off|rand */
+ set_tx_pkt_split(argv[2]);
+ break;
+ case 60: /* set %|corelist|portlist %s */
+ n = rte_stropt(&opts[1][2], argv[1], "|");
+ switch(n) {
+ case 0:
+ nb_item = parse_list(argv[2], "core",
+ RTE_MAX_LCORE,
+ parsed_items.lcorelist, 1);
+ if (nb_item > 0) {
+ set_fwd_lcores_list(parsed_items.lcorelist,
+ nb_item);
+ fwd_config_setup();
+ }
+ break;
+ case 1:
+ nb_item = parse_list(argv[2], "port",
+ RTE_MAX_ETHPORTS,
+ parsed_items.portlist, 1);
+ if (nb_item > 0) {
+ set_fwd_ports_list(parsed_items.portlist,
+ nb_item);
+ fwd_config_setup();
+ }
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case 70: /* set tx loopback %d %|on|off */
+ pid = atoi(argv[3]);
+ val = (strcmp(argv[4], "on") == 0) ? 1 : 0;
+ n = rte_pmd_ixgbe_set_tx_loopback(pid, val);
+ _err1(n, pid, val);
+ break;
+ case 80: /* set all queues drop %d %|on|off */
+ pid = atoi(argv[4]);
+ val = (strcmp(argv[5], "on") == 0) ? 1 : 0;
+ n = rte_pmd_ixgbe_set_all_queues_drop_en(pid, val);
+ _err1(n, pid, val);
+ break;
+ case 90: /* set vf split drop %d %d %|on|off */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ val = (strcmp(argv[6], "on") == 0) ? 1 : 0;
+ n = rte_pmd_ixgbe_set_vf_split_drop_en(pid, vid, val);
+ _err2(n, pid, vid, val);
+ break;
+ case 100: /* set vf mac antispoof %d %d %|on|off */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ val = (strcmp(argv[6], "on") == 0) ? 1 : 0;
+ n = rte_pmd_ixgbe_set_vf_mac_anti_spoof(pid, vid, val);
+ _err2(n, pid, vid, val);
+ break;
+ case 110: /* set vf vlan stripq %d %d %|on|off */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ val = (strcmp(argv[6], "on") == 0) ? 1 : 0;
+ n = rte_pmd_ixgbe_set_vf_vlan_stripq(pid, vid, val);
+ _err2(n, pid, vid, val);
+ break;
+ case 120: /* set vf vlan insert %d %d %d */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ val = atoi(argv[6]);
+
+ n = rte_pmd_ixgbe_set_vf_vlan_insert(pid, vid, val);
+ _err2(n, pid, vid, val);
+ break;
+ case 130: /* set vf vlan antispoof %d %d %|on|off */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ val = (strcmp(argv[6], "on") == 0) ? 1 : 0;
+
+ n = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(pid, vid, val);
+ _err2(n, pid, vid, val);
+ break;
+ case 140: /* set rx_vlan %|add|rm all %d */
+ pid = atoi(argv[4]);
+ if (!strcmp(argv[2], "add"))
+ rx_vlan_all_filter_set(pid, 1);
+ else
+ rx_vlan_all_filter_set(pid, 0);
+ break;
+ case 141: /* set rx_vlan %|add|rm %d %d */
+ vid = atoi(argv[3]);
+ pid = atoi(argv[4]);
+ if (!strcmp(argv[2], "add"))
+ rx_vft_set(pid, vid, 1);
+ else
+ rx_vft_set(pid, vid, 0);
+ break;
+ case 150: { /* set rx_vlan %|add|rm %d port %d vf %D */
+ int ret = -ENOTSUP;
+ __rte_unused int is_add = (strcmp(argv[2], "add") == 0) ? 1 : 0;
+
+ vid = atoi(argv[3]);
+ pid = atoi(argv[5]);
+ hex = strtoull(argv[7], NULL, 10);
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_filter(pid, vid, hex,
+ is_add);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_filter(pid, vid, hex,
+ is_add);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vlan_id %d or vf_mask %" PRIu64 "\n",
+ vid, hex);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", pid);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+ }
+ break;
+ case 160: { /* set rx_vxlan_port %|add|rm %d %d */
+ struct rte_eth_udp_tunnel tunnel_udp;
+
+ val = atoi(argv[3]);
+ pid = atoi(argv[4]);
+
+ tunnel_udp.udp_port = val;
+
+ if (!strcmp(argv[1], "rx_vxlan_port"))
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ if (!strcmp(argv[2], "add"))
+ n = rte_eth_dev_udp_tunnel_port_add(pid, &tunnel_udp);
+ else
+ n = rte_eth_dev_udp_tunnel_port_delete(pid, &tunnel_udp);
+
+ if (n < 0)
+ cli_printf("udp tunneling add error: (%s)\n",
+ strerror(-n));
+ }
+ break;
+ case 200: /* set tx_vlan %d %l */
+ pid = atoi(argv[2]);
+ vid = atoi(argv[3]);
+ tx_vlan_set(pid, vid);
+ break;
+ case 210: /* set tx_vlan pvid %d %d %|on|off */
+ pid = atoi(argv[3]);
+ vid = atoi(argv[4]);
+ val = (strcmp(argv[5], "on") == 0) ? 1 : 0;
+ tx_vlan_pvid_set(pid, vid, val);
+ break;
+ case 220: /* set tx_vlan reset %d */
+ pid = atoi(argv[3]);
+ tx_vlan_reset(pid);
+ break;
+ case 230: /* set csum %|ip|udp|tcp|sctp|outer-ip %|hw|sw %d */
+ pid = atoi(argv[4]);
+ val = (strcmp(argv[3], "hw") == 0) ? 1 : 0;
+ if (!strcmp(argv[2], "ip"))
+ mask = TESTPMD_TX_OFFLOAD_IP_CKSUM;
+ else if (!strcmp(argv[2], "udp"))
+ mask = TESTPMD_TX_OFFLOAD_UDP_CKSUM;
+ else if (!strcmp(argv[2], "tcp"))
+ mask = TESTPMD_TX_OFFLOAD_TCP_CKSUM;
+ else if (!strcmp(argv[2], "sctp"))
+ mask = TESTPMD_TX_OFFLOAD_SCTP_CKSUM;
+ else if (!strcmp(argv[2], "outer-ip"))
+ mask = TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM;
+ else
+ mask = 0;
+
+ if (val)
+ ports[pid].tx_ol_flags |= mask;
+ else
+ ports[pid].tx_ol_flags &= (~mask);
+ csum_show(pid);
+ break;
+ case 240: /* set csum parse-tunnel %|on|off %d */
+ pid = atoi(argv[4]);
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ if (val)
+ ports[pid].tx_ol_flags |=
+ TESTPMD_TX_OFFLOAD_PARSE_TUNNEL;
+ else
+ ports[pid].tx_ol_flags &=
+ ~TESTPMD_TX_OFFLOAD_PARSE_TUNNEL;
+ csum_show(pid);
+ break;
+ case 250: /* set tso %d %d */
+ pid = atoi(argv[2]);
+ val = atoi(argv[3]);
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return -1;
+
+ ports[pid].tso_segsz = val;
+
+ if (ports[pid].tso_segsz == 0)
+ cli_printf("TSO for non-tunneled packets is disabled\n");
+ else
+ cli_printf(
+ "TSO segment size for non-tunneled packets is %d\n",
+ ports[pid].tso_segsz);
+
+ /* display warnings if configuration is not supported by the NIC */
+ rte_eth_dev_info_get(pid, &dev_info);
+ if ((ports[pid].tso_segsz != 0) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0)
+ cli_printf("Warning: TSO enabled but not "
+ "supported by port %d\n", pid);
+ break;
+ case 260: /* set fwd %|io|mac|macswap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588 */
+ retry_enabled = 0;
+ set_pkt_forwarding_mode(argv[2]);
+ break;
+ case 261: /* set fwd %|io|mac|macswap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588 retry */
+ retry_enabled = 1;
+ set_pkt_forwarding_mode(argv[2]);
+ break;
+ case 270: /* set mac_addr %|add|remove %d %m */
+ pid = atoi(argv[3]);
+ val = (strcmp(argv[2], "add") == 0) ? 1 : 0;
+ if (val)
+ n =
+ rte_eth_dev_mac_addr_add(pid,
+ rte_ether_aton(argv[4], NULL), 0);
+ else
+ n =
+ rte_eth_dev_mac_addr_remove(pid,
+ rte_ether_aton(argv[4], NULL));
+
+ if (n < 0)
+ cli_printf("mac_addr_cmd error: (%s)\n", strerror(-n));
+ break;
+ case 280: /* set mac_addr add port %d vf %d %m */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ n = rte_eth_dev_mac_addr_add(pid,
+ rte_ether_aton(argv[7], NULL), vid);
+ if(n < 0)
+ cli_printf("vf_mac_addr_cmd error: (%s)\n",
+ strerror(-n));
+ break;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ case 300: /* set vf mac addr %d %d %m */
+ pid = atoi(argv[4]);
+ vid = atoi(argv[5]);
+ n = rte_pmd_ixgbe_set_vf_mac_addr(pid, vid,
+ rte_ether_aton(argv[6], NULL));
+ _err2(n, pid, vid, 0);
+ break;
+#endif
+ case 310: /* set port %d uta %m %|on|off */
+ pid = atoi(argv[2]);
+ val = (strcmp(argv[5], "on") == 0) ? 1 : 0;
+ n = rte_eth_dev_uc_hash_table_set(pid,
+ rte_ether_aton(argv[4],
+ NULL),
+ (uint8_t)val);
+ if (n < 0)
+ cli_printf("bad unicast hash table parameter,"
+ " return code = %d \n", n);
+ break;
+ case 320: /* set port %d uta all %|on|off */
+ pid = atoi(argv[2]);
+ val = (strcmp(argv[5], "on") == 0) ? 1 : 0;
+ n = rte_eth_dev_uc_all_hash_table_set(pid, (uint8_t)val);
+ if (n < 0)
+ cli_printf("bad unicast hash table parameter,"
+ " return code = %d \n", n);
+ break;
+ case 330: /* set promisc %d %|on|off */
+ pid = atoi(argv[2]);
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ if (val)
+ rte_eth_promiscuous_disable(pid);
+ else
+ rte_eth_promiscuous_disable(pid);
+ break;
+ case 340: /* set promisc all %|on|off */
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ RTE_ETH_FOREACH_DEV(pid) {
+ if (val)
+ rte_eth_promiscuous_disable(pid);
+ else
+ rte_eth_promiscuous_disable(pid);
+ }
+ break;
+ case 350: /* set allmulti %d %|on|off */
+ pid = atoi(argv[2]);
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ if (val)
+ rte_eth_allmulticast_enable(pid);
+ else
+ rte_eth_allmulticast_disable(pid);
+ break;
+ case 360: /* set almulti all %|on|off */
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ RTE_ETH_FOREACH_DEV(pid) {
+ if (val)
+ rte_eth_allmulticast_enable(pid);
+ else
+ rte_eth_allmulticast_disable(pid);
+ }
+ break;
+ case 370: /* set flow_ctrl %|rx|tx %|on|off %d */
+ pid = atoi(argv[4]);
+ val = (strcmp(argv[3], "on") == 0) ? 1 : 0;
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, argv[2], argv[3],
+ 0);
+ break;
+ case 380: /* set flow_ctrl high_water %d %d */
+ pid = atoi(argv[4]);
+ val = atoi(argv[3]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, NULL, val);
+ break;
+
+ case 400: /* set flow_ctrl low_water %d %d */
+ pid = atoi(argv[4]);
+ val = atoi(argv[3]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, NULL, val);
+ break;
+ case 410: /* set flow_ctrl pause_time %d %d */
+ pid = atoi(argv[4]);
+ val = atoi(argv[3]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, NULL, val);
+ break;
+ case 420: /* set flow_ctrl send_xon %d */
+ pid = atoi(argv[3]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, NULL, 0);
+ break;
+ case 430: /* set flow_ctrl max_ctrl_frame_fwd %|on|off %d */
+ pid = atoi(argv[4]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, argv[3], 0);
+ break;
+ case 440: /* set flow_ctrl autoneg %|on|off %d */
+ pid = atoi(argv[4]);
+ cmd_link_flow_ctrl_set_parsed(m->index, pid, NULL, argv[3], 0);
+ break;
+ case 450: { /* set pfc_ctrl rx %|on|off tx %|on|off %d %d %d %d %d */
+ struct rte_eth_pfc_conf pfc_conf;
+ int rx_fc_enable, tx_fc_enable;
+
+ pid = atoi(argv[10]);
+ val = (!strcmp(argv[3], "on")) ? 1 : 0;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_pfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_RX_PAUSE},
+ {RTE_FC_TX_PAUSE, RTE_FC_FULL}
+ };
+
+ rx_fc_enable = (!strcmp(argv[3], "on")) ? 1 : 0;
+ tx_fc_enable = (!strcmp(argv[5], "on")) ? 1 : 0;
+ pfc_conf.fc.mode =
+ rx_tx_onoff_2_pfc_mode[rx_fc_enable][tx_fc_enable];
+ pfc_conf.fc.high_water = atoi(argv[6]);
+ pfc_conf.fc.low_water = atoi(argv[7]);
+ pfc_conf.fc.pause_time = atoi(argv[8]);
+ pfc_conf.priority = atoi(argv[9]);
+
+ n = rte_eth_dev_priority_flow_ctrl_set(pid, &pfc_conf);
+ if (n != 0)
+ cli_printf(
+ "bad priority flow contrl parameter, return code = %d \n",
+ n);
+ }
+ break;
+ case 460: /* set stat_qmap %|tx|rx %d %d %d */
+ pid = atoi(argv[3]);
+ qid = atoi(argv[4]);
+ val = atoi(argv[5]);
+ set_qmap(pid, (!strcmp(argv[2],"tx")) ? 0 : 1, qid, val);
+ break;
+ case 470: /* set flush_rx %|on|off */
+ no_flush_rx = (!strcmp(argv[2], "on")) ? 0 : 1;
+ break;
+ case 480: /* set %|link-up|link-down port %d */
+ val = (!strcmp(argv[1], "link-up")) ? 1 : 0;
+ pid = atoi(argv[3]);
+ if (val)
+ dev_set_link_up(pid);
+ else
+ dev_set_link_down(pid);
+ break;
+ case 490: { /* set E-tag insertion on port-tag-id %d port %d vf %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ val = atoi(argv[5]);
+ pid = atoi(argv[7]);
+ vid = atoi(argv[9]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = val;
+ entry.vf_id = vid;
+ rte_eth_dev_l2_tunnel_offload_set(pid,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 1);
+ }
+ break;
+ case 500: { /* set E-tag insertion off port %d vf %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ pid = atoi(argv[5]);
+ vid = atoi(argv[7]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.vf_id = vid;
+ rte_eth_dev_l2_tunnel_offload_set(pid,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 0);
+ }
+ break;
+ case 510: { /* set E-tag stripping %|on|off port %d vf %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ val = (!strcmp(argv[3], "on")) ? 1 : 0;
+ pid = atoi(argv[7]);
+ vid = atoi(argv[9]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ rte_eth_dev_l2_tunnel_offload_set(pid, &entry,
+ ETH_L2_TUNNEL_STRIPPING_MASK,
+ val);
+ }
+ break;
+ case 520: { /* set E-tag forwarding %|on|off port %d vf %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ val = (!strcmp(argv[3], "on")) ? 1 : 0;
+ pid = atoi(argv[7]);
+ vid = atoi(argv[9]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ rte_eth_dev_l2_tunnel_offload_set(pid, &entry,
+ ETH_L2_TUNNEL_FORWARDING_MASK,
+ val);
+ }
+ break;
+ case 530: { /* set E-tag filter add e-tag-id %d dst-pool %d port %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ eid = atoi(argv[5]);
+ qid = atoi(argv[7]);
+ pid = atoi(argv[9]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ if (eid > 0x3fff) {
+ cli_printf(
+ "e-tag-id must be equal or less than 0x3fff.\n");
+ return 0;
+ }
+
+ n = rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (n < 0) {
+ cli_printf("E-tag filter is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = eid;
+ entry.pool = qid;
+
+ n = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &entry);
+ if (n < 0)
+ cli_printf("E-tag filter programming error: (%s)\n",
+ strerror(-n));
+ }
+ break;
+ case 531: { /* set E-tag filter del e-tag-id %d port %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ eid = atoi(argv[5]);
+ pid = atoi(argv[7]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ if (eid > 0x3fff) {
+ cli_printf(
+ "e-tag-id must be equal or less than 0x3fff.\n");
+ return 0;
+ }
+
+ n = rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (n < 0) {
+ cli_printf(
+ "E-tag filter is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = eid;
+
+ n = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &entry);
+ if (n < 0)
+ cli_printf("E-tag filter programming error: (%s)\n",
+ strerror(-n));
+ }
+ break;
+ case 540: { /* set vlan %|strip|filter|qinq|stripq %|on|off %l */
+ int on;
+ char *str;
+ int i, len = 0;
+ unsigned int tmp;
+
+ str = argv[4];
+ len = strnlen(str, STR_TOKEN_SIZE);
+ i = 0;
+ /* Get port_id first */
+ while(i < len) {
+ if(str[i] == ',')
+ break;
+
+ i++;
+ }
+ str[i]='\0';
+ tmp = strtoul(str, NULL, 0);
+ /* If port_id greater that what portid_t can represent, return */
+ if(tmp >= RTE_MAX_ETHPORTS)
+ return 0;
+ pid = (portid_t)tmp;
+
+ if (!strcmp(argv[3], "on"))
+ on = 1;
+ else
+ on = 0;
+
+ if (!strcmp(argv[2], "strip"))
+ rx_vlan_strip_set(pid, on);
+ else if(!strcmp(argv[2], "stripq")) {
+ uint16_t queue_id = 0;
+
+ /* No queue_id, return */
+ if(i + 1 >= len) {
+ cli_printf("must specify (port,queue_id)\n");
+ return 0;
+ }
+ tmp = strtoul(str + i + 1, NULL, 0);
+ /* If queue_id greater that what 16-bits can represent, return */
+ if(tmp > 0xffff)
+ return 0;
+
+ queue_id = (uint16_t)tmp;
+ rx_vlan_strip_set_on_queue(pid, queue_id, on);
+ } else if (!strcmp(argv[2], "filter"))
+ rx_vlan_filter_set(pid, on);
+ else
+ vlan_extend_set(pid, on);
+ }
+ break;
+ case 550: /* set vlan %|inner|outer tpid %d %d */
+ pid = atoi(argv[5]);
+ tid = atoi(argv[4]);
+ val = (!strcmp(argv[2], "inner")) ?
+ ETH_VLAN_TYPE_INNER : ETH_VLAN_TYPE_OUTER;
+ vlan_tpid_set(pid, val, tid);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct cli_map port_map[] = {
+ { 0, "port reset %d mirror-rule %d" },
+ { 10, "port %|start|stop|close %d" },
+ { 20, "port %|start|stop|close all" },
+ { 70, "port attach %s" },
+ { 80, "port detach %d" },
+ {
+ 90,
+ "port %|show|clear %|info|stats|xstats|fdir|stat_qmap|dcb_tc %d"
+ },
+ { 100, "port show %|rxq|txq info %d %d" },
+ { 110, "port show %|rxd|txd %d %d %d" },
+ { 170, "port set %d vf %d %|tx|rx %|on|off" },
+ {
+ 180,
+ "port set %d vf %d %m %|exact-mac|exact-mac-vlan|hashmac|hashmac-vlan %|on|off"
+ },
+ { 190, "port set %d vf %d rxmode %|AUPE|ROPE|BAM|MPE %|on|off" },
+ { 200, "port set %d queue %d rate %d" },
+ { 210, "port set %d vf %d rate %d queue_mask %D" },
+ {
+ 220,
+ "port set %d mirror-rule %d %|pool-mirror-up|pool-mirror-down|vlan-mirror %s dst-pool %d %|on|off"
+ },
+ {
+ 230,
+ "port set %d mirror-rule %d %|uplink-mirror|downlink-mirror dst-pool %d %|on|off"
+ },
+ {
+ 240,
+ "port config %d speed %|10|100|1000|10000|2500|40000|50000|100000|auto duplex %|half|full|auto"
+ },
+ {
+ 250,
+ "port config all speed %|10|100|1000|10000|2500|40000|50000|100000|auto duplex %|half|full|auto"
+ },
+ { 260, "port config all %|rxq|txq|rxd|txd %d" },
+ { 270, "port config all max-pkt-len %d" },
+ {
+ 280,
+ "port config all %|crc-strip|scatter|rx-cksum|hw-vlan|hw-vlan-filter|hw-vlan-strip|hw-vlan-extend|drop-en %|on|off"
+ },
+ {
+ 290,
+ "port config all rss %|all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none"
+ },
+ { 300, "port config %d rss reta %l" },
+ { 310, "port config %d dcb vt %|on|off %d pfc %|on|off" },
+ { 320, "port config all burst %d" },
+ { 330, "port config all %|txpt|txht|txwt|rxpt|rxht|rxwt %d" },
+ { 340, "port config all %|txfreet|txrst|rxfreet %d" },
+ { 350, "port config %d %|rxq|txq %d %|start|stop" },
+ { 360, "port config all l2-tunnel E-tag ether-type %d" },
+ { 370, "port config %d l2-tunnel E-tag ether-type %d" },
+ { 380, "port config all l2-tunnel E-tag %|enable|disable" },
+ { 390, "port config %d l2-tunnel E-tag %|enable|disable" },
+#ifdef RTE_LIBRTE_PMD_BOND
+ { 400, "port bonding create device %d %d" },
+ { 410, "port bonding add slave %d %d" },
+ { 420, "port bonding remove slave %d %d" },
+ { 430, "port bonding show config %d" },
+ { 440, "port bonding set mode %d %d" },
+ { 450, "port bonding set primary %d %d" },
+ { 460, "port bonding set mac_addr %d %m" },
+ { 470, "port bonding set slave %d %d" },
+ { 480, "port bonding set xmit_balance_policy %d %|l2|l23|l34" },
+ { 490, "port bonding set mon_period %d %d" },
+#endif
+#ifdef RTE_NIC_BYPASS
+ { 500, "port bypass set mode %|normal|bypass|isolate %d" },
+ {
+ 510,
+ "port bypass set event %|timeout|os_on|os_off|power_on|power_off mode %|normal|bypass|isolate %d"
+ },
+ { 520, "port bypass set timeout %|0|1.5|2|3|4|8|16|32" },
+ { 530, "port bypass show config %d" },
+#endif
+ { -1, NULL }
+};
+
+static void
+cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)
+{
+ if (id == (portid_t)RTE_PORT_ALL) {
+ portid_t pid;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[pid].need_reconfig == 0)
+ ports[pid].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[pid].need_reconfig_queues == 0)
+ ports[pid].need_reconfig_queues = queue;
+ }
+ } else if (!port_id_is_invalid(id, DISABLED_WARN)) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[id].need_reconfig == 0)
+ ports[id].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[id].need_reconfig_queues == 0)
+ ports[id].need_reconfig_queues = queue;
+ }
+}
+
+static uint8_t
+hexa_digit_to_value(char hexa_digit)
+{
+ if ((hexa_digit >= '0') && (hexa_digit <= '9'))
+ return (uint8_t) (hexa_digit - '0');
+ if ((hexa_digit >= 'a') && (hexa_digit <= 'f'))
+ return (uint8_t) ((hexa_digit - 'a') + 10);
+ if ((hexa_digit >= 'A') && (hexa_digit <= 'F'))
+ return (uint8_t) ((hexa_digit - 'A') + 10);
+ /* Invalid hexa digit */
+ return 0xFF;
+}
+
+static inline uint8_t
+parse_and_check_key_hexa_digit(char *key, int idx)
+{
+ return hexa_digit_to_value(key[idx]);
+}
+
+static int
+parse_reta_config(const char *str,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries)
+{
+ int i;
+ unsigned size;
+ uint16_t hash_index, idx, shift;
+ uint16_t nb_queue;
+ char s[256];
+ const char *p, *p0 = str;
+ char *end;
+ enum fieldnames {
+ FLD_HASH_INDEX = 0,
+ FLD_QUEUE,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD,
+ ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] ||
+ int_fld[i] > 65535)
+ return -1;
+ }
+
+ hash_index = (uint16_t)int_fld[FLD_HASH_INDEX];
+ nb_queue = (uint16_t)int_fld[FLD_QUEUE];
+
+ if (hash_index >= nb_entries)
+ return -1;
+
+ idx = hash_index / RTE_RETA_GROUP_SIZE;
+ shift = hash_index % RTE_RETA_GROUP_SIZE;
+ reta_conf[idx].mask |= (1ULL << shift);
+ reta_conf[idx].reta[shift] = nb_queue;
+ }
+
+ return 0;
+}
+
+static enum rte_eth_tunnel_type
+str2fdir_l2_tunnel_type(char *string) {
+ uint32_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_tunnel_type type;
+ } l2_tunnel_type_str[] = {
+ {"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+ };
+
+ for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++)
+ if (!strcmp(l2_tunnel_type_str[i].str, string))
+ return l2_tunnel_type_str[i].type;
+ return RTE_TUNNEL_TYPE_NONE;
+}
+
+#ifdef RTE_LIBRTE_PMD_BOND
+static int bond_dev_num = 0;
+#endif
+
+static int
+port_cmd(int argc, char **argv)
+{
+ int val, n;
+ uint8_t pid;
+ uint16_t qid, vid, rule, pool;
+ uint32_t speed, uval;
+ uint64_t mask;
+ struct cli_map *m;
+
+ m = cli_mapping(port_map, argc, argv);
+ if (!m)
+ return -1;
+
+ switch(m->index) {
+ case 0: /* port reset %d mirror-rule %d */
+ pid = atoi(argv[1]);
+ val = atoi(argv[3]);
+ n = rte_eth_mirror_rule_reset(pid, val);
+ if (n < 0)
+ cli_printf("mirror rule remove error: (%s)\n",
+ strerror(-n));
+ break;
+ case 10: /* port %|start|stop|close %d */
+ pid = atoi(argv[2]);
+ n = rte_stropt("start|stop|close", argv[1], "|");
+ switch(n) {
+ case 0:
+ start_port(pid);
+ break;
+ case 1:
+ stop_port(pid);
+ break;
+ case 2:
+ close_port(pid);
+ break;
+ }
+ break;
+ case 20: /* port %|start|stop|close all */
+ n = rte_stropt("start|stop|close", argv[1], "|");
+ switch(n) {
+ case 0:
+ start_port(RTE_PORT_ALL);
+ break;
+ case 1:
+ stop_port(RTE_PORT_ALL);
+ break;
+ case 2:
+ close_port(RTE_PORT_ALL);
+ break;
+ }
+ break;
+ case 70: /* port attach %s */
+ attach_port(argv[2]);
+ break;
+ case 80: /* port detach %d */
+ detach_port(atoi(argv[2]));
+ break;
+ case 90: /* port %|show|clear %|info|stats|xstats|fdir|stat_qmap|dcb_tc %d */
+ pid = atoi(argv[3]);
+ n = rte_stropt("info|stats|xstats|fdir|stat_qmap|dcb_tc",
+ argv[2], "|");
+ if (!strcmp(argv[1],"show"))
+ switch(n) {
+ case 0:
+ port_infos_display(pid);
+ break;
+ case 1:
+ nic_stats_display(pid);
+ break;
+ case 2:
+ nic_xstats_display(pid);
+ break;
+ case 3:
+ fdir_get_infos(pid);
+ break;
+ case 4:
+ nic_stats_mapping_display(pid);
+ break;
+ case 5:
+ port_dcb_info_display(pid);
+ break;
+ default:
+ break;
+ } else
+ switch(n) {
+ case 0:
+ return -1; /* Info is invalid for clear */
+ case 1:
+ nic_stats_clear(pid);
+ break;
+ case 2:
+ nic_xstats_clear(pid);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 100: /* port show %|rxq|txq info %d %d */
+ pid = atoi(argv[4]);
+ qid = atoi(argv[5]);
+ if (!strcmp(argv[2], "rxq"))
+ rx_queue_infos_display(pid, qid);
+ else
+ tx_queue_infos_display(pid, qid);
+ break;
+ case 110: /* port show %|rxd|txd %d %d %d */
+ pid = atoi(argv[3]);
+ qid = atoi(argv[4]);
+ val = atoi(argv[5]);
+ if (!strcmp(argv[2], "rxd"))
+ rx_ring_desc_display(pid, qid, val);
+ else
+ tx_ring_desc_display(pid, qid, val);
+ break;
+ case 170: /* port set %d vf %d %|tx|rx %|on|off */
+ pid = atoi(argv[2]);
+ vid = atoi(argv[4]);
+ val = (!strcmp(argv[6], "on")) ? 1 : 0;
+ set_vf_traffic(pid, val, vid, (!strcmp(argv[5], "rx")) ? 1 : 0);
+ break;
+ case 180: { /* port set %d vf %d %m %|exact-mac|exact-mac-vlan|hashmac|hashmac-vlan %|on|off */
+ struct rte_eth_mac_filter filter;
+
+ memset(&filter, 0, sizeof(struct rte_eth_mac_filter));
+
+ rte_memcpy(&filter.mac_addr, rte_ether_aton(argv[5],
+ NULL),
+ ETHER_ADDR_LEN);
+
+ pid = atoi(argv[2]);
+ vid = atoi(argv[4]);
+ val =
+ (!strcmp(argv[7],
+ "on")) ? RTE_ETH_FILTER_ADD :
+ RTE_ETH_FILTER_DELETE;
+
+ n = rte_stropt("exact-mac|exact-mac-vlan|hashmac|hashmac-vlan",
+ argv[6], "|");
+ switch(n) {
+ case 0:
+ filter.filter_type = RTE_MAC_PERFECT_MATCH;
+ break;
+ case 1:
+ filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+ break;
+ case 2:
+ filter.filter_type = RTE_MAC_HASH_MATCH;
+ break;
+ case 3:
+ filter.filter_type = RTE_MACVLAN_HASH_MATCH;
+ break;
+ }
+ n = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_MACVLAN, val,
+ &filter);
+ if (n < 0)
+ cli_printf(
+ "bad set MAC hash parameter, return code = %d\n",
+ n);
+ }
+ break;
+ case 190: { /* port set %d vf %d rxmode %|AUPE|ROPE|BAM|MPE %|on|off */
+ uint16_t rx_mode = 0;
+
+ pid = atoi(argv[2]);
+ vid = atoi(argv[4]);
+ val = (!strcmp(argv[7], "on")) ? 1 : 0;
+ n = rte_stropt("AUPE|ROPE|BAM|MPE", argv[6], "|");
+ switch(n) {
+ case 0:
+ rx_mode |= ETH_VMDQ_ACCEPT_UNTAG;
+ break;
+ case 1:
+ rx_mode |= ETH_VMDQ_ACCEPT_HASH_UC;
+ break;
+ case 2:
+ rx_mode |= ETH_VMDQ_ACCEPT_BROADCAST;
+ break;
+ case 3:
+ rx_mode |= ETH_VMDQ_ACCEPT_MULTICAST;
+ break;
+ }
+ if (rte_pmd_ixgbe_set_vf_rxmode(pid, vid, rx_mode, val) < 0)
+ cli_printf(
+ "bad VF receive mode parameter, return code = %d \n",
+ n);
+ }
+ break;
+ case 200: /* port set %d queue %d rate %d */
+ pid = atoi(argv[2]);
+ qid = atoi(argv[4]);
+ val = atoi(argv[6]);
+ if ((n = set_queue_rate_limit(pid, qid, val)) < 0)
+ cli_printf("queue_rate_limit_cmd error: (%s)\n", strerror(
+ -n));
+ break;
+ case 210: /* port set %d vf %d rate %d queue_mask %D */
+ pid = atoi(argv[2]);
+ vid = atoi(argv[4]);
+ val = atoi(argv[6]);
+ mask = strtoull(argv[8], NULL, 10);
+ if ((n = set_vf_rate_limit(pid, vid, val, mask)) < 0)
+ cli_printf("vf_rate_limit_cmd error: (%s)\n",
+ strerror(-n));
+ break;
+ case 220: { /* port set %d mirror-rule %d %|pool-mirror-up|pool-mirror-down|vlan-mirror %s dst-pool %d %|on|off */
+ int ret,nb_item,i;
+ struct rte_eth_mirror_conf mr_conf;
+
+ pid = atoi(argv[2]);
+ rule = atoi(argv[4]);
+ pool = atoi(argv[8]);
+ val = (!strcmp(argv[9], "on")) ? 1 : 0;
+
+ memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
+
+ unsigned int vlan_list[ETH_MIRROR_MAX_VLANS];
+
+ mr_conf.dst_pool = pool;
+
+ if (!strcmp(argv[5], "pool-mirror-up")) {
+ mr_conf.pool_mask = strtoull(argv[6], NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_UP;
+ } else if (!strcmp(argv[5], "pool-mirror-down")) {
+ mr_conf.pool_mask = strtoull(argv[6], NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_DOWN;
+ } else if (!strcmp(argv[5], "vlan-mirror")) {
+ mr_conf.rule_type = ETH_MIRROR_VLAN;
+ nb_item = parse_list(argv[6], "vlan",
+ ETH_MIRROR_MAX_VLANS, vlan_list,
+ 1);
+ if (nb_item <= 0)
+ return -1;
+
+ for (i = 0; i < nb_item; i++) {
+ if (vlan_list[i] > ETHER_MAX_VLAN_ID) {
+ cli_printf(
+ "Invalid vlan_id: must be < 4096\n");
+ return -1;
+ }
+
+ mr_conf.vlan.vlan_id[i] =
+ (uint16_t)vlan_list[i];
+ mr_conf.vlan.vlan_mask |= 1ULL << i;
+ }
+ }
+
+ ret = rte_eth_mirror_rule_set(pid, &mr_conf, rule, val);
+ if (ret < 0)
+ cli_printf("mirror rule add error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 240: /* port config %d speed %|10|100|1000|10000|2500|40000|50000|100000|auto duplex %|half|full|auto */
+ case 250: { /* port config all speed %|10|100|1000|10000|2500|40000|50000|100000|auto duplex %|half|full|auto */
+ uint32_t speeds[] = {
+ ETH_LINK_SPEED_10M, ETH_LINK_SPEED_100M,
+ ETH_LINK_SPEED_1G, ETH_LINK_SPEED_10G,
+ ETH_LINK_SPEED_25G,
+ ETH_LINK_SPEED_40G, ETH_LINK_SPEED_50G,
+ ETH_LINK_SPEED_100G,
+ ETH_LINK_SPEED_AUTONEG
+ };
+ pid = atoi(argv[2]);
+ n = rte_stropt("10|100|1000|10000|2500|40000|50000|100000|auto",
+ argv[4], "|");
+ if (!strcmp(argv[6], "half") && (n > 1))
+ return -1;
+ speed = speeds[n];
+ if (!strcmp(argv[6], "half")) {
+ if (n == 0)
+ speed = ETH_LINK_SPEED_10M_HD;
+ else if (n == 1)
+ speed = ETH_LINK_SPEED_100M_HD;
+ }
+ if (m->index == 250) {
+ RTE_ETH_FOREACH_DEV(pid) {
+ ports[pid].dev_conf.link_speeds = speed;
+ }
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ } else {
+ ports[pid].dev_conf.link_speeds = speed;
+ cmd_reconfig_device_queue(pid, 1, 1);
+ }
+ }
+ break;
+ case 260: { /* port config all %|rxq|txq|rxd|txd %d */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all port first\n");
+ return 0;
+ }
+ val = atoi(argv[4]);
+ n = rte_stropt("rxq|txq|rxd|txd", argv[3], "|");
+ switch(n) {
+ case 0:
+ if (val == 0) return -1;
+ nb_rxq = val;
+ break;
+ case 1:
+ if (val == 0) return -1;
+ nb_txq = val;
+ break;
+ case 2:
+ if (val <= 0 || val > RTE_TEST_RX_DESC_MAX) return -1;
+ nb_rxd = val;
+ break;
+ case 3:
+ if (val <= 0 || val > RTE_TEST_TX_DESC_MAX) return -1;
+ nb_txd = val;
+ break;
+ }
+
+ fwd_config_setup();
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ }
+ break;
+ case 270: /* port config all max-pkt-len %d */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all ports first\n");
+ return 0;
+ }
+ uval = strtoul(argv[4], NULL, 10);
+ if (uval < ETHER_MIN_LEN)
+ return -1;
+ if (uval == rx_mode.max_rx_pkt_len)
+ return 0;
+ rx_mode.max_rx_pkt_len = uval;
+ if (uval > ETHER_MAX_LEN)
+ rx_mode.jumbo_frame = 1;
+ else
+ rx_mode.jumbo_frame = 0;
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ break;
+ case 280: /* port config all %|crc-strip|scatter|rx-cksum|hw-vlan|hw-vlan-filter|hw-vlan-strip|hw-vlan-extend}drop-en %|on|off */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all ports first\n");
+ return -1;
+ }
+
+ val = (!strcmp(argv[4], "on")) ? 1 : 0;
+ n = rte_stropt(
+ "crc-strip|scatter|rx-cksum|hw-vlan|hw-vlan-filter|hw-vlan-strip|hw-vlan-extend|drop-en",
+ argv[3], "|");
+ switch(n) {
+ case 0:
+ rx_mode.hw_strip_crc = val;
+ break;
+ case 1:
+ rx_mode.enable_scatter = val;
+ break;
+ case 2:
+ rx_mode.hw_ip_checksum = val;
+ break;
+ case 3:
+ rx_mode.hw_vlan_filter = val;
+ rx_mode.hw_vlan_strip = val;
+ break;
+ case 4:
+ rx_mode.hw_vlan_filter = val;
+ break;
+ case 5:
+ rx_mode.hw_vlan_strip = val;
+ break;
+ case 6:
+ rx_mode.hw_vlan_extend = val;
+ break;
+ case 7:
+ rx_drop_en = val;
+ break;
+ }
+ init_port_config();
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ break;
+ case 290: { /* port config all rss %|all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none */
+ struct rte_eth_rss_conf rss_conf;
+ int diag;
+ uint8_t i;
+
+ n = rte_stropt(
+ "all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none",
+ argv[4], "|");
+ switch(n) {
+ case 0:
+ rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_TCP |
+ ETH_RSS_UDP | ETH_RSS_SCTP |
+ ETH_RSS_L2_PAYLOAD;
+ break;
+ case 1:
+ rss_conf.rss_hf = ETH_RSS_IP;
+ break;
+ case 2:
+ rss_conf.rss_hf = ETH_RSS_UDP;
+ break;
+ case 3:
+ rss_conf.rss_hf = ETH_RSS_TCP;
+ break;
+ case 4:
+ rss_conf.rss_hf = ETH_RSS_SCTP;
+ break;
+ case 5:
+ rss_conf.rss_hf = ETH_RSS_L2_PAYLOAD;
+ break;
+ case 6:
+ rss_conf.rss_hf = ETH_RSS_PORT;
+ break;
+ case 7:
+ rss_conf.rss_hf = ETH_RSS_VXLAN;
+ break;
+ case 8:
+ rss_conf.rss_hf = ETH_RSS_GENEVE;
+ break;
+ case 9:
+ rss_conf.rss_hf = ETH_RSS_NVGRE;
+ break;
+ case 10:
+ rss_conf.rss_hf = 0;
+ break;
+ }
+ rss_conf.rss_key = NULL;
+ for (i = 0; i < rte_eth_dev_count(); i++) {
+ diag = rte_eth_dev_rss_hash_update(i, &rss_conf);
+ if (diag < 0)
+ cli_printf("Configuration of RSS hash at ethernet port %d "
+ "failed with error (%d): %s.\n",
+ i, -diag, strerror(
+ -diag));
+ }
+ }
+ break;
+ case 300: { /* port config %d rss reta %l */
+ int ret;
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rss_reta_entry64 reta_conf[8];
+
+ pid = atoi(argv[2]);
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(pid, &dev_info);
+ if (dev_info.reta_size == 0) {
+ cli_printf("Redirection table size is 0 which is "
+ "invalid for RSS\n");
+ return -1;
+ } else
+ cli_printf("The reta size of port %d is %u\n",
+ pid, dev_info.reta_size);
+ if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) {
+ cli_printf("Currently do not support more than %u entries of "
+ "redirection table\n",
+ ETH_RSS_RETA_SIZE_512);
+ return -1;
+ }
+
+ memset(reta_conf, 0, sizeof(reta_conf));
+ if (parse_reta_config(argv[5], reta_conf,
+ dev_info.reta_size)) {
+ cli_printf("Invalid RSS Redirection Table "
+ "config entered\n");
+ return -1;
+ }
+ ret = rte_eth_dev_rss_reta_update(pid,
+ reta_conf,
+ dev_info.reta_size);
+ if (ret != 0)
+ cli_printf("Bad redirection table parameter, "
+ "return code = %d \n", ret);
+ }
+ break;
+ case 310: { /* port config %d dcb vt %|on|off %d pfc %|on|off */
+ struct rte_port *port;
+ uint8_t pfc_en;
+ int ret;
+
+ pid = atoi(argv[2]);
+ val = atoi(argv[6]);
+
+ port = &ports[pid];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ cli_printf("Please stop port %d first\n", pid);
+ return -1;
+ }
+
+ if ((val != ETH_4_TCS) && (val != ETH_8_TCS)) {
+ cli_printf("The invalid number of traffic class,"
+ " only 4 or 8 allowed.\n");
+ return -1;
+ }
+
+ if (nb_fwd_lcores < val) {
+ cli_printf(
+ "nb_cores shouldn't be less than number of TCs.\n");
+ return -1;
+ }
+ if (!strncmp(argv[8], "on", 2))
+ pfc_en = 1;
+ else
+ pfc_en = 0;
+
+ /* DCB in VT mode */
+ if (!strncmp(argv[5], "on", 2))
+ ret = init_port_dcb_config(pid, DCB_VT_ENABLED,
+ (enum rte_eth_nb_tcs)val,
+ pfc_en);
+ else
+ ret = init_port_dcb_config(pid, DCB_ENABLED,
+ (enum rte_eth_nb_tcs)val,
+ pfc_en);
+
+ if (ret != 0) {
+ cli_printf("Cannot initialize network ports.\n");
+ return -1;
+ }
+
+ cmd_reconfig_device_queue(pid, 1, 1);
+ }
+ break;
+ case 320: /* port config all burst %d */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all ports first\n");
+ return 0;
+ }
+
+ val = atoi(argv[4]);
+ nb_pkt_per_burst = val;
+
+ init_port_config();
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ break;
+ case 330: /* port config all %|txpt|txht|txwt|rxpt|rxht|rxwt %d */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all ports first\n");
+ return 0;
+ }
+ val = atoi(argv[4]);
+ n = rte_stropt("txpt|txht|txwt|rxpt|rxht|rxwt", argv[3], "|");
+ switch(n) {
+ case 0:
+ tx_pthresh = val;
+ break;
+ case 1:
+ tx_hthresh = val;
+ break;
+ case 2:
+ tx_wthresh = val;
+ break;
+ case 3:
+ rx_pthresh = val;
+ break;
+ case 4:
+ rx_hthresh = val;
+ break;
+ case 5:
+ rx_wthresh = val;
+ break;
+ }
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ break;
+ case 340: /* port config all %|txfreet|txrst|rxfreet %d */
+ if (!all_ports_stopped()) {
+ cli_printf("Please stop all ports first\n");
+ return 0;
+ }
+ val = atoi(argv[4]);
+ val = atoi(argv[4]);
+ n = rte_stropt("txfreet|txrst|rxfreet", argv[3], "|");
+ switch(n) {
+ case 0:
+ tx_free_thresh = val;
+ break;
+ case 1:
+ tx_rs_thresh = val;
+ break;
+ case 2:
+ rx_free_thresh = val;
+ break;
+ }
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+ break;
+ case 350: { /* port config %d %|rxq|txq %d %|start|stop */
+ uint8_t isrx;
+ uint8_t isstart;
+ int ret = 0;
+
+ if (test_done == 0) {
+ cli_printf("Please stop forwarding first\n");
+ return 0;
+ }
+ pid = atoi(argv[2]);
+ qid = atoi(argv[4]);
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return -1;
+
+ if (port_is_started(pid) != 1) {
+ cli_printf("Please start port %u first\n", pid);
+ return -1;
+ }
+
+ isrx = (!strcmp(argv[3], "rxq")) ? 1 : 0;
+
+ if (isrx && rx_queue_id_is_invalid(qid))
+ return -1;
+ else if (!isrx && tx_queue_id_is_invalid(qid))
+ return -1;
+
+ isstart = (!strcmp(argv[5], "start")) ? 1 : 0;
+
+ if (isstart && isrx)
+ ret = rte_eth_dev_rx_queue_start(pid, qid);
+ else if (!isstart && isrx)
+ ret = rte_eth_dev_rx_queue_stop(pid, qid);
+ else if (isstart && !isrx)
+ ret = rte_eth_dev_tx_queue_start(pid, qid);
+ else
+ ret = rte_eth_dev_tx_queue_stop(pid, qid);
+
+ if (ret == -ENOTSUP)
+ cli_printf("Function not supported in PMD driver\n");
+ }
+ break;
+ case 360: /* port config all l2-tunnel E-tag ether-type %d */
+ case 370: { /* port config %d l2-tunnel E-tag ether-type %d */
+ struct rte_eth_l2_tunnel_conf entry;
+
+ val = atoi(argv[6]);
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(argv[4]);
+ entry.ether_type = val;
+
+ if (m->index == 360)
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_eth_type_conf(pid,
+ &entry);
+ } else {
+ pid = atoi(argv[2]);
+ rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+ }
+ }
+ break;
+ case 380: /* port config all l2-tunnel E-tag %|enable|disable */
+ case 390: { /* port config %d l2-tunnel E-tag %|enable|disable */
+ struct rte_eth_l2_tunnel_conf entry;
+ uint8_t en;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(argv[4]);
+
+ en = (!strcmp("enable", argv[5])) ? 1 : 0;
+
+ if (m->index == 380)
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_offload_set(pid, &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK, en);
+ } else {
+ pid = atoi(argv[2]);
+ rte_eth_dev_l2_tunnel_offload_set(pid, &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK, en);
+ }
+ }
+ break;
+#ifdef RTE_LIBRTE_PMD_BOND
+ case 400: { /* port bonding create device %d %d */
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+ if (test_done == 0) {
+ cli_printf("Please stop forwarding first\n");
+ return -1;
+ }
+
+ snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN,
+ "net_bond_testpmd_%d",
+ bond_dev_num++);
+
+ /* Create a new bonded device. */
+ n = rte_eth_bond_create(ethdev_name, atoi(argv[4]), atoi(
+ argv[5]));
+ if (n < 0) {
+ cli_printf("\t Failed to create bonded device.\n");
+ return -1;
+ } else {
+ pid = n;
+ cli_printf("Created new bonded device %s on (port %d).\n",
+ ethdev_name, pid);
+
+ /* Update number of ports */
+ nb_ports = rte_eth_dev_count();
+ reconfig(pid, atoi(argv[5]));
+ rte_eth_promiscuous_enable(pid);
+ }
+ }
+ break;
+ case 410: /* port bonding add slave %d %d */
+ pid = atoi(argv[5]);
+ val = atoi(argv[4]);
+
+ /* Set the primary slave for a bonded device. */
+ if (rte_eth_bond_slave_add(pid, val)) {
+ cli_printf("\t Failed to add slave %d to master port = %d.\n",
+ val, pid);
+ return -1;
+ }
+ init_port_config();
+ set_port_slave_flag(val);
+ break;
+ case 420: /* port bonding remove slave %d %d */
+ pid = atoi(argv[5]);
+ val = atoi(argv[4]);
+
+ /* Set the primary slave for a bonded device. */
+ if (rte_eth_bond_slave_remove(pid, val)) {
+ cli_printf("\t Failed to remove slave %d to master port = %d.\n",
+ val, pid);
+ return -1;
+ }
+ init_port_config();
+ clear_port_slave_flag(val);
+ break;
+ case 430: { /* port bonding show config %d */
+ int bonding_mode;
+ uint8_t slaves[RTE_MAX_ETHPORTS];
+ int num_slaves, num_active_slaves;
+ int primary_id;
+ int i;
+
+ pid = atoi(argv[4]);
+
+ /* Display the bonding mode.*/
+ bonding_mode = rte_eth_bond_mode_get(pid);
+ if (bonding_mode < 0) {
+ cli_printf("\tFailed to get bonding mode for port = %d\n",
+ pid);
+ return -1;
+ } else
+ cli_printf("\tBonding mode: %d\n", bonding_mode);
+
+ if (bonding_mode == BONDING_MODE_BALANCE) {
+ int balance_xmit_policy;
+
+ balance_xmit_policy = rte_eth_bond_xmit_policy_get(pid);
+ if (balance_xmit_policy < 0) {
+ cli_printf("\tFailed to get balance xmit policy for port = %d\n",
+ pid);
+ return -1;
+ } else {
+ cli_printf("\tBalance Xmit Policy: ");
+
+ switch (balance_xmit_policy) {
+ case BALANCE_XMIT_POLICY_LAYER2:
+ cli_printf("BALANCE_XMIT_POLICY_LAYER2");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER23:
+ cli_printf("BALANCE_XMIT_POLICY_LAYER23");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER34:
+ cli_printf("BALANCE_XMIT_POLICY_LAYER34");
+ break;
+ }
+ cli_printf("\n");
+ }
+ }
+
+ num_slaves = rte_eth_bond_slaves_get(pid, slaves,
+ RTE_MAX_ETHPORTS);
+
+ if (num_slaves < 0) {
+ cli_printf("\tFailed to get slave list for port = %d\n",
+ pid);
+ return -1;
+ }
+ if (num_slaves > 0) {
+ cli_printf("\tSlaves (%d): [", num_slaves);
+ for (i = 0; i < num_slaves - 1; i++)
+ cli_printf("%d ", slaves[i]);
+
+ cli_printf("%d]\n", slaves[num_slaves - 1]);
+ } else
+ cli_printf("\tSlaves: []\n");
+
+
+ num_active_slaves = rte_eth_bond_active_slaves_get(pid, slaves,
+ RTE_MAX_ETHPORTS);
+
+ if (num_active_slaves < 0) {
+ cli_printf(
+ "\tFailed to get active slave list for port = %d\n",
+ pid);
+ return -1;
+ }
+ if (num_active_slaves > 0) {
+ cli_printf("\tActive Slaves (%d): [",
+ num_active_slaves);
+ for (i = 0; i < num_active_slaves - 1; i++)
+ cli_printf("%d ", slaves[i]);
+
+ cli_printf("%d]\n", slaves[num_active_slaves - 1]);
+
+ } else
+ cli_printf("\tActive Slaves: []\n");
+
+
+ primary_id = rte_eth_bond_primary_get(pid);
+ if (primary_id < 0) {
+ cli_printf(
+ "\tFailed to get primary slave for port = %d\n",
+ pid);
+ return -1;
+ } else
+ cli_printf("\tPrimary: [%d]\n", primary_id);
+ }
+ break;
+ case 440: /* port bonding set mode %d %d */
+ pid = atoi(argv[4]);
+ val = atoi(argv[5]);
+ if (rte_eth_bond_mode_set(pid, val) < 0)
+ cli_printf("\t Failed to set bonding mode for port = %d.\n",
+ pid);
+ break;
+ case 450: /* port bonding set primary %d %d */
+ pid = atoi(argv[5]);
+
+ /* Set the primary slave for a bonded device. */
+ if (rte_eth_bond_primary_set(pid, atoi(argv[4]))) {
+ cli_printf("\t Failed to set primary slave for port = %d.\n",
+ pid);
+ return -1;
+ }
+ init_port_config();
+ break;
+ case 460: /* port bonding set mac_addr %d %m */
+ pid = atoi(argv[4]);
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return -1;
+
+ n =
+ rte_eth_bond_mac_address_set(pid,
+ rte_ether_aton(argv[5], NULL));
+
+ /* check the return value and print it if is < 0 */
+ if (n < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-n));
+ break;
+ case 470: /* port bonding set slave %d %d */
+ pid = atoi(argv[5]);
+ val = atoi(argv[4]);
+
+ /* Set the primary slave for a bonded device. */
+ if (rte_eth_bond_slave_remove(pid, val)) {
+ cli_printf("\t Failed to remove slave %d from master port = %d.\n",
+ val, pid);
+ return -1;
+ }
+ init_port_config();
+ clear_port_slave_flag(val);
+ break;
+ case 480: { /* port bonding set xmit_balance_policy %d %|l2|l23|l34 */
+ uint8_t policy = 0;
+
+ pid = atoi(argv[4]);
+
+ if (!strcmp(argv[5], "l2"))
+ policy = BALANCE_XMIT_POLICY_LAYER2;
+ else if (!strcmp(argv[5], "l23"))
+ policy = BALANCE_XMIT_POLICY_LAYER23;
+ else if (!strcmp(argv[5], "l34"))
+ policy = BALANCE_XMIT_POLICY_LAYER34;
+ else {
+ cli_printf("\t Invalid xmit policy selection");
+ return -1;
+ }
+
+ /* Set the bonding mode for the relevant port. */
+ if (rte_eth_bond_xmit_policy_set(pid, policy) != 0)
+ cli_printf("\t Failed to set bonding balance xmit policy for port = %d.\n",
+ pid);
+ }
+ break;
+ case 490: /* port bonding set mon_period %d %d */
+ pid = atoi(argv[4]);
+ val = atoi(argv[5]);
+ if (pid >= nb_ports) {
+ cli_printf("Port id %d must be less than %d\n", pid,
+ nb_ports);
+ return -1;
+ }
+
+ n = rte_eth_bond_link_monitoring_set(pid, val);
+
+ /* check the return value and print it if is < 0 */
+ if (n < 0)
+ cli_printf("set_bond_mac_addr error: (%s)\n",
+ strerror(-n));
+ break;
+#endif
+#ifdef RTE_NIC_BYPASS
+ case 500: { /* port bypass set mode %|normal|bypass|isolate %d */
+ unsigned int bypass_mode;
+
+ pid = atoi(argv[5]);
+ bypass_mode = RTE_BYPASS_MODE_NORMAL;
+ if (!strcmp(argv[4], "bypass"))
+ bypass_mode = RTE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(argv[4], "isolate"))
+ bypass_mode = RTE_BYPASS_MODE_ISOLATE;
+
+ if (rte_eth_dev_bypass_state_set(atoi(pid, &bypass_mode)))
+ cli_printf(
+ "\t Failed to set bypass mode for port = %d.\n",
+ pid);
+ }
+ break;
+ case 510: { /* port bypass set event %|timeout|os_on|os_off|power_on|power_off mode %|normal|bypass|isolate %d */
+ unsigned int bypass_mode, bypass_event;
+ pid = atoi(argv[7]);
+ bypass_event = RTE_BYPASS_EVENT_NONE;
+ n = rte_stropt("timeout|os_on|os_off|power_on|power_off",
+ argv[4], '|');
+ switch(n) {
+ case 0:
+ bypass_event = RTE_BYPASS_EVENT_TIMEOUT;
+ break;
+ case 1:
+ bypass_event = RTE_BYPASS_EVENT_OS_ON;
+ break;
+ case 2:
+ bypass_event = RTE_BYPASS_EVENT_OS_OFF;
+ break;
+ case 3:
+ bypass_event = RTE_BYPASS_EVENT_POWER_ON;
+ break;
+ case 4:
+ bypass_event = RTE_BYPASS_EVENT_POWER_OFF;
+ break;
+ default:
+ return -1;
+ }
+ /* Set the watchdog timeout. */
+ if (bypass_event == RTE_BYPASS_EVENT_TIMEOUT) {
+ n = -EINVAL;
+ if (!RTE_BYPASS_TMT_VALID(bypass_timeout) ||
+ (n = rte_eth_dev_wd_timeout_store(pid,
+ bypass_timeout))
+ != 0)
+ cli_printf("Failed to set timeout value %u "
+ "for port %d, errto code: %d.\n",
+ bypass_timeout, pid, n);
+ }
+ bypass_mode = RTE_BYPASS_MODE_NORMAL;
+ if (!strcmp(argv[6], "bypass"))
+ bypass_mode = RTE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(argv[6], "isolate"))
+ bypass_mode = RTE_BYPASS_MODE_ISOLATE;
+
+ /* Set the bypass event to transition to bypass mode. */
+ if (rte_eth_dev_bypass_event_store(pid,
+ bypass_event, bypass_mode))
+ cli_printf(
+ "\t Failed to set bypass event for port = %d.\n",
+ pid);
+ }
+ break;
+ case 520: /* port bypass set timeout %|0|1.5|2|3|4|8|16|32 */
+ n = rte_stropt("1.5|2|3|4|8|16|32", argv[4], '|');
+ switch(n) {
+ case 0:
+ bypass_timeout = RTE_BYPASS_TMT_1_5_SEC;
+ break;
+ case 1:
+ bypass_timeout = RTE_BYPASS_TMT_2_SEC;
+ break;
+ case 2:
+ bypass_timeout = RTE_BYPASS_TMT_3_SEC;
+ break;
+ case 3:
+ bypass_timeout = RTE_BYPASS_TMT_4_SEC;
+ break;
+ case 4:
+ bypass_timeout = RTE_BYPASS_TMT_8_SEC;
+ break;
+ case 5:
+ bypass_timeout = RTE_BYPASS_TMT_16_SEC;
+ break;
+ case 6:
+ bypass_timeout = RTE_BYPASS_TMT_32SEC;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 530: { /* port bypass show config %d */
+ unsigned int bypass_mode, bypass_event;
+ int i;
+ static const char * const modes[RTE_BYPASS_MODE_NUM] =
+ {"UNKNOWN", "normal", "bypass", "isolate"};
+ static const char * const timeouts[RTE_BYPASS_TMT_NUM] =
+ {"off", "1.5", "2", "3", "4", "8", "16", "32"};
+ static const char * const modes[RTE_BYPASS_MODE_NUM] =
+ {"UNKNOWN", "normal", "bypass", "isolate"};
+ static const char * const events[RTE_BYPASS_EVENT_NUM] = {
+ "NONE",
+ "OS/board on",
+ "power supply on",
+ "OS/board off",
+ "power supply off",
+ "timeout"
+ };
+ int num_events = (sizeof events) / (sizeof events[0]);
+
+ pid = atoi(argv[4]);
+
+ bypass_mode = RTE_BYPASS_MODE_NORMAL;
+ bypass_event = RTE_BYPASS_EVENT_NODE;
+ bypass_timeout = RTE_BYPASS_TMT_OFF;
+
+ /* Display the bypass mode.*/
+ if (rte_eth_dev_bypass_state_show(port_id, &bypass_mode)) {
+ cli_printf(
+ "\tFailed to get bypass mode for port = %d\n",
+ pid);
+ return -1;
+ } else {
+ if (!RTE_BYPASS_MODE_VALID(bypass_mode))
+ bypass_mode = RTE_BYPASS_MODE_NONE;
+
+ cli_printf("\tbypass mode = %s\n",
+ modes[bypass_mode]);
+ }
+
+ /* Display the bypass timeout.*/
+ if (!RTE_BYPASS_TMT_VALID(timeout))
+ timeout = RTE_BYPASS_TMT_OFF;
+
+ cli_printf("\tbypass timeout = %s\n", timeouts[timeout]);
+
+ /* Display the bypass events and associated modes. */
+ for (i = RTE_BYPASS_EVENT_START; i < num_events; i++) {
+
+ if (rte_eth_dev_bypass_event_show(port_id, i,
+ &event_mode))
+ cli_printf("\tFailed to get bypass mode for event = %s\n",
+ events[i]);
+ else {
+ if (!RTE_BYPASS_MODE_VALID(event_mode))
+ event_mode = RTE_BYPASS_MODE_NONE;
+
+ cli_printf("\tbypass event: %-16s = %s\n",
+ events[i], modes[event_mode]);
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static struct cli_map filter_map[] = {
+ {
+ 0, "filter tunnel %|add|rm %d %m %m %4 %d %|vxlan|nvgre|ipingre "
+ "%|oip|iip|imac-ivlan|imac-ivlan-tenid|imac-tenid|imac|omac-imac-tenid %d %d"
+ },
+
+ {
+ 20,
+ "filter ethertype %d %|add|del %|mac_addr|mac_ignr %m ethertype %d %|drop|fwd queue %d"
+ },
+ {
+ 40,
+ "filter 2tuple %d %|add|del dst_port %d protocol %d mask %d tcp_flags %d priority %d queue %d"
+ },
+ {
+ 60,
+ "filter 5tuple %d %|add|del dst_ip %4 src_ip %4 dst_port %d src_port %d protocol %d mask %d tcp_flags %d priority %d queue %d"
+ },
+ { 80, "filter syn %d %|add|del priority %|high|low queue %d" },
+ {
+ 100,
+ "filter flex %d %|add|del len %d bytes %s mask %s priority %d queue %d"
+ },
+
+ {
+ 120, "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 dst %4 tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d"
+ },
+
+ {
+ 121, "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 %d dst %4 %d tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d"
+ },
+
+ {
+ 122, "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 %d dst %4 %d verify_tag %d tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d"
+ },
+
+ {
+ 123, "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "ether %d flexbytes %s %|drop|fwd %s queue %d fd_id %d"
+ },
+
+ {
+ 124, "filter flow_director %d mode MAC-VLAN %|add|del|update "
+ "mac %m vlan %d flexbytes %s %|drop|fwd queue %d fd_id %d"
+ },
+
+ {
+ 125, "filter flow_director %d mode Tunnel %|add|del|update "
+ "mac %m vlan %d tunnel %|NVGRE|VxLAN tunnel-id %d"
+ "flexbytes %s %|drop|fwd queue %d fd_id %d"
+ },
+
+ { 180, "filter flow_director flush %d" },
+
+ {
+ 190,
+ "filter flow_director mask %d mode IP vlan %d src_mask %4 %6 %d dst_mask %4 %6 %d %m %d"
+ },
+
+ { 191, "filter flow_director mask %d mode MAC-VLAN vlan %d" },
+
+ {
+ 192,
+ "filter flow_director mask %d mode Tunnel vlan %d mac %m tunnel-type %d tunnelid %d"
+ },
+
+ {
+ 220, "filter flow_director flex_mask %d "
+ "flow %|none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload %s"
+ },
+
+ { 230, "filter flow_director flex_payload %d %|raw|l2|l3|l4 %s" },
+ { -1, NULL }
+};
+
+static inline int
+parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT8_MAX)
+ return -1;
+ flexbytes[i] = (uint8_t)int_fld;
+ }
+ return ret;
+}
+
+static uint16_t
+str2flowtype(char *string)
+{
+ uint8_t i = 0;
+ static const struct {
+ char str[32];
+ uint16_t type;
+ } flowtype_str[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str); i++)
+ if (!strcmp(flowtype_str[i].str, string))
+ return flowtype_str[i].type;
+ return RTE_ETH_FLOW_UNKNOWN;
+}
+
+static enum rte_eth_fdir_tunnel_type
+str2fdir_tunneltype(char *string) {
+ uint8_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_fdir_tunnel_type type;
+ } tunneltype_str[] = {
+ {"NVGRE", RTE_FDIR_TUNNEL_TYPE_NVGRE},
+ {"VxLAN", RTE_FDIR_TUNNEL_TYPE_VXLAN},
+ };
+
+ for (i = 0; i < RTE_DIM(tunneltype_str); i++)
+ if (!strcmp(tunneltype_str[i].str, string))
+ return tunneltype_str[i].type;
+ return RTE_FDIR_TUNNEL_TYPE_UNKNOWN;
+}
+
+#define IPV4_ADDR_TO_UINT(ip_addr, ip) \
+ do { \
+ if ((ip_addr).family == AF_INET) \
+ (ip) = (ip_addr).ipv4.s_addr; \
+ else { \
+ printf("invalid parameter.\n"); \
+ return -1; \
+ } \
+ } while (0)
+
+#define IPV6_ADDR_TO_ARRAY(ip_addr, ip) \
+ do { \
+ if ((ip_addr).family == AF_INET6) \
+ (void)rte_memcpy(&(ip), \
+ &((ip_addr).ipv6), \
+ sizeof(struct in6_addr)); \
+ else { \
+ printf("invalid parameter.\n"); \
+ return -1; \
+ } \
+ } while (0)
+
+static int
+xdigit2val(unsigned char c)
+{
+ int val;
+ if (isdigit(c))
+ val = c - '0';
+ else if (isupper(c))
+ val = c - 'A' + 10;
+ else
+ val = c - 'a' + 10;
+ return val;
+}
+
+static inline int
+parse_offsets(const char *q_arg, uint16_t *offsets, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT16_MAX)
+ return -1;
+ offsets[i] = (uint16_t)int_fld;
+ }
+ return ret;
+}
+
+static int
+filter_cmd(int argc, char **argv)
+{
+ int ret = 0, n = 0;
+ uint8_t pid = 0;
+ uint16_t qid = 0;
+ struct cli_map *m;
+
+ m = cli_mapping(filter_map, argc, argv);
+ if (!m)
+ return -1;
+
+ switch(m->index) {
+ case 0: {
+ /* filter tunnel %|add|rm %d %m %m %4 %d %|vxlan|nvgre|ipingre
+ %|oip|iip|imac-ivlan|imac-ivlan-tenid|imac-tenid|imac|omac-imac-tenid %d %d */
+ struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
+ struct rte_ipaddr ip;
+
+ pid = atoi(argv[3]);
+ memset(&tunnel_filter_conf, 0, sizeof(tunnel_filter_conf));
+
+ ether_addr_copy(rte_ether_aton(argv[4],
+ NULL),
+ &tunnel_filter_conf.outer_mac);
+ ether_addr_copy(rte_ether_aton(argv[5],
+ NULL),
+ &tunnel_filter_conf.inner_mac);
+ tunnel_filter_conf.inner_vlan = atoi(argv[7]);
+
+ rte_atoip(argv[6], RTE_IPADDR_V4|RTE_IPADDR_V6, &ip,
+ sizeof(ip));
+
+ if (ip.family == AF_INET) {
+ tunnel_filter_conf.ip_addr.ipv4_addr = ip.ipv4.s_addr;
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV4;
+ } else {
+ memcpy(&(tunnel_filter_conf.ip_addr.ipv6_addr),
+ &(ip.ipv6), sizeof(struct in6_addr));
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV6;
+ }
+
+ n = rte_stropt(
+ "oip|iip|imac-ivlan|imac-ivlan-tenid|imac-tenid|imac|omac-imac-tenid",
+ argv[9], "|");
+ switch(n) {
+ case 0:
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_OIP;
+ break;
+ case 1:
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IIP;
+ break;
+ case 2:
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN;
+ break;
+ case 3:
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID;
+ break;
+ case 4:
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_IMAC_TENID;
+ break;
+ case 5:
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC;
+ break;
+ case 6:
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IMAC;
+ break;
+ }
+
+ n = rte_stropt("", argv[8], "|");
+ switch(n) {
+ case 0:
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+ break;
+ case 1:
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_NVGRE;
+ break;
+ case 2:
+ tunnel_filter_conf.tunnel_type =
+ RTE_TUNNEL_TYPE_IP_IN_GRE;
+ break;
+ }
+
+ tunnel_filter_conf.tenant_id = atoi(argv[10]);
+ tunnel_filter_conf.queue_id = atoi(argv[11]);
+ if (!strcmp(argv[2], "add"))
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &tunnel_filter_conf);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &tunnel_filter_conf);
+ if (ret < 0)
+ printf("cmd_tunnel_filter_parsed error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 20: { /* filter ethertype %d %|add|del %|mac_addr|mac_ignr %m ethertype %d %|drop|fwd queue %d */
+ struct rte_eth_ethertype_filter filter;
+
+ pid = atoi(argv[2]);
+ ret =
+ rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_ETHERTYPE);
+ if (ret < 0) {
+ printf(
+ "ethertype filter is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+
+ memset(&filter, 0, sizeof(filter));
+ if (!strcmp(argv[4], "mac_addr")) {
+ filter.flags |= RTE_ETHTYPE_FLAGS_MAC;
+ (void)rte_memcpy(&filter.mac_addr,
+ rte_ether_aton(argv[5], NULL),
+ sizeof(struct ether_addr));
+ }
+ if (!strcmp(argv[8], "drop"))
+ filter.flags |= RTE_ETHTYPE_FLAGS_DROP;
+ filter.ether_type = atoi(argv[7]);
+ filter.queue = atoi(argv[10]);
+
+ if (!strcmp(argv[3], "add"))
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("ethertype filter programming error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 40: { /* filter 2tuple %d %|add|del dst_port %d protocol %d mask %d tcp_flags %d priority %d queue %d */
+ struct rte_eth_ntuple_filter filter;
+ uint8_t proto, tcp_flags, priority;
+ uint16_t dst_port;
+ uint32_t mask;
+ char *ops;
+
+ pid = atoi(argv[2]);
+ ops = argv[3];
+ dst_port = atoi(argv[5]);
+ proto = atoi(argv[7]);
+ mask = atoi(argv[9]);
+ tcp_flags = atoi(argv[11]);
+ priority = atoi(argv[13]);
+ qid = atoi(argv[15]);
+
+ ret = rte_eth_dev_filter_supported(pid, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ pid);
+ return ret;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_2TUPLE_FLAGS;
+ filter.dst_port_mask = (mask & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (mask & 0x01) ? UINT8_MAX : 0;
+ filter.proto = proto;
+ filter.priority = priority;
+ if (tcp_flags != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return -1;
+ }
+ if (tcp_flags > TCP_FLAG_ALL) {
+ printf("invalid TCP flags.\n");
+ return -1;
+ }
+
+ if (tcp_flags != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = tcp_flags;
+ }
+
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(dst_port);
+ filter.queue = qid;
+
+ if (!strcmp(ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("2tuple filter programming error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 60: { /* filter 5tuple %d %|add|del dst_ip %4 src_ip %4 dst_port %d src_port %d protocol %d mask %d tcp_flags %d priority %d queue %d */
+ struct rte_eth_ntuple_filter filter;
+ uint8_t proto, tcp_flags, priority;
+ uint16_t dst_port, src_port;
+ uint32_t mask;
+ struct rte_ipaddr ip_dst, ip_src;
+ char *ops, *dst_ip, *src_ip;
+
+ pid = atoi(argv[2]);
+ ops = argv[3];
+ dst_ip = argv[5];
+ src_ip = argv[7];
+ dst_port = atoi(argv[9]);
+ src_port = atoi(argv[11]);
+ proto = atoi(argv[13]);
+ mask = atoi(argv[15]);
+ tcp_flags = atoi(argv[17]);
+ priority = atoi(argv[19]);
+ qid = atoi(argv[21]);
+
+ ret = rte_eth_dev_filter_supported(pid, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ pid);
+ return ret;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_5TUPLE_FLAGS;
+ filter.dst_ip_mask = (mask & 0x10) ? UINT32_MAX : 0;
+ filter.src_ip_mask = (mask & 0x08) ? UINT32_MAX : 0;
+ filter.dst_port_mask = (mask & 0x04) ? UINT16_MAX : 0;
+ filter.src_port_mask = (mask & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (mask & 0x01) ? UINT8_MAX : 0;
+ filter.proto = proto;
+ filter.priority = priority;
+ if (tcp_flags != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return -1;
+ }
+ if (tcp_flags > TCP_FLAG_ALL) {
+ printf("invalid TCP flags.\n");
+ return -1;
+ }
+
+ if (tcp_flags != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = tcp_flags;
+ }
+
+ rte_atoip(dst_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_dst,
+ sizeof(ip_dst));
+ if (ip_dst.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.dst_ip = ip_dst.ipv4.s_addr;
+ else {
+ if (filter.dst_ip_mask == 0) {
+ printf(
+ "can not support ipv6 involved compare.\n");
+ return -1;
+ }
+ filter.dst_ip = 0;
+ }
+
+ rte_atoip(src_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_src,
+ sizeof(ip_src));
+ if (ip_src.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.src_ip = ip_src.ipv4.s_addr;
+ else {
+ if (filter.src_ip_mask == 0) {
+ printf(
+ "can not support ipv6 involved compare.\n");
+ return -1;
+ }
+ filter.src_ip = 0;
+ }
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(dst_port);
+ filter.src_port = rte_cpu_to_be_16(src_port);
+ filter.queue = qid;
+
+ if (!strcmp(ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("5tuple filter programming error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 80: { /* filter syn %d %|add|del priority %|high|low queue %d */
+ struct rte_eth_syn_filter syn_filter;
+ char *ops, *high;
+
+ pid = atoi(argv[2]);
+ ops = argv[3];
+ high = argv[5];
+ qid = atoi(argv[7]);
+ ret = rte_eth_dev_filter_supported(pid, RTE_ETH_FILTER_SYN);
+ if (ret < 0) {
+ printf("syn filter is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+
+ memset(&syn_filter, 0, sizeof(syn_filter));
+
+ if (!strcmp(ops, "add")) {
+ if (!strcmp(high, "high"))
+ syn_filter.hig_pri = 1;
+ else
+ syn_filter.hig_pri = 0;
+
+ syn_filter.queue = qid;
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_ADD,
+ &syn_filter);
+ } else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_DELETE,
+ &syn_filter);
+
+ if (ret < 0)
+ printf("syn filter programming error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 100: { /* filter flex %d %|add|del len %d bytes %s mask %s priority %d queue %d */
+ struct rte_eth_flex_filter filter;
+ char *bytes_ptr, *mask_ptr;
+ uint16_t len, len_value, i, j = 0;
+ char c, *ops;
+ int val, priority;
+ uint8_t byte = 0;
+
+ pid = atoi(argv[2]);
+ ops = argv[3];
+ len_value = atoi(argv[5]);
+ bytes_ptr = argv[7];
+ mask_ptr = argv[9];
+ priority = atoi(argv[11]);
+ qid = atoi(argv[13]);
+
+ if (len_value > RTE_FLEX_FILTER_MAXLEN) {
+ printf("the len exceed the max length 128\n");
+ return -1;
+ }
+ memset(&filter, 0, sizeof(struct rte_eth_flex_filter));
+ filter.len = len_value;
+ filter.priority = priority;
+ filter.queue = qid;
+
+ /* translate bytes string to array. */
+ if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+ (bytes_ptr[1] == 'X')))
+ bytes_ptr += 2;
+ len = strnlen(bytes_ptr, len_value * 2);
+ if (len == 0 || (len % 8 != 0)) {
+ printf("please check len and bytes input\n");
+ return -1;
+ }
+ for (i = 0; i < len; i++) {
+ c = bytes_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return -1;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.bytes[j] = byte;
+ printf("bytes[%d]:%02x ", j, filter.bytes[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+ /* translate mask string to uint8_t array. */
+ if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+ (mask_ptr[1] == 'X')))
+ mask_ptr += 2;
+ len = strnlen(mask_ptr, (len_value + 3) / 4);
+ if (len == 0) {
+ printf("invalid input\n");
+ return -1;
+ }
+ j = 0;
+ byte = 0;
+ for (i = 0; i < len; i++) {
+ c = mask_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return -1;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.mask[j] = byte;
+ printf("mask[%d]:%02x ", j, filter.mask[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+
+ if (!strcmp(ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+
+ if (ret < 0)
+ printf("flex filter setting error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 120: /* "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 dst %4 tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d" */
+ case 121: /* "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 %d dst %4 %d tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d" */
+ case 122: /* "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "src %4 %d dst %4 %d verify_tag %d tos %d proto %d ttl %d vlan %d "
+ "flexbytes %s %|drop|fwd %s queue %d fd_id %d" */
+ case 123: /* "filter flow_director %d mode IP %|add|del|update "
+ "flow %|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload "
+ "ether %d flexbytes %s %|drop|fwd %s queue %d fd_id %d" */
+ case 124: /* "filter flow_director %d mode MAC-VLAN %|add|del|update "
+ "mac %m vlan %d flexbytes %s %|drop|fwd queue %d fd_id %d" */
+ case 125: {
+ /* "filter flow_director %d mode Tunnel %|add|del|update "
+ "mac %m vlan %d tunnel %|NVGRE|VxLAN tunnel-id %d"
+ "flexbytes %s %|drop|fwd queue %d fd_id %d" */
+ struct rte_eth_fdir_filter entry;
+ uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
+ char *end = NULL;
+ unsigned long vf_id = 0;
+ int ret = 0, tos = 0, proto = 0, ttl = 0, vid = 0, fid = 0,
+ tid = 0;
+ char *mode = NULL, *flow = NULL, *flex = NULL, *dst_ip = NULL;
+ char *src_ip = NULL, *mac = NULL, *pf_vf = NULL, *drop = NULL;
+ char *ops = NULL, *tunnel = NULL;
+ uint16_t port_src = 0, port_dst = 0, tag = 0, ether = 0;
+ struct rte_ipaddr ip_dst, ip_src;
+
+ pid = atoi(argv[2]);
+ mode = argv[4];
+ ops = argv[5];
+
+ if (m->index == 120) {
+ flow = argv[7];
+ src_ip = argv[9];
+ dst_ip = argv[11];
+ tos = atoi(argv[13]);
+ proto = atoi(argv[15]);
+ ttl = atoi(argv[17]);
+ vid = atoi(argv[19]);
+ flex = argv[21];
+ drop = argv[22];
+ pf_vf = argv[23];
+ qid = atoi(argv[25]);
+ fid = atoi(argv[27]);
+ } else if (m->index == 121) {
+ flow = argv[7];
+ src_ip = argv[9];
+ port_src = atoi(argv[10]);
+ dst_ip = argv[12];
+ port_dst = atoi(argv[13]);
+ tos = atoi(argv[15]);
+ proto = atoi(argv[17]);
+ ttl = atoi(argv[19]);
+ vid = atoi(argv[20]);
+ flex = argv[23];
+ drop = argv[24];
+ pf_vf = argv[25];
+ qid = atoi(argv[27]);
+ fid = atoi(argv[29]);
+ } else if (m->index == 122) {
+ flow = argv[7];
+ src_ip = argv[9];
+ port_src = atoi(argv[10]);
+ dst_ip = argv[12];
+ port_dst = atoi(argv[13]);
+ tag = atoi(argv[15]);
+ tos = atoi(argv[17]);
+ proto = atoi(argv[19]);
+ ttl = atoi(argv[21]);
+ vid = atoi(argv[23]);
+ flex = argv[25];
+ drop = argv[26];
+ pf_vf = argv[27];
+ qid = atoi(argv[29]);
+ fid = atoi(argv[31]);
+ } else if (m->index == 123) {
+ flow = argv[7];
+ ether = atoi(argv[9]);
+ flex = argv[11];
+ drop = argv[12];
+ pf_vf = argv[13];
+ qid = atoi(argv[15]);
+ fid = atoi(argv[17]);
+ } else if (m->index == 124) {
+ mac = argv[7];
+ vid = atoi(argv[9]);
+ flex = argv[11];
+ drop = argv[12];
+ pf_vf = argv[13];
+ qid = atoi(argv[15]);
+ fid = atoi(argv[17]);
+ } else if (m->index == 125) {
+ mac = argv[7];
+ vid = atoi(argv[9]);
+ tunnel = argv[11];
+ tid = atoi(argv[13]);
+ flex = argv[15];
+ drop = argv[16];
+ pf_vf = argv[17];
+ qid = atoi(argv[19]);
+ fid = atoi(argv[21]);
+ }
+
+ ret = rte_eth_dev_filter_supported(pid, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+ memset(flexbytes, 0, sizeof(flexbytes));
+ memset(&entry, 0, sizeof(struct rte_eth_fdir_filter));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(mode, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return -1;
+ }
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(mode, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return -1;
+ }
+ } else {
+ if (strcmp(mode, "IP")) {
+ printf("Please set mode to IP.\n");
+ return -1;
+ }
+ entry.input.flow_type = str2flowtype(flow);
+ }
+
+ ret =
+ parse_flexbytes(flex, flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flexbytes input.\n");
+ return -1;
+ }
+
+ switch (entry.input.flow_type) {
+ case RTE_ETH_FLOW_FRAG_IPV4:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+ entry.input.flow.ip4_flow.proto = proto;
+ case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+ rte_atoip(dst_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_dst,
+ sizeof(ip_dst));
+ rte_atoip(src_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_src,
+ sizeof(ip_src));
+ IPV4_ADDR_TO_UINT(ip_dst,
+ entry.input.flow.ip4_flow.dst_ip);
+ IPV4_ADDR_TO_UINT(ip_src,
+ entry.input.flow.ip4_flow.src_ip);
+ entry.input.flow.ip4_flow.tos = tos;
+ entry.input.flow.ip4_flow.ttl = ttl;
+ /* need convert to big endian. */
+ entry.input.flow.udp4_flow.dst_port = rte_cpu_to_be_16(
+ port_dst);
+ entry.input.flow.udp4_flow.src_port = rte_cpu_to_be_16(
+ port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
+ rte_atoip(dst_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_dst,
+ sizeof(ip_dst));
+ rte_atoip(src_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_src,
+ sizeof(ip_src));
+ IPV4_ADDR_TO_UINT(ip_dst,
+ entry.input.flow.sctp4_flow.ip.dst_ip);
+ IPV4_ADDR_TO_UINT(ip_src,
+ entry.input.flow.sctp4_flow.ip.src_ip);
+ entry.input.flow.ip4_flow.tos = tos;
+ entry.input.flow.ip4_flow.ttl = ttl;
+ /* need convert to big endian. */
+ entry.input.flow.sctp4_flow.dst_port = rte_cpu_to_be_16(
+ port_dst);
+ entry.input.flow.sctp4_flow.src_port = rte_cpu_to_be_16(
+ port_src);
+ entry.input.flow.sctp4_flow.verify_tag =
+ rte_cpu_to_be_32(tag);
+ break;
+ case RTE_ETH_FLOW_FRAG_IPV6:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+ entry.input.flow.ipv6_flow.proto = proto;
+ case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+ rte_atoip(dst_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_dst,
+ sizeof(ip_dst));
+ rte_atoip(src_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_src,
+ sizeof(ip_src));
+ IPV6_ADDR_TO_ARRAY(ip_dst,
+ entry.input.flow.ipv6_flow.dst_ip);
+ IPV6_ADDR_TO_ARRAY(ip_src,
+ entry.input.flow.ipv6_flow.src_ip);
+ entry.input.flow.ipv6_flow.tc = tos;
+ entry.input.flow.ipv6_flow.hop_limits = ttl;
+ /* need convert to big endian. */
+ entry.input.flow.udp6_flow.dst_port = rte_cpu_to_be_16(
+ port_dst);
+ entry.input.flow.udp6_flow.src_port = rte_cpu_to_be_16(
+ port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
+ rte_atoip(dst_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_dst,
+ sizeof(ip_dst));
+ rte_atoip(src_ip, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip_src,
+ sizeof(ip_src));
+ IPV6_ADDR_TO_ARRAY(ip_dst,
+ entry.input.flow.sctp6_flow.ip.dst_ip);
+ IPV6_ADDR_TO_ARRAY(ip_src,
+ entry.input.flow.sctp6_flow.ip.src_ip);
+ entry.input.flow.ipv6_flow.tc = tos;
+ entry.input.flow.ipv6_flow.hop_limits = ttl;
+ /* need convert to big endian. */
+ entry.input.flow.sctp6_flow.dst_port = rte_cpu_to_be_16(
+ port_dst);
+ entry.input.flow.sctp6_flow.src_port = rte_cpu_to_be_16(
+ port_src);
+ entry.input.flow.sctp6_flow.verify_tag =
+ rte_cpu_to_be_32(tag);
+ break;
+ case RTE_ETH_FLOW_L2_PAYLOAD:
+ entry.input.flow.l2_flow.ether_type = rte_cpu_to_be_16(
+ ether);
+ break;
+ default:
+ break;
+ }
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ (void)rte_memcpy(
+ &entry.input.flow.mac_vlan_flow.mac_addr,
+ rte_ether_aton(mac, NULL),
+ sizeof(struct ether_addr));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ (void)rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr,
+ rte_ether_aton(mac, NULL),
+ sizeof(struct ether_addr));
+ entry.input.flow.tunnel_flow.tunnel_type =
+ str2fdir_tunneltype(tunnel);
+ entry.input.flow.tunnel_flow.tunnel_id =
+ rte_cpu_to_be_32(tid);
+ }
+
+ (void)rte_memcpy(entry.input.flow_ext.flexbytes,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+
+ entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(vid);
+
+ entry.action.flex_off = 0; /*use 0 by default */
+ if (!strcmp(drop, "drop"))
+ entry.action.behavior = RTE_ETH_FDIR_REJECT;
+ else
+ entry.action.behavior = RTE_ETH_FDIR_ACCEPT;
+
+ if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
+ fdir_conf.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (!strcmp(pf_vf, "pf"))
+ entry.input.flow_ext.is_vf = 0;
+ else if (!strncmp(pf_vf, "vf", 2)) {
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(pid, &dev_info);
+ errno = 0;
+ vf_id = strtoul(pf_vf + 2, &end, 10);
+ if (errno != 0 || *end != '\0' ||
+ vf_id >= dev_info.max_vfs) {
+ printf("invalid parameter %s.\n",
+ pf_vf);
+ return -1;
+ }
+ entry.input.flow_ext.is_vf = 1;
+ entry.input.flow_ext.dst_id = (uint16_t)vf_id;
+ } else {
+ printf("invalid parameter %s.\n", pf_vf);
+ return -1;
+ }
+ }
+
+ /* set to report FD ID by default */
+ entry.action.report_status = RTE_ETH_FDIR_REPORT_ID;
+ entry.action.rx_queue = qid;
+ entry.soft_id = fid;
+ if (!strcmp(ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_ADD,
+ &entry);
+ else if (!strcmp(ops, "del"))
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_DELETE,
+ &entry);
+ else
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_UPDATE,
+ &entry);
+ if (ret < 0)
+ printf("flow director programming error: (%s)\n",
+ strerror(-ret));
+ }
+ break;
+ case 180: /* filter flow_director flush %d */
+ pid = atoi(argv[3]);
+ ret = rte_eth_dev_filter_supported(pid, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ pid);
+ return -1;
+ }
+
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_FLUSH, NULL);
+ if (ret < 0)
+ printf("flow director table flushing error: (%s)\n",
+ strerror(-ret));
+ break;
+ case 190: /* filter flow_director mask %d mode IP vlan %d src_mask %4 %6 %d dst_mask %4 %6 %d */
+ case 191: /* filter flow_director mask %d mode MAC-VLAN vlan %d */
+ case 192: { /* filter flow_director mask %d mode Tunnel vlan %d mac %d tunnel-type %d tunnelid %d */
+ struct rte_eth_fdir_masks *mask;
+ struct rte_port *port;
+ struct rte_ipaddr ip;
+ char *mode = NULL, *ip4_src = NULL, *ip6_src = NULL;
+ char *ip4_dst = NULL, *ip6_dst = NULL;
+ uint16_t vlan_mask = 0, port_src = 0, port_dst = 0;
+ uint16_t tunnel_type = 0, mac_mask = 0;
+ uint32_t tid = 0;
+
+ pid = atoi(argv[3]);
+ mode = argv[5];
+ if (m->index == 190) {
+ vlan_mask = atoi(argv[7]);
+ ip4_src = argv[9];
+ ip6_src = argv[10];
+ port_src = atoi(argv[11]);
+ ip4_dst = argv[13];
+ ip6_dst = argv[14];
+ port_dst = atoi(argv[15]);
+ } else if (m->index == 191)
+ vlan_mask = atoi(argv[7]);
+ else if (m->index == 192) {
+ vlan_mask = atoi(argv[7]);
+ mac_mask = atoi(argv[9]);
+ tunnel_type = atoi(argv[11]);
+ tid = atoi(argv[13]);
+ }
+
+ if (pid > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n",
+ nb_ports - 1);
+ return -1;
+ }
+
+ port = &ports[pid];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", pid);
+ return -1;
+ }
+
+ mask = &port->dev_conf.fdir_conf.mask;
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(mode, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return -1;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(vlan_mask);
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(mode, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return -1;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(vlan_mask);
+ mask->mac_addr_byte_mask = (uint8_t)mac_mask;
+ mask->tunnel_id_mask = rte_cpu_to_be_32(tid);
+ mask->tunnel_type_mask = tunnel_type;
+ } else {
+ if (strcmp(mode, "IP")) {
+ printf("Please set mode to IP.\n");
+ return -1;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(vlan_mask);
+ rte_atoip(ip4_src, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip,
+ sizeof(ip));
+ IPV4_ADDR_TO_UINT(ip, mask->ipv4_mask.src_ip);
+ rte_atoip(ip4_dst, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip,
+ sizeof(ip));
+ IPV4_ADDR_TO_UINT(ip, mask->ipv4_mask.dst_ip);
+ rte_atoip(ip6_src, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip,
+ sizeof(ip));
+ IPV6_ADDR_TO_ARRAY(ip, mask->ipv6_mask.src_ip);
+ rte_atoip(ip6_dst, RTE_IPADDR_V4|RTE_IPADDR_V6, &ip,
+ sizeof(ip));
+ IPV6_ADDR_TO_ARRAY(ip, mask->ipv6_mask.dst_ip);
+ mask->src_port_mask = rte_cpu_to_be_16(port_src);
+ mask->dst_port_mask = rte_cpu_to_be_16(port_dst);
+ }
+
+ cmd_reconfig_device_queue(pid, 1, 1);
+ }
+ break;
+ case 220: {
+ /* "filter flow_director flex_mask %d "
+ "flow %|none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv6-other"
+ "|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload %s" */
+ struct rte_eth_fdir_info fdir_info;
+ struct rte_eth_fdir_flex_mask flex_mask;
+ struct rte_port *port;
+ char *mask, *flow;
+ uint32_t flow_type_mask;
+ uint16_t i;
+
+ pid = atoi(argv[3]);
+ flow = argv[4];
+ mask = argv[6];
+
+ if (pid > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n",
+ nb_ports - 1);
+ return -1;
+ }
+
+ port = &ports[pid];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", pid);
+ return -1;
+ }
+
+ memset(&flex_mask, 0, sizeof(struct rte_eth_fdir_flex_mask));
+ ret = parse_flexbytes(mask,
+ flex_mask.mask,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse mask input.\n");
+ return -1;
+ }
+
+ memset(&fdir_info, 0, sizeof(fdir_info));
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, &fdir_info);
+ if (ret < 0) {
+ printf("Cannot get FDir filter info\n");
+ return -1;
+ }
+
+ if (!strcmp(flow, "none")) {
+ /* means don't specify the flow type */
+ flex_mask.flow_type = RTE_ETH_FLOW_UNKNOWN;
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++)
+ memset(
+ &port->dev_conf.fdir_conf.flex_conf.flex_mask[
+ i],
+ 0,
+ sizeof(struct rte_eth_fdir_flex_mask));
+ port->dev_conf.fdir_conf.flex_conf.nb_flexmasks = 1;
+ (void)rte_memcpy(
+ &port->dev_conf.fdir_conf.flex_conf.flex_mask[
+ 0],
+ &flex_mask,
+ sizeof(struct rte_eth_fdir_flex_mask));
+ cmd_reconfig_device_queue(pid, 1, 1);
+ return -1;
+ }
+ flow_type_mask = fdir_info.flow_types_mask[0];
+ if (!strcmp(flow, "all")) {
+ if (!flow_type_mask) {
+ printf("No flow type supported\n");
+ return -1;
+ }
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX;
+ i++)
+ if (flow_type_mask & (1 << i)) {
+ flex_mask.flow_type = i;
+ fdir_set_flex_mask(pid, &flex_mask);
+ }
+ cmd_reconfig_device_queue(pid, 1, 1);
+ return -1;
+ }
+ flex_mask.flow_type = str2flowtype(flow);
+ if (!(flow_type_mask & (1 << flex_mask.flow_type))) {
+ printf("Flow type %s not supported on port %d\n",
+ flow, pid);
+ return -1;
+ }
+ fdir_set_flex_mask(pid, &flex_mask);
+ cmd_reconfig_device_queue(pid, 1, 1);
+ }
+ break;
+ case 230: { /* filter flow_director flex_payload %d %|raw|l2|l3|l4 %s */
+ struct rte_eth_flex_payload_cfg flex_cfg;
+ struct rte_port *port;
+ char *payload, *layer;
+
+ pid = atoi(argv[3]);
+ layer = argv[4];
+ payload = argv[5];
+
+ if (pid > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n",
+ nb_ports - 1);
+ return -1;
+ }
+
+ port = &ports[pid];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", pid);
+ return -1;
+ }
+
+ memset(&flex_cfg, 0, sizeof(struct rte_eth_flex_payload_cfg));
+
+ if (!strcmp(layer, "raw"))
+ flex_cfg.type = RTE_ETH_RAW_PAYLOAD;
+ else if (!strcmp(layer, "l2"))
+ flex_cfg.type = RTE_ETH_L2_PAYLOAD;
+ else if (!strcmp(layer, "l3"))
+ flex_cfg.type = RTE_ETH_L3_PAYLOAD;
+ else if (!strcmp(layer, "l4"))
+ flex_cfg.type = RTE_ETH_L4_PAYLOAD;
+
+ ret = parse_offsets(payload, flex_cfg.src_offset,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flex payload input.\n");
+ return -1;
+ }
+
+ fdir_set_flex_payload(pid, &flex_cfg);
+ cmd_reconfig_device_queue(pid, 1, 1);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static struct cli_map hash_map[] = {
+ { 0, "hash get sym_hash_ena_per_port %d" },
+ { 10, "hash set sym_hash_ena_per_port %d %|enable|disable" },
+ { 20, "hash hash_global_config get %d" },
+ {
+ 30, "hash set_hash_global_config %d %|toeplitz|simple_xor|default "
+ "%|ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|enable|disable"
+ },
+ {
+ 40, "hash hash_input set %d "
+ "%|ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6| "
+ "ipv4-tos|ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|"
+ "udp-dst-port|tcp-src-port|tcp-dst-port|sctp-src-port|"
+ "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|"
+ "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|"
+ "fld-8th|none "
+ "%|select|add"
+ },
+ {
+ 50, "hash fdir_input set %d "
+ "%|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|"
+ "ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|"
+ "ipv6-hop-limits|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|"
+ "sctp-veri-tag|none "
+ "%|select|add"
+ },
+
+ { -1, NULL }
+};
+
+static char *
+flowtype_to_str(uint16_t ftype)
+{
+ uint16_t i;
+ static struct {
+ char str[16];
+ uint16_t ftype;
+ } ftype_table[] = {
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ {"port", RTE_ETH_FLOW_PORT},
+ {"vxlan", RTE_ETH_FLOW_VXLAN},
+ {"geneve", RTE_ETH_FLOW_GENEVE},
+ {"nvgre", RTE_ETH_FLOW_NVGRE},
+ };
+
+ for (i = 0; i < RTE_DIM(ftype_table); i++)
+ if (ftype_table[i].ftype == ftype)
+ return ftype_table[i].str;
+
+ return NULL;
+}
+
+static enum rte_eth_input_set_field
+str2inset(char *string) {
+ uint16_t i;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_input_set_field inset;
+ } inset_table[] = {
+ {"ethertype", RTE_ETH_INPUT_SET_L2_ETHERTYPE},
+ {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN},
+ {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN},
+ {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4},
+ {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4},
+ {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS},
+ {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO},
+ {"ipv4-ttl", RTE_ETH_INPUT_SET_L3_IP4_TTL},
+ {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6},
+ {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6},
+ {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC},
+ {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER},
+ {"ipv6-hop-limits", RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS},
+ {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},
+ {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT},
+ {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},
+ {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT},
+ {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},
+ {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},
+ {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG},
+ {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY},
+ {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY},
+ {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD},
+ {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD},
+ {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD},
+ {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD},
+ {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD},
+ {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD},
+ {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD},
+ {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD},
+ {"none", RTE_ETH_INPUT_SET_NONE},
+ };
+
+ for (i = 0; i < RTE_DIM(inset_table); i++)
+ if (!strcmp(string, inset_table[i].str))
+ return inset_table[i].inset;
+
+ return RTE_ETH_INPUT_SET_UNKNOWN;
+}
+
+static int
+hash_cmd(int argc, char **argv)
+{
+ int ret;
+ uint8_t pid;
+ struct cli_map *m;
+
+ m = cli_mapping(hash_map, argc, argv);
+ if (!m)
+ return -1;
+
+ switch(m->index) {
+ case 0: { /* hash get sym_hash_ena_per_port %d */
+ struct rte_eth_hash_filter_info info;
+
+ pid = atoi(argv[3]);
+ if (rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf(
+ "RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ pid);
+ return -1;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+
+ if (ret < 0) {
+ printf("Cannot get symmetric hash enable per port "
+ "on port %u\n", pid);
+ return -1;
+ }
+
+ printf("Symmetric hash is %s on port %u\n", info.info.enable ?
+ "enabled" : "disabled", pid);
+ }
+ break;
+ case 10: { /* "hash set sym_hash_ena_per_port %d %|enable|disable" */
+ struct rte_eth_hash_filter_info info;
+
+ pid = atoi(argv[3]);
+ if (rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf(
+ "RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ pid);
+ return -1;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ if (!strcmp(argv[4], "enable"))
+ info.info.enable = 1;
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0) {
+ printf("Cannot set symmetric hash enable per port on "
+ "port %u\n", pid);
+ return -1;
+ }
+ printf("Symmetric hash has been set to %s on port %u\n",
+ argv[4], pid);
+ }
+ break;
+ case 20: { /* "hash hash_global_config get %d" */
+ struct rte_eth_hash_filter_info info;
+ uint32_t idx, offset;
+ uint16_t i;
+ char *str;
+
+ pid = atoi(argv[3]);
+ if (rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ pid);
+ return -1;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+ if (ret < 0) {
+ printf(
+ "Cannot get hash global configurations by port %d\n",
+ pid);
+ return -1;
+ }
+
+ switch (info.info.global_conf.hash_func) {
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ printf("Hash function is Toeplitz\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+ printf("Hash function is Simple XOR\n");
+ break;
+ default:
+ printf("Unknown hash function\n");
+ break;
+ }
+
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
+ idx = i / UINT32_BIT;
+ offset = i % UINT32_BIT;
+ if (!(info.info.global_conf.valid_bit_mask[idx] &
+ (1UL << offset)))
+ continue;
+ str = flowtype_to_str(i);
+ if (!str)
+ continue;
+ printf("Symmetric hash is %s globally for flow type %s "
+ "by port %d\n",
+ ((info.info.global_conf.sym_hash_enable_mask[idx]
+ &
+ (1UL << offset)) ? "enabled" : "disabled"),
+ str,
+ pid);
+ }
+ }
+ break;
+ case 30: {
+ /* "hash set_hash_global_config %d %|toeplitz|simple_xor|default "
+ "%|ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|enable|disable" */
+ struct rte_eth_hash_filter_info info;
+ uint32_t ftype, idx, offset;
+ char *hash, *flow, *on;
+
+ pid = atoi(argv[2]);
+ hash = argv[3];
+ flow = argv[4];
+ on = argv[5];
+ if (rte_eth_dev_filter_supported(pid,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ pid);
+ return -1;
+ }
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ if (!strcmp(hash, "toeplitz"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+ else if (!strcmp(hash, "simple_xor"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+ else if (!strcmp(hash, "default"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_DEFAULT;
+
+ ftype = str2flowtype(flow);
+ idx = ftype / (CHAR_BIT * sizeof(uint32_t));
+ offset = ftype % (CHAR_BIT * sizeof(uint32_t));
+ info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset);
+ if (!strcmp(on, "enable"))
+ info.info.global_conf.sym_hash_enable_mask[idx] |=
+ (1UL << offset);
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0)
+ printf(
+ "Cannot set global hash configurations by port %d\n",
+ pid);
+ else
+ printf("Global hash configurations have been set "
+ "succcessfully by port %d\n", pid);
+ }
+ break;
+ case 40: {
+ /* "hash hash_input set %d "
+ "%|ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6| "
+ "ipv4-tos|ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|"
+ "udp-dst-port|tcp-src-port|tcp-dst-port|sctp-src-port|"
+ "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|"
+ "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|"
+ "fld-8th|none "
+ "%|select|add" */
+ struct rte_eth_hash_filter_info info;
+ char *flow, *field, *select;
+
+ pid = atoi(argv[3]);
+ flow = argv[4];
+ field = argv[5];
+ select = argv[6];
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(flow);
+ info.info.input_set_conf.field[0] = str2inset(field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ }
+ break;
+ case 50: {
+ /* "hash fdir_input set %d "
+ "%|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "%|ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|"
+ "ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|"
+ "ipv6-hop-limits|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|"
+ "sctp-veri-tag|none "
+ "%|select|add" */
+ struct rte_eth_fdir_filter_info info;
+ char *flow, *field, *select;
+
+ pid = atoi(argv[3]);
+ flow = argv[4];
+ field = argv[5];
+ select = argv[6];
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(flow);
+ info.info.input_set_conf.field[0] = str2inset(field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_SET, &info);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static struct cli_map reg_map[] = {
+ { 0, "reg read %d %d" },
+ { 10, "reg field read %d %d %d %d" },
+ { 20, "reg bit read %d %d %d" },
+ { 30, "reg write %d %d %d" },
+ { 40, "reg field write %d %d %d %d %d" },
+ { 50, "reg bit write %d %d %d %d" },
+ { -1, NULL }
+};
+
+static int
+reg_cmd(int argc, char **argv)
+{
+ int off, val, bit1, bit2;
+ uint8_t pid;
+ struct cli_map *m;
+
+ m = cli_mapping(reg_map, argc, argv);
+ if (!m)
+ return -1;
+
+ switch(m->index) {
+ case 0: /* reg read %d %d */
+ pid = atoi(argv[2]);
+ off = atoi(argv[3]);
+ port_reg_display(pid, off);
+ break;
+ case 10: /* reg field read %d %d %d %d */
+ pid = atoi(argv[3]);
+ off = atoi(argv[4]);
+ bit1 = atoi(argv[5]);
+ bit2 = atoi(argv[6]);
+ port_reg_bit_field_display(pid, off, bit1, bit2);
+ break;
+ case 20: /* reg bit read %d %d %d */
+ pid = atoi(argv[3]);
+ off = atoi(argv[4]);
+ bit1 = atoi(argv[5]);
+ port_reg_bit_display(pid, off, bit1);
+ break;
+ case 30: /* reg write %d %d %d */
+ pid = atoi(argv[2]);
+ off = atoi(argv[3]);
+ val = atoi(argv[4]);
+ port_reg_set(pid, off, val);
+ break;
+ case 40: /* reg field write %d %d %d %d %d */
+ pid = atoi(argv[3]);
+ off = atoi(argv[4]);
+ bit1 = atoi(argv[5]);
+ bit2 = atoi(argv[6]);
+ val = atoi(argv[7]);
+ port_reg_bit_field_set(pid, off, bit1, bit2, val);
+ break;
+ case 50: /* reg bit write %d %d %d %d */
+ pid = atoi(argv[3]);
+ off = atoi(argv[4]);
+ bit1 = atoi(argv[5]);
+ val = atoi(argv[6]);
+ port_reg_bit_set(pid, off, bit1, val);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static struct cli_map misc_map[] = {
+ { 0, "misc global_config %d gre-key-len %d" },
+ {
+ 10,
+ "misc dump %|physmen|memzone|struct_sizes|ring|mempool|devargs"
+ },
+ { 20, "misc dump %|ring|mempool %s" },
+ { 30, "misc mcast_addr %|add|remove %d %m" },
+ { -1, NULL }
+};
+
+static void
+dump_struct_sizes(void)
+{
+#define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
+ DUMP_SIZE(struct rte_mbuf);
+ DUMP_SIZE(struct rte_mempool);
+ DUMP_SIZE(struct rte_ring);
+#undef DUMP_SIZE
+}
+static int
+misc_cmd(int argc, char **argv)
+{
+ int ret;
+ uint8_t pid;
+ struct cli_map *m;
+ struct ether_addr *mac;
+ char *opt;
+
+ (void)pid;
+ (void)ret;
+ m = cli_mapping(misc_map, argc, argv);
+ if (!m)
+ return -1;
+
+ switch(m->index) {
+ case 0: { /* misc global_config %d gre-key-len %d */
+ struct rte_eth_global_cfg conf;
+
+ pid = atoi(argv[2]);
+ memset(&conf, 0, sizeof(conf));
+ conf.cfg_type = RTE_ETH_GLOBAL_CFG_TYPE_GRE_KEY_LEN;
+ conf.cfg.gre_key_len = atoi(argv[4]);
+ ret = rte_eth_dev_filter_ctrl(pid, RTE_ETH_FILTER_NONE,
+ RTE_ETH_FILTER_SET, &conf);
+ if (ret != 0)
+ printf("Global config error\n");
+ }
+ break;
+ case 10: /* misc dump %|physmen|memzone|struct_sizes|ring|mempool|devargs */
+ opt = argv[2];
+ ret = rte_stropt(
+ "physmen|memzone|struct_sizes|ring|mempool|devargs",
+ opt, "|");
+ switch(ret) {
+ case 0:
+ rte_dump_physmem_layout(stdout);
+ break;
+ case 1:
+ rte_memzone_dump(stdout);
+ break;
+ case 2:
+ dump_struct_sizes();
+ break;
+ case 3:
+ rte_ring_list_dump(stdout);
+ break;
+ case 4:
+ rte_mempool_list_dump(stdout);
+ break;
+ case 5:
+ rte_eal_devargs_dump(stdout);
+ break;
+ }
+ break;
+ case 20: /* misc dump %|ring|mempool %s */
+ opt = argv[2];
+ if (!strcmp(opt, "ring")) {
+ struct rte_ring *r;
+ r = rte_ring_lookup(argv[3]);
+ if (r == NULL) {
+ cli_printf("Cannot find ring\n");
+ return -1;
+ }
+ rte_ring_dump(stdout, r);
+ } else if (!strcmp(opt, "mempool")) {
+ struct rte_mempool *mp;
+ mp = rte_mempool_lookup(argv[3]);
+ if (mp == NULL) {
+ cli_printf("Cannot find mempool\n");
+ return -1;
+ }
+ rte_mempool_dump(stdout, mp);
+ }
+ break;
+ case 30: /* misc mcast_addr %|add|remove %d %m */
+ opt = argv[2];
+ pid = atoi(argv[3]);
+ mac = rte_ether_aton(argv[4], NULL);
+ if (!is_multicast_ether_addr(mac)) {
+ printf(
+ "Invalid multicast addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+ mac->addr_bytes[0], mac->addr_bytes[1],
+ mac->addr_bytes[2], mac->addr_bytes[3],
+ mac->addr_bytes[4], mac->addr_bytes[5]);
+ return -1;
+ }
+ if (strcmp(opt, "add") == 0)
+ mcast_addr_add(pid, mac);
+ else
+ mcast_addr_remove(pid, mac);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int
+reset_cmd(int argc, char **argv)
+{
+ if (argc != 2) {
+ cli_usage();
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "default"))
+ set_def_fwd_config();
+
+ return 0;
+}
+
+static struct cli_tree default_tree[] = {
+ c_dir("/pmd"),
+ c_cmd("help-pmd", help_cmd, "help command"),
+
+ c_cmd("start", control_cmd, "Start packet forwarding"),
+ c_cmd("stop", control_cmd, "Stop packet forwarding"),
+ c_cmd("link-up", port_cmd, "set port link state up"),
+ c_cmd("link-down", port_cmd, "set port link state down"),
+ c_cmd("reset", reset_cmd,
+ "reset to default forwarding"),
+
+ c_cmd("misc", misc_cmd, "Misc commands"),
+ c_cmd("port", port_cmd, "port commands"),
+ c_cmd("set", set_cmd, "Set commands"),
+ c_cmd("reg", reg_cmd, "register commands"),
+ c_cmd("filter", filter_cmd, "filter commands"),
+ c_cmd("hash", hash_cmd, "hash commands"),
+
+ c_end()
+};
+
+static int
+init_tree(void)
+{
+ if (cli_default_tree_init())
+ return -1;
+
+ if (cli_add_tree(cli_root_node(), default_tree))
+ return -1;
+
+ if (cli_add_bin_path("/pmd"))
+ return -1;
+
+ return 0;
+}
+
+static void
+my_prompt(int cont __rte_unused)
+{
+ cli_printf("test_pmd:%s> ", cli_path_string(NULL, NULL));
+}
+
+void
+prompt_cli(void)
+{
+ if (cli_create(my_prompt, init_tree,
+ CLI_DEFAULT_NODES, CLI_DEFAULT_HISTORY))
+ return;
+
+ cli_printf("\n\n");
+ cli_start("CLI Test Application");
+
+ cli_destroy();
+}
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 84e7a63..bc0b459 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -639,6 +639,9 @@ launch_args_parse(int argc, char** argv)
{ "flow-isolate-all", 0, 0, 0 },
{ "txpkts", 1, 0, 0 },
{ "disable-link-check", 0, 0, 0 },
+#ifdef RTE_LIBRTE_CLI
+ { "cli-interactive", 0, 0, 0 },
+#endif
{ "no-lsc-interrupt", 0, 0, 0 },
{ "no-rmv-interrupt", 0, 0, 0 },
{ "print-event", 1, 0, 0 },
@@ -649,10 +652,19 @@ launch_args_parse(int argc, char** argv)
argvopt = argv;
#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIBRTE_CLI
+#define SHORTOPTS "iI"
+#else
+#define SHORTOPTS "i"
+#endif
+#else
+#ifdef RTE_LIBRTE_CLI
#define SHORTOPTS "i"
#else
#define SHORTOPTS ""
#endif
+#endif
+
while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
lgopts, &opt_idx)) != EOF) {
switch (opt) {
@@ -661,6 +673,19 @@ launch_args_parse(int argc, char** argv)
printf("Interactive-mode selected\n");
interactive = 1;
break;
+#ifdef RTE_LIBRTE_CLI
+ case 'I':
+ printf("Interactive-mode selected\n");
+ interactive = 2;
+ break;
+#endif
+#else
+#ifdef RTE_LIBRTE_CLI
+ case 'i':
+ printf("Interactive-mode selected\n");
+ interactive = 2;
+ break;
+#endif
#endif
case 'a':
printf("Auto-start selected\n");
@@ -735,6 +760,19 @@ launch_args_parse(int argc, char** argv)
peer_addr[c];
nb_peer_eth_addrs++;
}
+#ifdef RTE_LIBRTE_CLI
+ if (!strcmp(lgopts[opt_idx].name, "cli-interactive")) {
+ printf("Interactive-mode selected\n");
+ interactive = 2;
+ }
+#endif
+#else
+#ifdef RTE_LIBRTE_CLI
+ if (!strcmp(lgopts[opt_idx].name, "interactive")) {
+ printf("Interactive-mode selected\n");
+ interactive = 2;
+ }
+#endif
#endif
if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
n = atoi(optarg);
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index c3ab448..5822979 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2474,14 +2474,32 @@ main(int argc, char** argv)
if (strlen(cmdline_filename) != 0)
cmdline_read_from_file(cmdline_filename);
- if (interactive == 1) {
+ if (interactive) {
if (auto_start) {
printf("Start automatic packet forwarding\n");
start_packet_forwarding(0);
}
- prompt();
+ if (interactive == 1)
+ prompt();
+#ifdef RTE_LIBRTE_CLI
+ else if (interactive == 2)
+ prompt_cli();
+#endif
pmd_test_exit();
} else
+#else
+#ifdef RTE_LIBRTE_CLI
+ if (interactive) {
+ if (auto_start) {
+ printf("Start automatic packet forwarding\n");
+ start_packet_forwarding(0);
+ }
+ if (interactive == 2)
+ prompt_cli();
+
+ pmd_test_exit();
+ } else
+#endif
#endif
{
char c;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 1639d27..33f4ff3 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -582,6 +582,9 @@ unsigned int parse_item_list(char* str, const char* item_name,
void launch_args_parse(int argc, char** argv);
void cmdline_read_from_file(const char *filename);
void prompt(void);
+#ifdef RTE_LIBRTE_CLI
+void prompt_cli(void);
+#endif
void prompt_exit(void);
void nic_stats_display(portid_t port_id);
void nic_stats_clear(portid_t port_id);