diff -ur dpdk-16.04.orig/drivers/net/enic/enic.h dpdk-16.04/drivers/net/enic/enic.h --- dpdk-16.04.orig/drivers/net/enic/enic.h 2016-05-26 16:59:16.531326660 -0700 +++ dpdk-16.04/drivers/net/enic/enic.h 2016-05-26 16:59:52.689262489 -0700 @@ -91,6 +91,11 @@ struct enic_fdir_node *nodes[ENICPMD_FDIR_MAX]; }; +struct enic_soft_stats { + rte_atomic64_t rx_nombuf; + rte_atomic64_t rx_packet_errors; +}; + /* Per-instance private data structure */ struct enic { struct enic *next; @@ -133,6 +138,8 @@ /* interrupt resource */ struct vnic_intr intr; unsigned int intr_count; + + struct enic_soft_stats soft_stats; }; static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq) diff -ur dpdk-16.04.orig/drivers/net/enic/enic_main.c dpdk-16.04/drivers/net/enic/enic_main.c --- dpdk-16.04.orig/drivers/net/enic/enic_main.c 2016-05-26 16:59:16.533326822 -0700 +++ dpdk-16.04/drivers/net/enic/enic_main.c 2016-05-26 17:08:11.768801926 -0700 @@ -142,22 +142,51 @@ } +static void enic_clear_soft_stats(struct enic *enic) +{ + struct enic_soft_stats *soft_stats = &enic->soft_stats; + rte_atomic64_clear(&soft_stats->rx_nombuf); + rte_atomic64_clear(&soft_stats->rx_packet_errors); +} + +static void enic_init_soft_stats(struct enic *enic) +{ + struct enic_soft_stats *soft_stats = &enic->soft_stats; + rte_atomic64_init(&soft_stats->rx_nombuf); + rte_atomic64_init(&soft_stats->rx_packet_errors); + enic_clear_soft_stats(enic); +} + void enic_dev_stats_clear(struct enic *enic) { if (vnic_dev_stats_clear(enic->vdev)) dev_err(enic, "Error in clearing stats\n"); + enic_clear_soft_stats(enic); } void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats) { struct vnic_stats *stats; + struct enic_soft_stats *soft_stats = &enic->soft_stats; + int64_t rx_truncated; + uint64_t rx_packet_errors; if (vnic_dev_stats_dump(enic->vdev, &stats)) { dev_err(enic, "Error in getting stats\n"); return; } - r_stats->ipackets = stats->rx.rx_frames_ok; + /* The number of truncated packets can only be calculated by + * subtracting a hardware counter from error packets received by + * the driver. Note: this causes transient inaccuracies in the + * ipackets count. Also, the length of truncated packets are + * counted in ibytes even though truncated packets are dropped + * which can make ibytes be slightly higher than it should be. + */ + rx_packet_errors = rte_atomic64_read(&soft_stats->rx_packet_errors); + rx_truncated = rx_packet_errors - stats->rx.rx_errors; + + r_stats->ipackets = stats->rx.rx_frames_ok - rx_truncated; r_stats->opackets = stats->tx.tx_frames_ok; r_stats->ibytes = stats->rx.rx_bytes_ok; @@ -166,10 +195,9 @@ r_stats->ierrors = stats->rx.rx_errors + stats->rx.rx_drop; r_stats->oerrors = stats->tx.tx_errors; - r_stats->imissed = stats->rx.rx_no_bufs; + r_stats->imissed = stats->rx.rx_no_bufs + rx_truncated; - r_stats->imcasts = stats->rx.rx_multicast_frames_ok; - r_stats->rx_nombuf = stats->rx.rx_no_bufs; + r_stats->rx_nombuf = rte_atomic64_read(&soft_stats->rx_nombuf); } void enic_del_mac_address(struct enic *enic) @@ -755,6 +783,8 @@ { int ret; + enic_init_soft_stats(enic); + ret = enic_set_rss_nic_cfg(enic); if (ret) { dev_err(enic, "Failed to config nic, aborting.\n"); diff -ur dpdk-16.04.orig/drivers/net/enic/enic_rxtx.c dpdk-16.04/drivers/net/enic/enic_rxtx.c --- dpdk-16.04.orig/drivers/net/enic/enic_rxtx.c 2016-05-26 16:59:16.522325929 -0700 +++ dpdk-16.04/drivers/net/enic/enic_rxtx.c 2016-05-26 16:59:52.694262896 -0700 @@ -251,6 +251,7 @@ struct vnic_cq *cq; volatile struct cq_desc *cqd_ptr; uint8_t color; + uint16_t nb_err = 0; cq = &enic->cq[enic_cq_rq(enic, rq->index)]; rx_id = cq->to_clean; /* index of cqd, rqd, mbuf_table */ @@ -278,10 +279,7 @@ /* allocate a new mbuf */ nmb = rte_rxmbuf_alloc(rq->mp); if (nmb == NULL) { - dev_err(enic, "RX mbuf alloc failed port=%u qid=%u", - enic->port_id, (unsigned)rq->index); - rte_eth_devices[enic->port_id]. - data->rx_mbuf_alloc_failed++; + rte_atomic64_inc(&enic->soft_stats.rx_nombuf); break; } @@ -323,9 +321,10 @@ rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd); enic_cq_rx_to_pkt_flags(&cqd, rxmb); } else { - rxmb->pkt_len = 0; - rxmb->packet_type = 0; - rxmb->ol_flags = 0; + rte_pktmbuf_free(rxmb); + rte_atomic64_inc(&enic->soft_stats.rx_packet_errors); + nb_err++; + continue; } rxmb->data_len = rxmb->pkt_len; @@ -337,7 +336,7 @@ rx_pkts[nb_rx++] = rxmb; } - nb_hold += nb_rx; + nb_hold += nb_rx + nb_err; cq->to_clean = rx_id; if (nb_hold > rq->rx_free_thresh) {