[dpdk-dev] [PATCH] ixgbe: add counter to track sw tx packets

David Harton dharton at cisco.com
Tue Aug 29 17:50:56 CEST 2017


Add counter to track packets transmitted at the software layer
to help isolate output errors not reported otherwise.

Signed-off-by: David Harton <dharton at cisco.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 98 ++++++++++++++++++++++++++++++++++++----
 drivers/net/ixgbe/ixgbe_ethdev.h |  9 ++++
 drivers/net/ixgbe/ixgbe_rxtx.c   | 49 ++++++++++++++------
 3 files changed, 132 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ed21af5..a38a595 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -728,6 +728,14 @@ struct rte_ixgbe_xstats_name_off {
 #define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
 			   sizeof(rte_ixgbe_stats_strings[0]))
 
+/* SW statistics */
+static const struct rte_ixgbe_xstats_name_off rte_ixgbe_sw_strings[] = {
+	{"tx_pkts", offsetof(struct ixgbe_sw_stats, tx_pkts)},
+};
+
+#define IXGBE_NB_SW_STATS (sizeof(rte_ixgbe_sw_strings) / \
+			   sizeof(rte_ixgbe_sw_strings[0]))
+
 /* MACsec statistics */
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_macsec_strings[] = {
 	{"out_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
@@ -3085,6 +3093,8 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_hw_stats *hw_stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_sw_stats *sw_stats =
+			IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
 	struct ixgbe_macsec_stats *macsec_stats =
 			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
 				dev->data->dev_private);
@@ -3130,7 +3140,10 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 			  hw_stats->fclast;
 
 	/* Tx Errors */
-	stats->oerrors  = 0;
+	if (sw_stats->tx_pkts > stats->opackets)
+		stats->oerrors = sw_stats->tx_pkts - stats->opackets;
+	else
+		stats->oerrors = 0;
 }
 
 static void
@@ -3138,18 +3151,21 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
 {
 	struct ixgbe_hw_stats *stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_sw_stats *sw_stats =
+			IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
 
 	/* HW registers are cleared on read */
 	ixgbe_dev_stats_get(dev, NULL);
 
 	/* Reset software totals */
 	memset(stats, 0, sizeof(*stats));
+	memset(sw_stats, 0, sizeof(*sw_stats));
 }
 
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS + IXGBE_NB_MACSEC_STATS +
+	return IXGBE_NB_HW_STATS + IXGBE_NB_MACSEC_STATS + IXGBE_NB_SW_STATS +
 		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
 		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
 }
@@ -3176,6 +3192,15 @@ static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 			count++;
 		}
 
+		/* SW Stats */
+		for (i = 0; i < IXGBE_NB_SW_STATS; i++) {
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s",
+				rte_ixgbe_sw_strings[i].name);
+			count++;
+		}
+
 		/* MACsec Stats */
 		for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
 			snprintf(xstats_names[count].name,
@@ -3236,6 +3261,15 @@ static int ixgbe_dev_xstats_get_names_by_id(
 				count++;
 			}
 
+			/* SW Stats */
+			for (i = 0; i < IXGBE_NB_SW_STATS; i++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"%s",
+					rte_ixgbe_sw_strings[i].name);
+				count++;
+			}
+
 			/* MACsec Stats */
 			for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
 				snprintf(xstats_names[count].name,
@@ -3291,17 +3325,23 @@ static int ixgbe_dev_xstats_get_names_by_id(
 static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	struct rte_eth_xstat_name *xstats_names, unsigned limit)
 {
-	unsigned i;
+	unsigned int i, j;
 
-	if (limit < IXGBEVF_NB_XSTATS && xstats_names != NULL)
+	if (limit < (IXGBEVF_NB_XSTATS + IXGBE_NB_SW_STATS) &&
+		xstats_names != NULL)
 		return -ENOMEM;
 
-	if (xstats_names != NULL)
+	if (xstats_names != NULL) {
 		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
 			snprintf(xstats_names[i].name,
 				sizeof(xstats_names[i].name),
 				"%s", rte_ixgbevf_stats_strings[i].name);
-	return IXGBEVF_NB_XSTATS;
+		for (j = 0; j < IXGBE_NB_SW_STATS; j++, i++)
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name),
+				"%s", rte_ixgbe_sw_strings[j].name);
+	}
+	return (IXGBEVF_NB_XSTATS + IXGBE_NB_SW_STATS);
 }
 
 static int
@@ -3312,6 +3352,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_hw_stats *hw_stats =
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_sw_stats *sw_stats =
+			IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
 	struct ixgbe_macsec_stats *macsec_stats =
 			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
 				dev->data->dev_private);
@@ -3346,6 +3388,14 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		count++;
 	}
 
+	/* SW Stats */
+	for (i = 0; i < IXGBE_NB_SW_STATS; i++) {
+		xstats[count].value = *(uint64_t *)(((char *)sw_stats) +
+				rte_ixgbe_sw_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
 	/* MACsec Stats */
 	for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
 		xstats[count].value = *(uint64_t *)(((char *)macsec_stats) +
@@ -3388,6 +3438,9 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		struct ixgbe_hw_stats *hw_stats =
 				IXGBE_DEV_PRIVATE_TO_STATS(
 						dev->data->dev_private);
+		struct ixgbe_sw_stats *sw_stats =
+				IXGBE_DEV_PRIVATE_TO_SW_STATS(
+						dev->data->dev_private);
 		struct ixgbe_macsec_stats *macsec_stats =
 				IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
 					dev->data->dev_private);
@@ -3422,6 +3475,13 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 			count++;
 		}
 
+		/* SW Stats */
+		for (i = 0; i < IXGBE_NB_SW_STATS; i++) {
+			values[count] = *(uint64_t *)(((char *)sw_stats) +
+					rte_ixgbe_sw_strings[i].offset);
+			count++;
+		}
+
 		/* MACsec Stats */
 		for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
 			values[count] = *(uint64_t *)(((char *)macsec_stats) +
@@ -3522,10 +3582,12 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 {
 	struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-	unsigned i;
+	struct ixgbe_sw_stats *sw_stats = (struct ixgbe_sw_stats *)
+			IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
+	unsigned int i, j;
 
-	if (n < IXGBEVF_NB_XSTATS)
-		return IXGBEVF_NB_XSTATS;
+	if (n < (IXGBEVF_NB_XSTATS + IXGBE_NB_SW_STATS))
+		return (IXGBEVF_NB_XSTATS + IXGBE_NB_SW_STATS);
 
 	ixgbevf_update_stats(dev);
 
@@ -3538,8 +3600,13 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_ixgbevf_stats_strings[i].offset);
 	}
+	for (j = 0; j < IXGBE_NB_SW_STATS; j++, i++) {
+		xstats[i].id = i;
+		xstats[i].value = *(uint64_t *)(((char *)sw_stats) +
+			rte_ixgbe_sw_strings[j].offset);
+	}
 
-	return IXGBEVF_NB_XSTATS;
+	return (IXGBEVF_NB_XSTATS + IXGBE_NB_SW_STATS);
 }
 
 static void
@@ -3547,6 +3614,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 {
 	struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
 			  IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_sw_stats *sw_stats = (struct ixgbe_sw_stats *)
+			  IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
 
 	ixgbevf_update_stats(dev);
 
@@ -3557,6 +3626,11 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	stats->ibytes = hw_stats->vfgorc;
 	stats->opackets = hw_stats->vfgptc;
 	stats->obytes = hw_stats->vfgotc;
+
+	if (sw_stats->tx_pkts > stats->opackets)
+		stats->oerrors = sw_stats->tx_pkts - stats->opackets;
+	else
+		stats->oerrors = 0;
 }
 
 static void
@@ -3564,6 +3638,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 {
 	struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
 			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_sw_stats *sw_stats = (struct ixgbe_sw_stats *)
+			  IXGBE_DEV_PRIVATE_TO_SW_STATS(dev->data->dev_private);
 
 	/* Sync HW register to the last stats */
 	ixgbevf_dev_stats_get(dev, NULL);
@@ -3573,6 +3649,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	hw_stats->vfgorc = 0;
 	hw_stats->vfgptc = 0;
 	hw_stats->vfgotc = 0;
+
+	memset(sw_stats, 0, sizeof(*sw_stats));
 }
 
 static int
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 3f1aeb5..ba9350c 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -434,6 +434,11 @@ struct ixgbe_macsec_stats {
 	uint64_t in_pkts_notusingsa;
 };
 
+/* Struct to track emulated stats */
+struct ixgbe_sw_stats {
+	uint64_t tx_pkts;
+};
+
 /* The configuration of bandwidth */
 struct ixgbe_bw_conf {
 	uint8_t tc_num; /* Number of TCs. */
@@ -508,6 +513,7 @@ struct ixgbe_adapter {
 	struct ixgbe_hw             hw;
 	struct ixgbe_hw_stats       stats;
 	struct ixgbe_macsec_stats   macsec_stats;
+	struct ixgbe_sw_stats       sw_stats;
 	struct ixgbe_hw_fdir_info   fdir;
 	struct ixgbe_interrupt      intr;
 	struct ixgbe_stat_mapping_registers stat_mappings;
@@ -541,6 +547,9 @@ struct ixgbe_adapter {
 #define IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(adapter) \
 	(&((struct ixgbe_adapter *)adapter)->macsec_stats)
 
+#define IXGBE_DEV_PRIVATE_TO_SW_STATS(adapter) \
+	(&((struct ixgbe_adapter *)adapter)->sw_stats)
+
 #define IXGBE_DEV_PRIVATE_TO_INTR(adapter) \
 	(&((struct ixgbe_adapter *)adapter)->intr)
 
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 64bff25..34e3968 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -347,24 +347,35 @@ uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 		       uint16_t nb_pkts)
 {
 	uint16_t nb_tx;
+	struct ixgbe_tx_queue *txq = (struct ixgbe_tx_queue *)tx_queue;
+	struct ixgbe_sw_stats *sw_stats = (struct ixgbe_sw_stats *)
+		IXGBE_DEV_PRIVATE_TO_SW_STATS(
+			rte_eth_devices[txq->port_id].data->dev_private);
 
 	/* Try to transmit at least chunks of TX_MAX_BURST pkts */
-	if (likely(nb_pkts <= RTE_PMD_IXGBE_TX_MAX_BURST))
-		return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts);
-
-	/* transmit more than the max burst, in chunks of TX_MAX_BURST */
-	nb_tx = 0;
-	while (nb_pkts) {
-		uint16_t ret, n;
-
-		n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_IXGBE_TX_MAX_BURST);
-		ret = tx_xmit_pkts(tx_queue, &(tx_pkts[nb_tx]), n);
-		nb_tx = (uint16_t)(nb_tx + ret);
-		nb_pkts = (uint16_t)(nb_pkts - ret);
-		if (ret < n)
-			break;
+	if (likely(nb_pkts <= RTE_PMD_IXGBE_TX_MAX_BURST)) {
+		nb_tx = tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts);
+	} else {
+		/*
+		 * transmit more than the max burst,
+		 * in chunks of TX_MAX_BURST
+		 */
+		nb_tx = 0;
+		while (nb_pkts) {
+			uint16_t ret, n;
+
+			n = (uint16_t)RTE_MIN(
+					nb_pkts, RTE_PMD_IXGBE_TX_MAX_BURST);
+			ret = tx_xmit_pkts(tx_queue, &tx_pkts[nb_tx], n);
+			nb_tx = (uint16_t)(nb_tx + ret);
+			nb_pkts = (uint16_t)(nb_pkts - ret);
+			if (ret < n)
+				break;
+		}
 	}
 
+	sw_stats->tx_pkts += nb_tx;
+
 	return nb_tx;
 }
 
@@ -375,6 +386,9 @@ uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 {
 	uint16_t nb_tx = 0;
 	struct ixgbe_tx_queue *txq = (struct ixgbe_tx_queue *)tx_queue;
+	struct ixgbe_sw_stats *sw_stats = (struct ixgbe_sw_stats *)
+		IXGBE_DEV_PRIVATE_TO_SW_STATS(
+			rte_eth_devices[txq->port_id].data->dev_private);
 
 	while (nb_pkts) {
 		uint16_t ret, num;
@@ -388,6 +402,8 @@ uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 			break;
 	}
 
+	sw_stats->tx_pkts += nb_tx;
+
 	return nb_tx;
 }
 #endif
@@ -636,6 +652,7 @@ uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		uint16_t nb_pkts)
 {
+	struct ixgbe_sw_stats *sw_stats;
 	struct ixgbe_tx_queue *txq;
 	struct ixgbe_tx_entry *sw_ring;
 	struct ixgbe_tx_entry *txe, *txn;
@@ -942,6 +959,10 @@ uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 	IXGBE_PCI_REG_WRITE_RELAXED(txq->tdt_reg_addr, tx_id);
 	txq->tx_tail = tx_id;
 
+	sw_stats = (struct ixgbe_sw_stats *)IXGBE_DEV_PRIVATE_TO_SW_STATS(
+			rte_eth_devices[txq->port_id].data->dev_private);
+	sw_stats->tx_pkts += nb_tx;
+
 	return nb_tx;
 }
 
-- 
1.8.3.1



More information about the dev mailing list