From: Ivan Ilchenko Date: Tue, 28 Sep 2021 11:29:11 +0000 (+0300) Subject: net/sfc: collect per queue stats in EF100 Rx X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=395ffcb431f48900cec4361d6f7ae22f9014642b;p=dpdk.git net/sfc: collect per queue stats in EF100 Rx If Rx datapath collects per queue statistics, use these stats to provide ipackets and ibytes in basic ethdev stats. Signed-off-by: Andrew Rybchenko Signed-off-by: Ivan Ilchenko --- diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index 30679014e3..30bd109e8b 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -236,6 +236,9 @@ struct sfc_sw_stats { unsigned int cache_count; uint64_t *reset_vals; + /* Location of per-queue reset values for packets/bytes in reset_vals */ + uint64_t *reset_rx_pkts; + uint64_t *reset_rx_bytes; rte_spinlock_t queues_bitmap_lock; void *queues_bitmap_mem; diff --git a/drivers/net/sfc/sfc_dp.h b/drivers/net/sfc/sfc_dp.h index 7fd8f34b0f..2edde61a68 100644 --- a/drivers/net/sfc/sfc_dp.h +++ b/drivers/net/sfc/sfc_dp.h @@ -16,6 +16,7 @@ #include #include "sfc_log.h" +#include "sfc_stats.h" #ifdef __cplusplus extern "C" { @@ -49,6 +50,7 @@ struct sfc_dp_queue { * put stats at top of the structure to be closer to fields * used on datapath or reap to have more chances to be cache-hot. */ + union sfc_pkts_bytes stats; uint32_t rx_dbells; uint32_t tx_dbells; diff --git a/drivers/net/sfc/sfc_dp_rx.h b/drivers/net/sfc/sfc_dp_rx.h index b6c44085ce..d037acaa56 100644 --- a/drivers/net/sfc/sfc_dp_rx.h +++ b/drivers/net/sfc/sfc_dp_rx.h @@ -216,6 +216,7 @@ struct sfc_dp_rx { #define SFC_DP_RX_FEAT_FLOW_FLAG 0x2 #define SFC_DP_RX_FEAT_FLOW_MARK 0x4 #define SFC_DP_RX_FEAT_INTR 0x8 +#define SFC_DP_RX_FEAT_STATS 0x10 /** * Rx offload capabilities supported by the datapath on device * level only if HW/FW supports it. diff --git a/drivers/net/sfc/sfc_ef100_rx.c b/drivers/net/sfc/sfc_ef100_rx.c index 1bf04f565a..391c52487d 100644 --- a/drivers/net/sfc/sfc_ef100_rx.c +++ b/drivers/net/sfc/sfc_ef100_rx.c @@ -525,10 +525,13 @@ sfc_ef100_rx_process_ready_pkts(struct sfc_ef100_rxq *rxq, lastseg = seg; } - if (likely(deliver)) + if (likely(deliver)) { *rx_pkts++ = pkt; - else + sfc_pkts_bytes_add(&rxq->dp.dpq.stats, 1, + rte_pktmbuf_pkt_len(pkt)); + } else { rte_pktmbuf_free(pkt); + } } return rx_pkts; @@ -914,7 +917,8 @@ struct sfc_dp_rx sfc_ef100_rx = { .hw_fw_caps = SFC_DP_HW_FW_CAP_EF100, }, .features = SFC_DP_RX_FEAT_MULTI_PROCESS | - SFC_DP_RX_FEAT_INTR, + SFC_DP_RX_FEAT_INTR | + SFC_DP_RX_FEAT_STATS, .dev_offload_capa = 0, .queue_offload_capa = DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index 7d1d7b1be4..14e8ed550b 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -586,6 +586,33 @@ sfc_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid) sfc_adapter_unlock(sa); } +static void +sfc_stats_get_dp_rx(struct sfc_adapter *sa, uint64_t *pkts, uint64_t *bytes) +{ + struct sfc_adapter_shared *sas = sfc_sa2shared(sa); + uint64_t pkts_sum = 0; + uint64_t bytes_sum = 0; + unsigned int i; + + for (i = 0; i < sas->ethdev_rxq_count; ++i) { + struct sfc_rxq_info *rxq_info; + + rxq_info = sfc_rxq_info_by_ethdev_qid(sas, i); + if (rxq_info->state & SFC_RXQ_INITIALIZED) { + union sfc_pkts_bytes qstats; + + sfc_pkts_bytes_get(&rxq_info->dp->dpq.stats, &qstats); + pkts_sum += qstats.pkts - + sa->sw_stats.reset_rx_pkts[i]; + bytes_sum += qstats.bytes - + sa->sw_stats.reset_rx_bytes[i]; + } + } + + *pkts = pkts_sum; + *bytes = bytes_sum; +} + /* * Some statistics are computed as A - B where A and B each increase * monotonically with some hardware counter(s) and the counters are read @@ -612,6 +639,8 @@ sfc_update_diff_stat(uint64_t *stat, uint64_t newval) static int sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { + const struct sfc_adapter_priv *sap = sfc_adapter_priv_by_eth_dev(dev); + bool have_dp_rx_stats = sap->dp_rx->features & SFC_DP_RX_FEAT_STATS; struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); struct sfc_port *port = &sa->port; uint64_t *mac_stats; @@ -619,6 +648,9 @@ sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) sfc_adapter_lock(sa); + if (have_dp_rx_stats) + sfc_stats_get_dp_rx(sa, &stats->ipackets, &stats->ibytes); + ret = sfc_port_update_mac_stats(sa, B_FALSE); if (ret != 0) goto unlock; @@ -627,18 +659,23 @@ sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, EFX_MAC_VADAPTER_RX_UNICAST_PACKETS)) { - stats->ipackets = - mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_PACKETS] + - mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_PACKETS] + - mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_PACKETS]; + if (!have_dp_rx_stats) { + stats->ipackets = + mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_PACKETS] + + mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_PACKETS] + + mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_PACKETS]; + stats->ibytes = + mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_BYTES] + + mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_BYTES] + + mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_BYTES]; + + /* CRC is included in these stats, but shouldn't be */ + stats->ibytes -= stats->ipackets * RTE_ETHER_CRC_LEN; + } stats->opackets = mac_stats[EFX_MAC_VADAPTER_TX_UNICAST_PACKETS] + mac_stats[EFX_MAC_VADAPTER_TX_MULTICAST_PACKETS] + mac_stats[EFX_MAC_VADAPTER_TX_BROADCAST_PACKETS]; - stats->ibytes = - mac_stats[EFX_MAC_VADAPTER_RX_UNICAST_BYTES] + - mac_stats[EFX_MAC_VADAPTER_RX_MULTICAST_BYTES] + - mac_stats[EFX_MAC_VADAPTER_RX_BROADCAST_BYTES]; stats->obytes = mac_stats[EFX_MAC_VADAPTER_TX_UNICAST_BYTES] + mac_stats[EFX_MAC_VADAPTER_TX_MULTICAST_BYTES] + @@ -647,15 +684,12 @@ sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) stats->oerrors = mac_stats[EFX_MAC_VADAPTER_TX_BAD_PACKETS]; /* CRC is included in these stats, but shouldn't be */ - stats->ibytes -= stats->ipackets * RTE_ETHER_CRC_LEN; stats->obytes -= stats->opackets * RTE_ETHER_CRC_LEN; } else { stats->opackets = mac_stats[EFX_MAC_TX_PKTS]; - stats->ibytes = mac_stats[EFX_MAC_RX_OCTETS]; stats->obytes = mac_stats[EFX_MAC_TX_OCTETS]; /* CRC is included in these stats, but shouldn't be */ - stats->ibytes -= mac_stats[EFX_MAC_RX_PKTS] * RTE_ETHER_CRC_LEN; stats->obytes -= mac_stats[EFX_MAC_TX_PKTS] * RTE_ETHER_CRC_LEN; /* @@ -681,12 +715,16 @@ sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) mac_stats[EFX_MAC_RX_JABBER_PKTS]; /* no oerrors counters supported on EF10 */ - /* Exclude missed, errors and pauses from Rx packets */ - sfc_update_diff_stat(&port->ipackets, - mac_stats[EFX_MAC_RX_PKTS] - - mac_stats[EFX_MAC_RX_PAUSE_PKTS] - - stats->imissed - stats->ierrors); - stats->ipackets = port->ipackets; + if (!have_dp_rx_stats) { + /* Exclude missed, errors and pauses from Rx packets */ + sfc_update_diff_stat(&port->ipackets, + mac_stats[EFX_MAC_RX_PKTS] - + mac_stats[EFX_MAC_RX_PAUSE_PKTS] - + stats->imissed - stats->ierrors); + stats->ipackets = port->ipackets; + stats->ibytes = mac_stats[EFX_MAC_RX_OCTETS] - + mac_stats[EFX_MAC_RX_PKTS] * RTE_ETHER_CRC_LEN; + } } unlock: diff --git a/drivers/net/sfc/sfc_sw_stats.c b/drivers/net/sfc/sfc_sw_stats.c index 81bd531a17..8ffa923215 100644 --- a/drivers/net/sfc/sfc_sw_stats.c +++ b/drivers/net/sfc/sfc_sw_stats.c @@ -12,13 +12,21 @@ #define SFC_SW_STAT_INVALID UINT64_MAX -#define SFC_SW_STATS_GROUP_SIZE_MAX 1U +#define SFC_SW_STATS_GROUP_SIZE_MAX 2U +#define SFC_SW_STAT_GOOD_PACKETS "packets" +#define SFC_SW_STAT_GOOD_BYTES "bytes" enum sfc_sw_stats_type { SFC_SW_STATS_RX, SFC_SW_STATS_TX, }; +enum sfc_sw_stats_group_basic { + SFC_SW_STATS_GROUP_BASIC_PKTS = 0, + SFC_SW_STATS_GROUP_BASIC_BYTES, + SFX_SW_STATS_GROUP_BASIC_MAX +}; + typedef void sfc_get_sw_stat_val_t(struct sfc_adapter *sa, uint16_t qid, uint64_t *values, unsigned int values_count); @@ -29,6 +37,29 @@ struct sfc_sw_stat_descr { bool provide_total; }; +static sfc_get_sw_stat_val_t sfc_sw_stat_get_rx_good_pkts_bytes; +static void +sfc_sw_stat_get_rx_good_pkts_bytes(struct sfc_adapter *sa, uint16_t qid, + uint64_t *values, + unsigned int values_count) +{ + struct sfc_adapter_shared *sas = sfc_sa2shared(sa); + struct sfc_rxq_info *rxq_info; + union sfc_pkts_bytes qstats; + + RTE_SET_USED(values_count); + SFC_ASSERT(values_count == SFX_SW_STATS_GROUP_BASIC_MAX); + rxq_info = sfc_rxq_info_by_ethdev_qid(sas, qid); + if (rxq_info->state & SFC_RXQ_INITIALIZED) { + sfc_pkts_bytes_get(&rxq_info->dp->dpq.stats, &qstats); + values[SFC_SW_STATS_GROUP_BASIC_PKTS] = qstats.pkts; + values[SFC_SW_STATS_GROUP_BASIC_BYTES] = qstats.bytes; + } else { + values[SFC_SW_STATS_GROUP_BASIC_PKTS] = 0; + values[SFC_SW_STATS_GROUP_BASIC_BYTES] = 0; + } +} + static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_rx_dbells; static void sfc_get_sw_stat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid, @@ -66,6 +97,20 @@ sfc_get_sw_stat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid, * The start of the group is denoted by stat implementing get value callback. */ const struct sfc_sw_stat_descr sfc_sw_stats_descr[] = { + /* Group of Rx packets/bytes stats */ + { + .name = SFC_SW_STAT_GOOD_PACKETS, + .type = SFC_SW_STATS_RX, + .get_val = sfc_sw_stat_get_rx_good_pkts_bytes, + .provide_total = false, + }, + { + .name = SFC_SW_STAT_GOOD_BYTES, + .type = SFC_SW_STATS_RX, + .get_val = NULL, + .provide_total = false, + }, + /* End of basic stats */ { .name = "dbells", .type = SFC_SW_STATS_RX, @@ -584,6 +629,66 @@ sfc_sw_xstats_reset(struct sfc_adapter *sa) } } +static bool +sfc_sw_stats_is_packets_or_bytes(const char *xstat_name) +{ + return strcmp(xstat_name, SFC_SW_STAT_GOOD_PACKETS) == 0 || + strcmp(xstat_name, SFC_SW_STAT_GOOD_BYTES) == 0; +} + +static void +sfc_sw_stats_fill_available_descr(struct sfc_adapter *sa) +{ + const struct sfc_adapter_priv *sap = &sa->priv; + bool have_dp_rx_stats = sap->dp_rx->features & SFC_DP_RX_FEAT_STATS; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; + const struct sfc_sw_stat_descr *sw_stat_descr; + unsigned int i; + + sw_stats->supp_count = 0; + for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) { + sw_stat_descr = &sfc_sw_stats_descr[i]; + if (!have_dp_rx_stats && + sw_stat_descr->type == SFC_SW_STATS_RX && + sfc_sw_stats_is_packets_or_bytes(sw_stat_descr->name)) + continue; + sw_stats->supp[sw_stats->supp_count].descr = sw_stat_descr; + sw_stats->supp_count++; + } +} + +static int +sfc_sw_stats_set_reset_basic_stats(struct sfc_adapter *sa) +{ + uint64_t *reset_vals = sa->sw_stats.reset_vals; + struct sfc_sw_stats *sw_stats = &sa->sw_stats; + const struct sfc_sw_stat_descr *sw_stat; + unsigned int i; + + for (i = 0; i < sw_stats->supp_count; i++) { + sw_stat = sw_stats->supp[i].descr; + + switch (sw_stat->type) { + case SFC_SW_STATS_RX: + if (strcmp(sw_stat->name, + SFC_SW_STAT_GOOD_PACKETS) == 0) + sa->sw_stats.reset_rx_pkts = reset_vals; + else if (strcmp(sw_stat->name, + SFC_SW_STAT_GOOD_BYTES) == 0) + sa->sw_stats.reset_rx_bytes = reset_vals; + break; + case SFC_SW_STATS_TX: + default: + SFC_GENERIC_LOG(ERR, "Unknown SW stat type"); + return -EINVAL; + } + + reset_vals += sfc_sw_xstat_get_nb_supported(sa, sw_stat); + } + + return 0; +} + int sfc_sw_xstats_configure(struct sfc_adapter *sa) { @@ -605,6 +710,7 @@ sfc_sw_xstats_configure(struct sfc_adapter *sa) } for (i = 0; i < sw_stats->supp_count; i++) sw_stats->supp[i].descr = &sfc_sw_stats_descr[i]; + sfc_sw_stats_fill_available_descr(sa); for (i = 0; i < sw_stats->supp_count; i++) { nb_supported += sfc_sw_xstat_get_nb_supported(sa, @@ -630,6 +736,9 @@ sfc_sw_xstats_configure(struct sfc_adapter *sa) } sa->sw_stats.cache_count = cache_count; stat_cache = *cache; + rc = sfc_sw_stats_set_reset_basic_stats(sa); + if (rc != 0) + goto fail_reset_basic_stats; for (i = 0; i < sw_stats->supp_count; i++) { sw_stats->supp[i].cache = stat_cache; @@ -639,6 +748,10 @@ sfc_sw_xstats_configure(struct sfc_adapter *sa) return 0; +fail_reset_basic_stats: + rte_free(*cache); + *cache = NULL; + sa->sw_stats.cache_count = 0; fail_cache: rte_free(*reset_vals); *reset_vals = NULL;