* BSD LICENSE
*
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ * Copyright 2013-2014 6WIND S.A.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* BSD LICENSE
- *
- * Copyright 2013-2014 6WIND S.A.
- *
- * 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 6WIND S.A. 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.
- */
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
-#include <stdarg.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_byteorder.h>
#ifdef RTE_LIBRTE_IXGBE_PMD
#include <rte_pmd_ixgbe.h>
#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+#include <rte_pmd_bnxt.h>
+#endif
+#include <rte_gro.h>
#include "testpmd.h"
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
- FOREACH_PORT(pid, ports)
+ RTE_ETH_FOREACH_DEV(pid)
printf(", %d", pid);
printf("]\n");
return;
if (diff_cycles > 0)
diff_cycles = prev_cycles[port_id] - diff_cycles;
- diff_pkts_rx = stats.ipackets - prev_pkts_rx[port_id];
- diff_pkts_tx = stats.opackets - prev_pkts_tx[port_id];
+ diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
+ (stats.ipackets - prev_pkts_rx[port_id]) : 0;
+ diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ?
+ (stats.opackets - prev_pkts_tx[port_id]) : 0;
prev_pkts_rx[port_id] = stats.ipackets;
prev_pkts_tx[port_id] = stats.opackets;
mpps_rx = diff_cycles > 0 ?
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
- FOREACH_PORT(pid, ports)
+ RTE_ETH_FOREACH_DEV(pid)
printf(", %d", pid);
printf("]\n");
return;
}
/* Display xstats */
- for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+ for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) {
+ if (xstats_hide_zero && !xstats[idx_xstat].value)
+ continue;
printf("%s: %"PRIu64"\n",
xstats_names[idx_xstat].name,
xstats[idx_xstat].value);
+ }
free(xstats_names);
free(xstats);
}
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
- FOREACH_PORT(pid, ports)
+ RTE_ETH_FOREACH_DEV(pid)
printf(", %d", pid);
printf("]\n");
return;
rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
if (rc != 0) {
- printf("Failed to retrieve information for port: %hhu, "
+ printf("Failed to retrieve information for port: %u, "
"RX queue: %hu\nerror desc: %s(%d)\n",
port_id, queue_id, strerror(-rc), rc);
return;
rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
if (rc != 0) {
- printf("Failed to retrieve information for port: %hhu, "
+ printf("Failed to retrieve information for port: %u, "
"TX queue: %hu\nerror desc: %s(%d)\n",
port_id, queue_id, strerror(-rc), rc);
return;
struct rte_mempool * mp;
static const char *info_border = "*********************";
portid_t pid;
+ uint16_t mtu;
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
printf("Valid port range is [0");
- FOREACH_PORT(pid, ports)
+ RTE_ETH_FOREACH_DEV(pid)
printf(", %d", pid);
printf("]\n");
return;
printf("Link speed: %u Mbps\n", (unsigned) link.link_speed);
printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
("full-duplex") : ("half-duplex"));
+
+ if (!rte_eth_dev_get_mtu(port_id, &mtu))
+ printf("MTU: %u\n", mtu);
+
printf("Promiscuous mode: %s\n",
rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled");
printf("Allmulticast mode: %s\n",
char *p;
printf("Supported flow types:\n");
- for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX;
- i++) {
+ for (i = RTE_ETH_FLOW_UNKNOWN + 1;
+ i < sizeof(dev_info.flow_type_rss_offloads) * CHAR_BIT; i++) {
if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
continue;
p = flowtype_to_str(i);
- printf(" %s\n", (p ? p : "unknown"));
+ if (p)
+ printf(" %s\n", p);
+ else
+ printf(" user defined %d\n", i);
}
}
printf("off\n");
}
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP) {
+ printf("HW timestamp: ");
+ if (dev->data->dev_conf.rxmode.hw_timestamp)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
printf("Double VLANs insert: ");
if (ports[port_id].tx_ol_flags &
if (port_id == (portid_t)RTE_PORT_ALL)
return 0;
- if (port_id < RTE_MAX_ETHPORTS && ports[port_id].enabled)
+ if (rte_eth_dev_is_valid_port(port_id))
return 0;
if (warning == ENABLED_WARN)
MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+ MK_FLOW_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
+ MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+ MK_FLOW_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)),
+ MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
+ MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
+ MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
};
/** Compute storage space needed by item specification. */
flow_item_spec_size(const struct rte_flow_item *item,
size_t *size, size_t *pad)
{
- if (!item->spec)
+ if (!item->spec) {
+ *size = 0;
goto empty;
+ }
switch (item->type) {
union {
const struct rte_flow_item_raw *raw;
spec.raw->length * sizeof(*spec.raw->pattern);
break;
default:
-empty:
- *size = 0;
+ *size = flow_item[item->type].size;
break;
}
+empty:
*pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
}
flow_action_conf_size(const struct rte_flow_action *action,
size_t *size, size_t *pad)
{
- if (!action->conf)
+ if (!action->conf) {
+ *size = 0;
goto empty;
+ }
switch (action->type) {
union {
const struct rte_flow_action_rss *rss;
conf.rss->num * sizeof(*conf.rss->queue);
break;
default:
-empty:
- *size = 0;
+ *size = flow_action[action->type].size;
break;
}
+empty:
*pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
}
}
}
+/** Restrict ingress traffic to the defined flow rules. */
+int
+port_flow_isolate(portid_t port_id, int set)
+{
+ struct rte_flow_error error;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x66, sizeof(error));
+ if (rte_flow_isolate(port_id, set, &error))
+ return port_flow_complain(&error);
+ printf("Ingress traffic on port %u is %s to the defined flow rules\n",
+ port_id,
+ set ? "now restricted" : "not restricted anymore");
+ return 0;
+}
+
/*
* RX/TX ring descriptors display functions.
*/
}
static const struct rte_memzone *
-ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id)
+ring_dma_zone_lookup(const char *ring_name, portid_t port_id, uint16_t q_id)
{
char mz_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
static void
ring_rx_descriptor_display(const struct rte_memzone *ring_mz,
#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
- uint8_t port_id,
+ portid_t port_id,
#else
- __rte_unused uint8_t port_id,
+ __rte_unused portid_t port_id,
#endif
uint16_t desc_id)
{
fwd_streams[i]->rx_queue = 0;
fwd_streams[i]->tx_port = fwd_ports_ids[j];
fwd_streams[i]->tx_queue = 0;
- fwd_streams[i]->peer_addr = j;
+ fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port;
fwd_streams[i]->retry_enabled = retry_enabled;
if (port_topology == PORT_TOPOLOGY_PAIRED) {
fwd_streams[j]->rx_queue = 0;
fwd_streams[j]->tx_port = fwd_ports_ids[i];
fwd_streams[j]->tx_queue = 0;
- fwd_streams[j]->peer_addr = i;
+ fwd_streams[j]->peer_addr = fwd_streams[j]->tx_port;
fwd_streams[j]->retry_enabled = retry_enabled;
}
}
return;
}
nb_pt = 0;
- for (i = 0; i < (unsigned)RTE_MIN(64, RTE_MAX_ETHPORTS); i++) {
+ RTE_ETH_FOREACH_DEV(i) {
if (! ((uint64_t)(1ULL << i) & portmask))
continue;
portlist[nb_pt++] = i;
tx_pkt_nb_segs = (uint8_t) nb_segs;
}
+void
+setup_gro(const char *onoff, portid_t port_id)
+{
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("invalid port id %u\n", port_id);
+ return;
+ }
+ if (test_done == 0) {
+ printf("Before enable/disable GRO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ if (strcmp(onoff, "on") == 0) {
+ if (gro_ports[port_id].enable != 0) {
+ printf("Port %u has enabled GRO. Please"
+ " disable GRO first\n", port_id);
+ return;
+ }
+ if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
+ gro_ports[port_id].param.gro_types = RTE_GRO_TCP_IPV4;
+ gro_ports[port_id].param.max_flow_num =
+ GRO_DEFAULT_FLOW_NUM;
+ gro_ports[port_id].param.max_item_per_flow =
+ GRO_DEFAULT_ITEM_NUM_PER_FLOW;
+ }
+ gro_ports[port_id].enable = 1;
+ } else {
+ if (gro_ports[port_id].enable == 0) {
+ printf("Port %u has disabled GRO\n", port_id);
+ return;
+ }
+ gro_ports[port_id].enable = 0;
+ }
+}
+
+void
+setup_gro_flush_cycles(uint8_t cycles)
+{
+ if (test_done == 0) {
+ printf("Before change flush interval for GRO,"
+ " please stop forwarding first.\n");
+ return;
+ }
+
+ if (cycles > GRO_MAX_FLUSH_CYCLES || cycles <
+ GRO_DEFAULT_FLUSH_CYCLES) {
+ printf("The flushing cycle be in the range"
+ " of 1 to %u. Revert to the default"
+ " value %u.\n",
+ GRO_MAX_FLUSH_CYCLES,
+ GRO_DEFAULT_FLUSH_CYCLES);
+ cycles = GRO_DEFAULT_FLUSH_CYCLES;
+ }
+
+ gro_flush_cycles = cycles;
+}
+
+void
+show_gro(portid_t port_id)
+{
+ struct rte_gro_param *param;
+ uint32_t max_pkts_num;
+
+ param = &gro_ports[port_id].param;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("Invalid port id %u.\n", port_id);
+ return;
+ }
+ if (gro_ports[port_id].enable) {
+ printf("GRO type: TCP/IPv4\n");
+ if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
+ max_pkts_num = param->max_flow_num *
+ param->max_item_per_flow;
+ } else
+ max_pkts_num = MAX_PKT_BURST * GRO_MAX_FLUSH_CYCLES;
+ printf("Max number of packets to perform GRO: %u\n",
+ max_pkts_num);
+ printf("Flushing cycles: %u\n", gro_flush_cycles);
+ } else
+ printf("Port %u doesn't enable GRO.\n", port_id);
+}
+
+void
+setup_gso(const char *mode, portid_t port_id)
+{
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("invalid port id %u\n", port_id);
+ return;
+ }
+ if (strcmp(mode, "on") == 0) {
+ if (test_done == 0) {
+ printf("before enabling GSO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ gso_ports[port_id].enable = 1;
+ } else if (strcmp(mode, "off") == 0) {
+ if (test_done == 0) {
+ printf("before disabling GSO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ gso_ports[port_id].enable = 0;
+ }
+}
+
char*
list_pkt_forwarding_modes(void)
{
}
}
+void
+set_xstats_hide_zero(uint8_t on_off)
+{
+ xstats_hide_zero = on_off;
+}
+
static inline void
print_fdir_mask(struct rte_eth_fdir_masks *mask)
{
return;
}
}
- (void)rte_memcpy(&flex_conf->flex_mask[idx],
+ rte_memcpy(&flex_conf->flex_mask[idx],
cfg,
sizeof(struct rte_eth_fdir_flex_mask));
}
return;
}
}
- (void)rte_memcpy(&flex_conf->flex_set[idx],
+ rte_memcpy(&flex_conf->flex_set[idx],
cfg,
sizeof(struct rte_eth_flex_payload_cfg));
}
-#ifdef RTE_LIBRTE_IXGBE_PMD
void
set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
{
+#ifdef RTE_LIBRTE_IXGBE_PMD
int diag;
if (is_rx)
if (diag == 0)
return;
- if(is_rx)
- printf("rte_pmd_ixgbe_set_vf_rx for port_id=%d failed "
- "diag=%d\n", port_id, diag);
- else
- printf("rte_pmd_ixgbe_set_vf_tx for port_id=%d failed "
- "diag=%d\n", port_id, diag);
-
-}
+ printf("rte_pmd_ixgbe_set_vf_%s for port_id=%d failed diag=%d\n",
+ is_rx ? "rx" : "tx", port_id, diag);
+ return;
#endif
+ printf("VF %s setting not supported for port %d\n",
+ is_rx ? "Rx" : "Tx", port_id);
+ RTE_SET_USED(vf);
+ RTE_SET_USED(on);
+}
int
set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
return diag;
}
-#ifdef RTE_LIBRTE_IXGBE_PMD
int
set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
{
- int diag;
+ int diag = -ENOTSUP;
- diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate, q_msk);
+ RTE_SET_USED(vf);
+ RTE_SET_USED(rate);
+ RTE_SET_USED(q_msk);
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (diag == -ENOTSUP)
+ diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate,
+ q_msk);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (diag == -ENOTSUP)
+ diag = rte_pmd_bnxt_set_vf_rate_limit(port_id, vf, rate, q_msk);
+#endif
if (diag == 0)
return diag;
- printf("rte_pmd_ixgbe_set_vf_rate_limit for port_id=%d failed diag=%d\n",
+
+ printf("set_vf_rate_limit for port_id=%d failed diag=%d\n",
port_id, diag);
return diag;
}
-#endif
/*
* Functions to manage the set of filtered Multicast MAC addresses.
}
static void
-eth_port_multicast_addr_list_set(uint8_t port_id)
+eth_port_multicast_addr_list_set(portid_t port_id)
{
struct rte_port *port;
int diag;
}
void
-mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr)
+mcast_addr_add(portid_t port_id, struct ether_addr *mc_addr)
{
struct rte_port *port;
uint32_t i;
}
void
-mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr)
+mcast_addr_remove(portid_t port_id, struct ether_addr *mc_addr)
{
struct rte_port *port;
uint32_t i;
}
void
-port_dcb_info_display(uint8_t port_id)
+port_dcb_info_display(portid_t port_id)
{
struct rte_eth_dcb_info dcb_info;
uint16_t i;
uint8_t *
open_ddp_package_file(const char *file_path, uint32_t *size)
{
- FILE *fh = fopen(file_path, "rb");
- uint32_t pkg_size;
+ int fd = open(file_path, O_RDONLY);
+ off_t pkg_size;
uint8_t *buf = NULL;
int ret = 0;
+ struct stat st_buf;
if (size)
*size = 0;
- if (fh == NULL) {
+ if (fd == -1) {
printf("%s: Failed to open %s\n", __func__, file_path);
return buf;
}
- ret = fseek(fh, 0, SEEK_END);
- if (ret < 0) {
- fclose(fh);
+ if ((fstat(fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
+ close(fd);
printf("%s: File operations failed\n", __func__);
return buf;
}
- pkg_size = ftell(fh);
+ pkg_size = st_buf.st_size;
+ if (pkg_size < 0) {
+ close(fd);
+ printf("%s: File operations failed\n", __func__);
+ return buf;
+ }
buf = (uint8_t *)malloc(pkg_size);
if (!buf) {
- fclose(fh);
+ close(fd);
printf("%s: Failed to malloc memory\n", __func__);
return buf;
}
- ret = fseek(fh, 0, SEEK_SET);
- if (ret < 0) {
- fclose(fh);
- printf("%s: File seek operation failed\n", __func__);
- close_ddp_package_file(buf);
- return NULL;
- }
-
- ret = fread(buf, 1, pkg_size, fh);
+ ret = read(fd, buf, pkg_size);
if (ret < 0) {
- fclose(fh);
+ close(fd);
printf("%s: File read operation failed\n", __func__);
close_ddp_package_file(buf);
return NULL;
if (size)
*size = pkg_size;
- fclose(fh);
+ close(fd);
return buf;
}
+int
+save_ddp_package_file(const char *file_path, uint8_t *buf, uint32_t size)
+{
+ FILE *fh = fopen(file_path, "wb");
+
+ if (fh == NULL) {
+ printf("%s: Failed to open %s\n", __func__, file_path);
+ return -1;
+ }
+
+ if (fwrite(buf, 1, size, fh) != size) {
+ fclose(fh);
+ printf("%s: File write operation failed\n", __func__);
+ return -1;
+ }
+
+ fclose(fh);
+
+ return 0;
+}
+
int
close_ddp_package_file(uint8_t *buf)
{
return -1;
}
+
+void
+port_queue_region_info_display(portid_t port_id, void *buf)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+ uint16_t i, j;
+ struct rte_pmd_i40e_queue_regions *info =
+ (struct rte_pmd_i40e_queue_regions *)buf;
+ static const char *queue_region_info_stats_border = "-------";
+
+ if (!info->queue_region_number)
+ printf("there is no region has been set before");
+
+ printf("\n %s All queue region info for port=%2d %s",
+ queue_region_info_stats_border, port_id,
+ queue_region_info_stats_border);
+ printf("\n queue_region_number: %-14u \n",
+ info->queue_region_number);
+
+ for (i = 0; i < info->queue_region_number; i++) {
+ printf("\n region_id: %-14u queue_number: %-14u "
+ "queue_start_index: %-14u \n",
+ info->region[i].region_id,
+ info->region[i].queue_num,
+ info->region[i].queue_start_index);
+
+ printf(" user_priority_num is %-14u :",
+ info->region[i].user_priority_num);
+ for (j = 0; j < info->region[i].user_priority_num; j++)
+ printf(" %-14u ", info->region[i].user_priority[j]);
+
+ printf("\n flowtype_num is %-14u :",
+ info->region[i].flowtype_num);
+ for (j = 0; j < info->region[i].flowtype_num; j++)
+ printf(" %-14u ", info->region[i].hw_flowtype[j]);
+ }
+#else
+ RTE_SET_USED(port_id);
+ RTE_SET_USED(buf);
+#endif
+
+ printf("\n\n");
+}