#define ETHDEV_FWVERS_LEN 32
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE_ID CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE_ID CLOCK_MONOTONIC
+#endif
+
+#define NS_PER_SEC 1E9
+
static char *flowtype_to_str(uint16_t flow_type);
static const struct {
const struct rss_type_info rss_type_table[] = {
{ "all", ETH_RSS_ETH | ETH_RSS_VLAN | ETH_RSS_IP | ETH_RSS_TCP |
ETH_RSS_UDP | ETH_RSS_SCTP | ETH_RSS_L2_PAYLOAD |
- ETH_RSS_L2TPV3 | ETH_RSS_ESP | ETH_RSS_AH | ETH_RSS_PFCP},
+ ETH_RSS_L2TPV3 | ETH_RSS_ESP | ETH_RSS_AH | ETH_RSS_PFCP |
+ ETH_RSS_GTPU},
{ "none", 0 },
{ "eth", ETH_RSS_ETH },
{ "l2-src-only", ETH_RSS_L2_SRC_ONLY },
{ "ah", ETH_RSS_AH },
{ "l2tpv3", ETH_RSS_L2TPV3 },
{ "pfcp", ETH_RSS_PFCP },
+ { "pppoe", ETH_RSS_PPPOE },
+ { "gtpu", ETH_RSS_GTPU },
{ NULL, 0 },
};
static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
- static uint64_t prev_cycles[RTE_MAX_ETHPORTS];
+ static uint64_t prev_ns[RTE_MAX_ETHPORTS];
+ struct timespec cur_time;
uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx,
- diff_cycles;
+ diff_ns;
uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
struct rte_eth_stats stats;
struct rte_port *port = &ports[port_id];
}
}
- diff_cycles = prev_cycles[port_id];
- prev_cycles[port_id] = rte_rdtsc();
- if (diff_cycles > 0)
- diff_cycles = prev_cycles[port_id] - diff_cycles;
+ diff_ns = 0;
+ if (clock_gettime(CLOCK_TYPE_ID, &cur_time) == 0) {
+ uint64_t ns;
+
+ ns = cur_time.tv_sec * NS_PER_SEC;
+ ns += cur_time.tv_nsec;
+
+ if (prev_ns[port_id] != 0)
+ diff_ns = ns - prev_ns[port_id];
+ prev_ns[port_id] = ns;
+ }
diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
(stats.ipackets - prev_pkts_rx[port_id]) : 0;
(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 ?
- diff_pkts_rx * rte_get_tsc_hz() / diff_cycles : 0;
- mpps_tx = diff_cycles > 0 ?
- diff_pkts_tx * rte_get_tsc_hz() / diff_cycles : 0;
+ mpps_rx = diff_ns > 0 ?
+ (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;
+ mpps_tx = diff_ns > 0 ?
+ (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;
diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?
(stats.ibytes - prev_bytes_rx[port_id]) : 0;
(stats.obytes - prev_bytes_tx[port_id]) : 0;
prev_bytes_rx[port_id] = stats.ibytes;
prev_bytes_tx[port_id] = stats.obytes;
- mbps_rx = diff_cycles > 0 ?
- diff_bytes_rx * rte_get_tsc_hz() / diff_cycles : 0;
- mbps_tx = diff_cycles > 0 ?
- diff_bytes_tx * rte_get_tsc_hz() / diff_cycles : 0;
+ mbps_rx = diff_ns > 0 ?
+ (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;
+ mbps_tx = diff_ns > 0 ?
+ (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;
printf("\n Throughput (since last show)\n");
printf(" Rx-pps: %12"PRIu64" Rx-bps: %12"PRIu64"\n Tx-pps: %12"
void
nic_stats_clear(portid_t port_id)
{
+ int ret;
+
if (port_id_is_invalid(port_id, ENABLED_WARN)) {
print_valid_ports();
return;
}
- rte_eth_stats_reset(port_id);
+
+ ret = rte_eth_stats_reset(port_id);
+ if (ret != 0) {
+ printf("%s: Error: failed to reset stats (port %u): %s",
+ __func__, port_id, strerror(-ret));
+ return;
+ }
+
+ ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+ if (ret != 0) {
+ if (ret < 0)
+ ret = -ret;
+ printf("%s: Error: failed to get stats (port %u): %s",
+ __func__, port_id, strerror(ret));
+ return;
+ }
printf("\n NIC statistics for port %d cleared\n", port_id);
}
print_valid_ports();
return;
}
+
ret = rte_eth_xstats_reset(port_id);
if (ret != 0) {
printf("%s: Error: failed to reset xstats (port %u): %s",
+ __func__, port_id, strerror(-ret));
+ return;
+ }
+
+ ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+ if (ret != 0) {
+ if (ret < 0)
+ ret = -ret;
+ printf("%s: Error: failed to get stats (port %u): %s",
__func__, port_id, strerror(ret));
+ return;
}
}
return;
}
diag = rte_eth_dev_set_mtu(port_id, mtu);
- if (diag == 0 &&
- dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) {
+ if (diag)
+ printf("Set MTU failed. diag=%d\n", diag);
+ else if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) {
/*
* Ether overhead in driver is equal to the difference of
* max_rx_pktlen and max_mtu in rte_eth_dev_info when the
} else
rte_port->dev_conf.rxmode.offloads &=
~DEV_RX_OFFLOAD_JUMBO_FRAME;
-
- return;
}
- printf("Set MTU failed. diag=%d\n", diag);
}
/* Generic flow management functions. */
return -err;
}
+static void
+rss_config_display(struct rte_flow_action_rss *rss_conf)
+{
+ uint8_t i;
+
+ if (rss_conf == NULL) {
+ printf("Invalid rule\n");
+ return;
+ }
+
+ printf("RSS:\n"
+ " queues: ");
+ if (rss_conf->queue_num == 0)
+ printf("none\n");
+ for (i = 0; i < rss_conf->queue_num; i++)
+ printf("%d\n", rss_conf->queue[i]);
+
+ printf(" function: ");
+ switch (rss_conf->func) {
+ case RTE_ETH_HASH_FUNCTION_DEFAULT:
+ printf("default\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ printf("toeplitz\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+ printf("simple_xor\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
+ printf("symmetric_toeplitz\n");
+ break;
+ default:
+ printf("Unknown function\n");
+ return;
+ }
+
+ printf(" types:\n");
+ if (rss_conf->types == 0) {
+ printf(" none\n");
+ return;
+ }
+ for (i = 0; rss_type_table[i].str; i++) {
+ if ((rss_conf->types &
+ rss_type_table[i].rss_type) ==
+ rss_type_table[i].rss_type &&
+ rss_type_table[i].rss_type != 0)
+ printf(" %s\n", rss_type_table[i].str);
+ }
+}
+
/** Validate flow rule. */
int
port_flow_validate(portid_t port_id,
const char *name;
union {
struct rte_flow_query_count count;
+ struct rte_flow_action_rss rss_conf;
} query;
int ret;
return port_flow_complain(&error);
switch (action->type) {
case RTE_FLOW_ACTION_TYPE_COUNT:
+ case RTE_FLOW_ACTION_TYPE_RSS:
break;
default:
printf("Cannot query action type %d (%s)\n",
query.count.hits,
query.count.bytes);
break;
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ rss_config_display(&query.rss_conf);
+ break;
default:
printf("Cannot display result for action type %d (%s)\n",
action->type, name);
printf("\n");
}
+static int
+get_fdir_info(portid_t port_id, struct rte_eth_fdir_info *fdir_info,
+ struct rte_eth_fdir_stats *fdir_stat)
+{
+ int ret;
+
+ ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
+ if (!ret) {
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, fdir_info);
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_STATS, fdir_stat);
+ return 0;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP) {
+ ret = rte_pmd_i40e_get_fdir_info(port_id, fdir_info);
+ if (!ret)
+ ret = rte_pmd_i40e_get_fdir_stats(port_id, fdir_stat);
+ }
+#endif
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP) {
+ ret = rte_pmd_ixgbe_get_fdir_info(port_id, fdir_info);
+ if (!ret)
+ ret = rte_pmd_ixgbe_get_fdir_stats(port_id, fdir_stat);
+ }
+#endif
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("\n FDIR is not supported on port %-2d\n",
+ port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ break;
+ }
+ return ret;
+}
+
void
fdir_get_infos(portid_t port_id)
{
struct rte_eth_fdir_stats fdir_stat;
struct rte_eth_fdir_info fdir_info;
- int ret;
static const char *fdir_stats_border = "########################";
if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
- if (ret < 0) {
- printf("\n FDIR is not supported on port %-2d\n",
- port_id);
- return;
- }
memset(&fdir_info, 0, sizeof(fdir_info));
- rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_INFO, &fdir_info);
memset(&fdir_stat, 0, sizeof(fdir_stat));
- rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_STATS, &fdir_stat);
+ if (get_fdir_info(port_id, &fdir_info, &fdir_stat))
+ return;
+
printf("\n %s FDIR infos for port %-2d %s\n",
fdir_stats_border, port_id, fdir_stats_border);
printf(" MODE: ");