X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Fconfig.c;h=418ea6dda49901407aa503074ea6aa7f73753f42;hb=b415b7a06856b148ace29ffcc6e9740a12b9ec33;hp=035d336ab541ad7e0bfde665ec9a1472c5280fb5;hpb=0e459ffa08891a3ba238821a80499b9b17e2f2d3;p=dpdk.git diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 035d336ab5..418ea6dda4 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -49,11 +49,20 @@ #include #endif #include +#include #include "testpmd.h" #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 { @@ -77,7 +86,8 @@ 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 }, @@ -110,6 +120,12 @@ const struct rss_type_info rss_type_table[] = { { "tcp", ETH_RSS_TCP }, { "sctp", ETH_RSS_SCTP }, { "tunnel", ETH_RSS_TUNNEL }, + { "l3-pre32", RTE_ETH_RSS_L3_PRE32 }, + { "l3-pre40", RTE_ETH_RSS_L3_PRE40 }, + { "l3-pre48", RTE_ETH_RSS_L3_PRE48 }, + { "l3-pre56", RTE_ETH_RSS_L3_PRE56 }, + { "l3-pre64", RTE_ETH_RSS_L3_PRE64 }, + { "l3-pre96", RTE_ETH_RSS_L3_PRE96 }, { "l3-src-only", ETH_RSS_L3_SRC_ONLY }, { "l3-dst-only", ETH_RSS_L3_DST_ONLY }, { "l4-src-only", ETH_RSS_L4_SRC_ONLY }, @@ -118,6 +134,8 @@ const struct rss_type_info rss_type_table[] = { { "ah", ETH_RSS_AH }, { "l2tpv3", ETH_RSS_L2TPV3 }, { "pfcp", ETH_RSS_PFCP }, + { "pppoe", ETH_RSS_PPPOE }, + { "gtpu", ETH_RSS_GTPU }, { NULL, 0 }, }; @@ -136,9 +154,10 @@ nic_stats_display(portid_t port_id) 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]; @@ -195,10 +214,17 @@ nic_stats_display(portid_t 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; @@ -206,10 +232,10 @@ nic_stats_display(portid_t 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 ? - 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; @@ -217,10 +243,10 @@ nic_stats_display(portid_t port_id) (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" @@ -234,11 +260,28 @@ nic_stats_display(portid_t port_id) 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); } @@ -314,10 +357,21 @@ nic_xstats_clear(portid_t 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; } } @@ -399,6 +453,8 @@ rx_queue_infos_display(portid_t port_id, uint16_t queue_id) (qinfo.conf.rx_deferred_start != 0) ? "on" : "off"); printf("\nRX scattered packets: %s", (qinfo.scattered_rx != 0) ? "on" : "off"); + if (qinfo.rx_buf_size != 0) + printf("\nRX buffer size: %hu", qinfo.rx_buf_size); printf("\nNumber of RXDs: %hu", qinfo.nb_desc); if (rte_eth_rx_burst_mode_get(port_id, queue_id, &mode) == 0) @@ -577,7 +633,7 @@ port_infos_display(portid_t port_id) printf("\nmemory allocation on the socket: %u",port->socket_id); printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); - printf("Link speed: %u Mbps\n", (unsigned) link.link_speed); + printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed)); printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); @@ -722,12 +778,128 @@ port_summary_display(portid_t port_id) if (ret != 0) return; - printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %uMbps\n", + printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %s\n", port_id, mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], name, dev_info.driver_name, (link.link_status) ? ("up") : ("down"), - (unsigned int) link.link_speed); + rte_eth_link_speed_to_str(link.link_speed)); +} + +void +port_eeprom_display(portid_t port_id) +{ + struct rte_dev_eeprom_info einfo; + int ret; + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + print_valid_ports(); + return; + } + + int len_eeprom = rte_eth_dev_get_eeprom_length(port_id); + if (len_eeprom < 0) { + switch (len_eeprom) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get EEPROM: %d\n", len_eeprom); + break; + } + return; + } + + char buf[len_eeprom]; + einfo.offset = 0; + einfo.length = len_eeprom; + einfo.data = buf; + + ret = rte_eth_dev_get_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get EEPROM: %d\n", ret); + break; + } + return; + } + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + printf("Finish -- Port: %d EEPROM length: %d bytes\n", port_id, len_eeprom); +} + +void +port_module_eeprom_display(portid_t port_id) +{ + struct rte_eth_dev_module_info minfo; + struct rte_dev_eeprom_info einfo; + int ret; + + if (port_id_is_invalid(port_id, ENABLED_WARN)) { + print_valid_ports(); + return; + } + + + ret = rte_eth_dev_get_module_info(port_id, &minfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get module EEPROM: %d\n", ret); + break; + } + return; + } + + char buf[minfo.eeprom_len]; + einfo.offset = 0; + einfo.length = minfo.eeprom_len; + einfo.data = buf; + + ret = rte_eth_dev_get_module_eeprom(port_id, &einfo); + if (ret != 0) { + switch (ret) { + case -ENODEV: + printf("port index %d invalid\n", port_id); + break; + case -ENOTSUP: + printf("operation not supported by device\n"); + break; + case -EIO: + printf("device is removed\n"); + break; + default: + printf("Unable to get module EEPROM: %d\n", ret); + break; + } + return; + } + + rte_hexdump(stdout, "hexdump", einfo.data, einfo.length); + printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length); } void @@ -999,6 +1171,15 @@ port_offload_cap_display(portid_t port_id) printf("off\n"); } + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) { + printf("Tx scheduling on timestamp: "); + if (ports[port_id].dev_conf.txmode.offloads & + DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) + printf("on\n"); + else + printf("off\n"); + } + } int @@ -1253,8 +1434,9 @@ port_mtu_set(portid_t port_id, uint16_t mtu) 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 @@ -1269,10 +1451,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu) } 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. */ @@ -1350,6 +1529,57 @@ port_flow_complain(struct rte_flow_error *error) 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"); + for (i = 0; i < rss_conf->queue_num; i++) + printf(" %d", rss_conf->queue[i]); + printf("\n"); + + 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, @@ -1477,9 +1707,12 @@ int port_flow_flush(portid_t port_id) { struct rte_flow_error error; - struct rte_port *port; + struct rte_port *port = &ports[port_id]; int ret = 0; + if (port->flow_list == NULL) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ memset(&error, 0x44, sizeof(error)); if (rte_flow_flush(port_id, &error)) { @@ -1488,7 +1721,7 @@ port_flow_flush(portid_t port_id) port_id == (portid_t)RTE_PORT_ALL) return ret; } - port = &ports[port_id]; + while (port->flow_list) { struct port_flow *pf = port->flow_list->next; @@ -1536,6 +1769,7 @@ port_flow_query(portid_t port_id, uint32_t rule, const char *name; union { struct rte_flow_query_count count; + struct rte_flow_action_rss rss_conf; } query; int ret; @@ -1557,6 +1791,7 @@ port_flow_query(portid_t port_id, uint32_t rule, 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", @@ -1581,6 +1816,9 @@ port_flow_query(portid_t port_id, uint32_t rule, 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); @@ -1775,22 +2013,102 @@ tx_queue_id_is_invalid(queueid_t txq_id) } static int -rx_desc_id_is_invalid(uint16_t rxdesc_id) +get_rx_ring_size(portid_t port_id, queueid_t rxq_id, uint16_t *ring_size) +{ + struct rte_port *port = &ports[port_id]; + struct rte_eth_rxq_info rx_qinfo; + int ret; + + ret = rte_eth_rx_queue_info_get(port_id, rxq_id, &rx_qinfo); + if (ret == 0) { + *ring_size = rx_qinfo.nb_desc; + return ret; + } + + if (ret != -ENOTSUP) + return ret; + /* + * If the rte_eth_rx_queue_info_get is not support for this PMD, + * ring_size stored in testpmd will be used for validity verification. + * When configure the rxq by rte_eth_rx_queue_setup with nb_rx_desc + * being 0, it will use a default value provided by PMDs to setup this + * rxq. If the default value is 0, it will use the + * RTE_ETH_DEV_FALLBACK_RX_RINGSIZE to setup this rxq. + */ + if (port->nb_rx_desc[rxq_id]) + *ring_size = port->nb_rx_desc[rxq_id]; + else if (port->dev_info.default_rxportconf.ring_size) + *ring_size = port->dev_info.default_rxportconf.ring_size; + else + *ring_size = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE; + return 0; +} + +static int +get_tx_ring_size(portid_t port_id, queueid_t txq_id, uint16_t *ring_size) +{ + struct rte_port *port = &ports[port_id]; + struct rte_eth_txq_info tx_qinfo; + int ret; + + ret = rte_eth_tx_queue_info_get(port_id, txq_id, &tx_qinfo); + if (ret == 0) { + *ring_size = tx_qinfo.nb_desc; + return ret; + } + + if (ret != -ENOTSUP) + return ret; + /* + * If the rte_eth_tx_queue_info_get is not support for this PMD, + * ring_size stored in testpmd will be used for validity verification. + * When configure the txq by rte_eth_tx_queue_setup with nb_tx_desc + * being 0, it will use a default value provided by PMDs to setup this + * txq. If the default value is 0, it will use the + * RTE_ETH_DEV_FALLBACK_TX_RINGSIZE to setup this txq. + */ + if (port->nb_tx_desc[txq_id]) + *ring_size = port->nb_tx_desc[txq_id]; + else if (port->dev_info.default_txportconf.ring_size) + *ring_size = port->dev_info.default_txportconf.ring_size; + else + *ring_size = RTE_ETH_DEV_FALLBACK_TX_RINGSIZE; + return 0; +} + +static int +rx_desc_id_is_invalid(portid_t port_id, queueid_t rxq_id, uint16_t rxdesc_id) { - if (rxdesc_id < nb_rxd) + uint16_t ring_size; + int ret; + + ret = get_rx_ring_size(port_id, rxq_id, &ring_size); + if (ret) + return 1; + + if (rxdesc_id < ring_size) return 0; - printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n", - rxdesc_id, nb_rxd); + + printf("Invalid RX descriptor %u (must be < ring_size=%u)\n", + rxdesc_id, ring_size); return 1; } static int -tx_desc_id_is_invalid(uint16_t txdesc_id) +tx_desc_id_is_invalid(portid_t port_id, queueid_t txq_id, uint16_t txdesc_id) { - if (txdesc_id < nb_txd) + uint16_t ring_size; + int ret; + + ret = get_tx_ring_size(port_id, txq_id, &ring_size); + if (ret) + return 1; + + if (txdesc_id < ring_size) return 0; - printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n", - txdesc_id, nb_txd); + + printf("Invalid TX descriptor %u (must be < ring_size=%u)\n", + txdesc_id, ring_size); return 1; } @@ -1911,11 +2229,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) { const struct rte_memzone *rx_mz; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; - if (rx_queue_id_is_invalid(rxq_id)) - return; - if (rx_desc_id_is_invalid(rxd_id)) + if (rx_desc_id_is_invalid(port_id, rxq_id, rxd_id)) return; rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); if (rx_mz == NULL) @@ -1928,11 +2242,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) { const struct rte_memzone *tx_mz; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; - if (tx_queue_id_is_invalid(txq_id)) - return; - if (tx_desc_id_is_invalid(txd_id)) + if (tx_desc_id_is_invalid(port_id, txq_id, txd_id)) return; tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); if (tx_mz == NULL) @@ -1973,10 +2283,17 @@ rxtx_config_display(void) struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0]; uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0]; uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0]; - uint16_t nb_rx_desc_tmp; - uint16_t nb_tx_desc_tmp; struct rte_eth_rxq_info rx_qinfo; struct rte_eth_txq_info tx_qinfo; + uint16_t rx_free_thresh_tmp; + uint16_t tx_free_thresh_tmp; + uint16_t tx_rs_thresh_tmp; + uint16_t nb_rx_desc_tmp; + uint16_t nb_tx_desc_tmp; + uint64_t offloads_tmp; + uint8_t pthresh_tmp; + uint8_t hthresh_tmp; + uint8_t wthresh_tmp; int32_t rc; /* per port config */ @@ -1990,41 +2307,64 @@ rxtx_config_display(void) /* per rx queue config only for first queue to be less verbose */ for (qid = 0; qid < 1; qid++) { rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo); - if (rc) + if (rc) { nb_rx_desc_tmp = nb_rx_desc[qid]; - else + rx_free_thresh_tmp = + rx_conf[qid].rx_free_thresh; + pthresh_tmp = rx_conf[qid].rx_thresh.pthresh; + hthresh_tmp = rx_conf[qid].rx_thresh.hthresh; + wthresh_tmp = rx_conf[qid].rx_thresh.wthresh; + offloads_tmp = rx_conf[qid].offloads; + } else { nb_rx_desc_tmp = rx_qinfo.nb_desc; + rx_free_thresh_tmp = + rx_qinfo.conf.rx_free_thresh; + pthresh_tmp = rx_qinfo.conf.rx_thresh.pthresh; + hthresh_tmp = rx_qinfo.conf.rx_thresh.hthresh; + wthresh_tmp = rx_qinfo.conf.rx_thresh.wthresh; + offloads_tmp = rx_qinfo.conf.offloads; + } printf(" RX queue: %d\n", qid); printf(" RX desc=%d - RX free threshold=%d\n", - nb_rx_desc_tmp, rx_conf[qid].rx_free_thresh); + nb_rx_desc_tmp, rx_free_thresh_tmp); printf(" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n", - rx_conf[qid].rx_thresh.pthresh, - rx_conf[qid].rx_thresh.hthresh, - rx_conf[qid].rx_thresh.wthresh); - printf(" RX Offloads=0x%"PRIx64"\n", - rx_conf[qid].offloads); + pthresh_tmp, hthresh_tmp, wthresh_tmp); + printf(" RX Offloads=0x%"PRIx64"\n", offloads_tmp); } /* per tx queue config only for first queue to be less verbose */ for (qid = 0; qid < 1; qid++) { rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo); - if (rc) + if (rc) { nb_tx_desc_tmp = nb_tx_desc[qid]; - else + tx_free_thresh_tmp = + tx_conf[qid].tx_free_thresh; + pthresh_tmp = tx_conf[qid].tx_thresh.pthresh; + hthresh_tmp = tx_conf[qid].tx_thresh.hthresh; + wthresh_tmp = tx_conf[qid].tx_thresh.wthresh; + offloads_tmp = tx_conf[qid].offloads; + tx_rs_thresh_tmp = tx_conf[qid].tx_rs_thresh; + } else { nb_tx_desc_tmp = tx_qinfo.nb_desc; + tx_free_thresh_tmp = + tx_qinfo.conf.tx_free_thresh; + pthresh_tmp = tx_qinfo.conf.tx_thresh.pthresh; + hthresh_tmp = tx_qinfo.conf.tx_thresh.hthresh; + wthresh_tmp = tx_qinfo.conf.tx_thresh.wthresh; + offloads_tmp = tx_qinfo.conf.offloads; + tx_rs_thresh_tmp = tx_qinfo.conf.tx_rs_thresh; + } printf(" TX queue: %d\n", qid); printf(" TX desc=%d - TX free threshold=%d\n", - nb_tx_desc_tmp, tx_conf[qid].tx_free_thresh); + nb_tx_desc_tmp, tx_free_thresh_tmp); printf(" TX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n", - tx_conf[qid].tx_thresh.pthresh, - tx_conf[qid].tx_thresh.hthresh, - tx_conf[qid].tx_thresh.wthresh); + pthresh_tmp, hthresh_tmp, wthresh_tmp); printf(" TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n", - tx_conf[qid].offloads, tx_conf->tx_rs_thresh); + offloads_tmp, tx_rs_thresh_tmp); } } } @@ -2459,55 +2799,6 @@ icmp_echo_config_setup(void) } } -#if defined RTE_LIBRTE_PMD_SOFTNIC -static void -softnic_fwd_config_setup(void) -{ - struct rte_port *port; - portid_t pid, softnic_portid; - queueid_t i; - uint8_t softnic_enable = 0; - - RTE_ETH_FOREACH_DEV(pid) { - port = &ports[pid]; - const char *driver = port->dev_info.driver_name; - - if (strcmp(driver, "net_softnic") == 0) { - softnic_portid = pid; - softnic_enable = 1; - break; - } - } - - if (softnic_enable == 0) { - printf("Softnic mode not configured(%s)!\n", __func__); - return; - } - - cur_fwd_config.nb_fwd_ports = 1; - cur_fwd_config.nb_fwd_streams = (streamid_t) nb_rxq; - - /* Re-initialize forwarding streams */ - init_fwd_streams(); - - /* - * In the softnic forwarding test, the number of forwarding cores - * is set to one and remaining are used for softnic packet processing. - */ - cur_fwd_config.nb_fwd_lcores = 1; - setup_fwd_config_of_each_lcore(&cur_fwd_config); - - for (i = 0; i < cur_fwd_config.nb_fwd_streams; i++) { - fwd_streams[i]->rx_port = softnic_portid; - fwd_streams[i]->rx_queue = i; - fwd_streams[i]->tx_port = softnic_portid; - fwd_streams[i]->tx_queue = i; - fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port; - fwd_streams[i]->retry_enabled = retry_enabled; - } -} -#endif - void fwd_config_setup(void) { @@ -2517,13 +2808,6 @@ fwd_config_setup(void) return; } -#if defined RTE_LIBRTE_PMD_SOFTNIC - if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) { - softnic_fwd_config_setup(); - return; - } -#endif - if ((nb_rxq > 1) && (nb_txq > 1)){ if (dcb_config) dcb_fwd_config_setup(); @@ -2924,17 +3208,41 @@ show_tx_pkt_segments(void) printf("Split packet: %s\n", split); } +static bool +nb_segs_is_invalid(unsigned int nb_segs) +{ + uint16_t ring_size; + uint16_t queue_id; + uint16_t port_id; + int ret; + + RTE_ETH_FOREACH_DEV(port_id) { + for (queue_id = 0; queue_id < nb_txq; queue_id++) { + ret = get_tx_ring_size(port_id, queue_id, &ring_size); + + if (ret) + return true; + + if (ring_size < nb_segs) { + printf("nb segments per TX packets=%u >= " + "TX queue(%u) ring_size=%u - ignored\n", + nb_segs, queue_id, ring_size); + return true; + } + } + } + + return false; +} + void set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) { uint16_t tx_pkt_len; unsigned i; - if (nb_segs >= (unsigned) nb_txd) { - printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n", - nb_segs, (unsigned int) nb_txd); + if (nb_segs_is_invalid(nb_segs)) return; - } /* * Check that each segment length is greater or equal than @@ -2966,6 +3274,58 @@ set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) tx_pkt_nb_segs = (uint8_t) nb_segs; } +void +show_tx_pkt_times(void) +{ + printf("Interburst gap: %u\n", tx_pkt_times_inter); + printf("Intraburst gap: %u\n", tx_pkt_times_intra); +} + +void +set_tx_pkt_times(unsigned int *tx_times) +{ + uint16_t port_id; + int offload_found = 0; + int offset; + int flag; + + static const struct rte_mbuf_dynfield desc_offs = { + .name = RTE_MBUF_DYNFIELD_TIMESTAMP_NAME, + .size = sizeof(uint64_t), + .align = __alignof__(uint64_t), + }; + static const struct rte_mbuf_dynflag desc_flag = { + .name = RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME, + }; + + RTE_ETH_FOREACH_DEV(port_id) { + struct rte_eth_dev_info dev_info = { 0 }; + int ret; + + ret = rte_eth_dev_info_get(port_id, &dev_info); + if (ret == 0 && dev_info.tx_offload_capa & + DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) { + offload_found = 1; + break; + } + } + if (!offload_found) { + printf("No device supporting Tx timestamp scheduling found, " + "dynamic flag and field not registered\n"); + return; + } + offset = rte_mbuf_dynfield_register(&desc_offs); + if (offset < 0 && rte_errno != EEXIST) + printf("Dynamic timestamp field registration error: %d", + rte_errno); + flag = rte_mbuf_dynflag_register(&desc_flag); + if (flag < 0 && rte_errno != EEXIST) + printf("Dynamic timestamp flag registration error: %d", + rte_errno); + tx_pkt_times_inter = tx_times[0]; + tx_pkt_times_intra = tx_times[1]; +} + void setup_gro(const char *onoff, portid_t port_id) { @@ -3278,9 +3638,11 @@ vlan_extend_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3305,9 +3667,11 @@ rx_vlan_strip_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3346,9 +3710,11 @@ rx_vlan_filter_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3373,9 +3739,11 @@ rx_vlan_qinq_strip_set(portid_t port_id, int on) } diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); - if (diag < 0) + if (diag < 0) { printf("%s(port_pi=%d, on=%d) failed " "diag=%d\n", __func__, port_id, on, diag); + return; + } ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads; } @@ -3433,8 +3801,6 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id) struct rte_eth_dev_info dev_info; int ret; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; if (vlan_id_is_invalid(vlan_id)) return; @@ -3465,8 +3831,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) struct rte_eth_dev_info dev_info; int ret; - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; if (vlan_id_is_invalid(vlan_id)) return; if (vlan_id_is_invalid(vlan_id_outer)) @@ -3492,8 +3856,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) void tx_vlan_reset(portid_t port_id) { - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return; ports[port_id].dev_conf.txmode.offloads &= ~(DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT); @@ -3568,6 +3930,18 @@ set_xstats_hide_zero(uint8_t on_off) xstats_hide_zero = on_off; } +void +set_record_core_cycles(uint8_t on_off) +{ + record_core_cycles = on_off; +} + +void +set_record_burst_stats(uint8_t on_off) +{ + record_burst_stats = on_off; +} + static inline void print_fdir_mask(struct rte_eth_fdir_masks *mask) { @@ -3701,30 +4075,65 @@ print_fdir_flow_type(uint32_t flow_types_mask) 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: "); @@ -3873,7 +4282,8 @@ set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) ret = eth_link_get_nowait_print_err(port_id, &link); if (ret < 0) return 1; - if (rate > link.link_speed) { + if (link.link_speed != ETH_SPEED_NUM_UNKNOWN && + rate > link.link_speed) { printf("Invalid rate value:%u bigger than link speed: %u\n", rate, link.link_speed); return 1;