From patchwork Tue Sep 22 09:19:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junyu Jiang X-Patchwork-Id: 78390 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 28906A04E1; Tue, 22 Sep 2020 11:48:35 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 694D01DB6A; Tue, 22 Sep 2020 11:41:47 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 745A51D660; Tue, 22 Sep 2020 11:41:45 +0200 (CEST) IronPort-SDR: T2erd2GRJ4kNyDwpLAeqTws0qxhdi/DucXilKw24Eqc/4foIgVhGV4xgDqqKEh13ERJMv2XLo5 4Xb3QNHm5q2A== X-IronPort-AV: E=McAfee;i="6000,8403,9751"; a="160640731" X-IronPort-AV: E=Sophos;i="5.77,290,1596524400"; d="scan'208";a="160640731" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2020 02:41:43 -0700 IronPort-SDR: fABRsyfGstsKJYh9JfzShuTUDxeTGh0Gpq3105fRBz339Kp5+QNmxQhAZGdV9teJoppNxe0V+d vlawDrwrIlOw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.77,290,1596524400"; d="scan'208";a="322160479" Received: from unknown (HELO intel.sh.intel.com) ([10.239.255.60]) by orsmga002.jf.intel.com with ESMTP; 22 Sep 2020 02:41:40 -0700 From: Junyu Jiang To: dev@dpdk.org Cc: Jeff Guo , Beilei Xing , Ferruh Yigit , Junyu Jiang , stable@dpdk.org Date: Tue, 22 Sep 2020 09:19:31 +0000 Message-Id: <20200922091931.3483-1-junyux.jiang@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200910015426.3140-1-junyux.jiang@intel.com> References: <20200910015426.3140-1-junyux.jiang@intel.com> Subject: [dpdk-dev] [PATCH v5] net/i40e: fix incorrect byte counters X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch fixed the issue that rx/tx bytes statistics counters overflowed on 48 bit limitation by enlarging the limitation. Fixes: 4861cde46116 ("i40e: new poll mode driver") Cc: stable@dpdk.org Signed-off-by: Junyu Jiang Reviewed-by: Ferruh Yigit --- V5: move this known issue next to related to the stats v4: put reading stats and extending in same function. v3: create a function to hide the extension inside it. v2: modify the error code --- --- doc/guides/nics/i40e.rst | 9 +++++ drivers/net/i40e/i40e_ethdev.c | 66 +++++++++++++++++++++------------- drivers/net/i40e/i40e_ethdev.h | 9 +++++ 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst index b7430f6c4..a0b81e669 100644 --- a/doc/guides/nics/i40e.rst +++ b/doc/guides/nics/i40e.rst @@ -670,6 +670,15 @@ When a packet is over maximum frame size, the packet is dropped. However, the Rx statistics, when calling `rte_eth_stats_get` incorrectly shows it as received. +RX/TX statistics may be incorrect when register overflowed +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The rx_bytes/tx_bytes statistics register is 48 bit length. +Although this limitation is enlarged to 64 bit length on the software side, +but there is no way to detect if the overflow occurred more than once. +So rx_bytes/tx_bytes statistics data is correct when statistics are +updated at least once between two overflows. + VF & TC max bandwidth setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 563f21d9d..6439baf2f 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -3052,6 +3052,21 @@ i40e_dev_link_update(struct rte_eth_dev *dev, return ret; } +static void +i40e_stat_update_48_in_64(struct i40e_hw *hw, uint32_t hireg, + uint32_t loreg, bool offset_loaded, uint64_t *offset, + uint64_t *stat, uint64_t *prev_stat) +{ + i40e_stat_update_48(hw, hireg, loreg, offset_loaded, offset, stat); + /* enlarge the limitation when statistics counters overflowed */ + if (offset_loaded) { + if (I40E_RXTX_BYTES_L_48_BIT(*prev_stat) > *stat) + *stat += (uint64_t)1 << I40E_48_BIT_WIDTH; + *stat += I40E_RXTX_BYTES_H_16_BIT(*prev_stat); + } + *prev_stat = *stat; +} + /* Get all the statistics of a VSI */ void i40e_update_vsi_stats(struct i40e_vsi *vsi) @@ -3061,9 +3076,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi) struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); int idx = rte_le_to_cpu_16(vsi->info.stat_counter_idx); - i40e_stat_update_48(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx), - vsi->offset_loaded, &oes->rx_bytes, - &nes->rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx), + vsi->offset_loaded, &oes->rx_bytes, + &nes->rx_bytes, &vsi->prev_rx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPRCH(idx), I40E_GLV_UPRCL(idx), vsi->offset_loaded, &oes->rx_unicast, &nes->rx_unicast); @@ -3084,9 +3099,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi) i40e_stat_update_32(hw, I40E_GLV_RUPP(idx), vsi->offset_loaded, &oes->rx_unknown_protocol, &nes->rx_unknown_protocol); - i40e_stat_update_48(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx), - vsi->offset_loaded, &oes->tx_bytes, - &nes->tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx), + vsi->offset_loaded, &oes->tx_bytes, + &nes->tx_bytes, &vsi->prev_tx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPTCH(idx), I40E_GLV_UPTCL(idx), vsi->offset_loaded, &oes->tx_unicast, &nes->tx_unicast); @@ -3128,17 +3143,18 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */ /* Get rx/tx bytes of internal transfer packets */ - i40e_stat_update_48(hw, I40E_GLV_GORCH(hw->port), - I40E_GLV_GORCL(hw->port), - pf->offset_loaded, - &pf->internal_stats_offset.rx_bytes, - &pf->internal_stats.rx_bytes); - - i40e_stat_update_48(hw, I40E_GLV_GOTCH(hw->port), - I40E_GLV_GOTCL(hw->port), - pf->offset_loaded, - &pf->internal_stats_offset.tx_bytes, - &pf->internal_stats.tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(hw->port), + I40E_GLV_GORCL(hw->port), + pf->offset_loaded, + &pf->internal_stats_offset.rx_bytes, + &pf->internal_stats.rx_bytes, + &pf->internal_prev_rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(hw->port), + I40E_GLV_GOTCL(hw->port), + pf->offset_loaded, + &pf->internal_stats_offset.tx_bytes, + &pf->internal_stats.tx_bytes, + &pf->internal_prev_tx_bytes); /* Get total internal rx packet count */ i40e_stat_update_48(hw, I40E_GLV_UPRCH(hw->port), I40E_GLV_UPRCL(hw->port), @@ -3178,10 +3194,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) pf->internal_stats.rx_broadcast) * RTE_ETHER_CRC_LEN; /* Get statistics of struct i40e_eth_stats */ - i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port), - I40E_GLPRT_GORCL(hw->port), - pf->offset_loaded, &os->eth.rx_bytes, - &ns->eth.rx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLPRT_GORCH(hw->port), + I40E_GLPRT_GORCL(hw->port), + pf->offset_loaded, &os->eth.rx_bytes, + &ns->eth.rx_bytes, &pf->prev_rx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPRCH(hw->port), I40E_GLPRT_UPRCL(hw->port), pf->offset_loaded, &os->eth.rx_unicast, @@ -3236,10 +3252,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw) pf->offset_loaded, &os->eth.rx_unknown_protocol, &ns->eth.rx_unknown_protocol); - i40e_stat_update_48(hw, I40E_GLPRT_GOTCH(hw->port), - I40E_GLPRT_GOTCL(hw->port), - pf->offset_loaded, &os->eth.tx_bytes, - &ns->eth.tx_bytes); + i40e_stat_update_48_in_64(hw, I40E_GLPRT_GOTCH(hw->port), + I40E_GLPRT_GOTCL(hw->port), + pf->offset_loaded, &os->eth.tx_bytes, + &ns->eth.tx_bytes, &pf->prev_tx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPTCH(hw->port), I40E_GLPRT_UPTCL(hw->port), pf->offset_loaded, &os->eth.tx_unicast, diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 19f821829..1466998aa 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -282,6 +282,9 @@ struct rte_flow { #define I40E_ETH_OVERHEAD \ (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + I40E_VLAN_TAG_SIZE * 2) +#define I40E_RXTX_BYTES_H_16_BIT(bytes) ((bytes) & ~I40E_48_BIT_MASK) +#define I40E_RXTX_BYTES_L_48_BIT(bytes) ((bytes) & I40E_48_BIT_MASK) + struct i40e_adapter; struct rte_pci_driver; @@ -399,6 +402,8 @@ struct i40e_vsi { uint8_t vlan_anti_spoof_on; /* The VLAN anti-spoofing enabled */ uint8_t vlan_filter_on; /* The VLAN filter enabled */ struct i40e_bw_info bw_info; /* VSI bandwidth information */ + uint64_t prev_rx_bytes; + uint64_t prev_tx_bytes; }; struct pool_entry { @@ -1156,6 +1161,10 @@ struct i40e_pf { uint16_t switch_domain_id; struct i40e_vf_msg_cfg vf_msg_cfg; + uint64_t prev_rx_bytes; + uint64_t prev_tx_bytes; + uint64_t internal_prev_rx_bytes; + uint64_t internal_prev_tx_bytes; }; enum pending_msg {