From 227c2d7305413396a67218226b590229b08bd9b9 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Mon, 22 Sep 2014 14:53:51 -0400 Subject: [PATCH 5/6] Convert ixl and ixlv drivers to use new ifcounter interface - Convert the ixl and ixlv drivers to use the new ifcounter interface when compiled for FreeBSD 11 or later. - Fix the drivers to report output queue discards - Remove redundant and racy increments of packet counters --- sys/dev/ixl/if_ixl.c | 40 ++++++++++++++++++++++++++-------------- sys/dev/ixl/if_ixlv.c | 4 ++++ sys/dev/ixl/ixl.h | 43 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/ixl/ixl_txrx.c | 44 ++++++++++++++++++++++++++++++++++++++++---- sys/dev/ixl/ixlvc.c | 37 ++++++++++++++++++++++++------------- 5 files changed, 137 insertions(+), 31 deletions(-) diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index abae7a5..6f52440 100755 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -2275,6 +2275,10 @@ ixl_setup_interface(device_t dev, struct ixl_vsi *vsi) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ixl_ioctl; +#if __FreeBSD_version >= 1100000 + if_setgetcounterfn(ifp, ixl_get_counter); +#endif + ifp->if_transmit = ixl_mq_start; ifp->if_qflush = ixl_qflush; @@ -4027,13 +4031,16 @@ void ixl_update_eth_stats(struct ixl_vsi *vsi) { struct ixl_pf *pf = (struct ixl_pf *)vsi->back; struct i40e_hw *hw = &pf->hw; - struct ifnet *ifp = vsi->ifp; struct i40e_eth_stats *es; struct i40e_eth_stats *oes; + int i; + uint64_t tx_discards; + struct i40e_hw_port_stats *nsd; u16 stat_idx = vsi->info.stat_counter_idx; es = &vsi->eth_stats; oes = &vsi->eth_stats_offsets; + nsd = &pf->stats; /* Gather up the stats that the hw collects */ ixl_stat_update32(hw, I40E_GLV_TEPC(stat_idx), @@ -4078,22 +4085,27 @@ void ixl_update_eth_stats(struct ixl_vsi *vsi) &oes->tx_broadcast, &es->tx_broadcast); vsi->stat_offsets_loaded = true; + tx_discards = es->tx_discards + nsd->tx_dropped_link_down; + for (i = 0; i < vsi->num_queues; i++) + tx_discards += vsi->queues[i].txr.br->br_drops; + /* Update ifnet stats */ - ifp->if_ipackets = es->rx_unicast + + IXL_SET_IPACKETS(vsi, es->rx_unicast + es->rx_multicast + - es->rx_broadcast; - ifp->if_opackets = es->tx_unicast + + es->rx_broadcast); + IXL_SET_OPACKETS(vsi, es->tx_unicast + es->tx_multicast + - es->tx_broadcast; - ifp->if_ibytes = es->rx_bytes; - ifp->if_obytes = es->tx_bytes; - ifp->if_imcasts = es->rx_multicast; - ifp->if_omcasts = es->tx_multicast; - - ifp->if_oerrors = es->tx_errors; - ifp->if_iqdrops = es->rx_discards; - ifp->if_noproto = es->rx_unknown_protocol; - ifp->if_collisions = 0; + es->tx_broadcast); + IXL_SET_IBYTES(vsi, es->rx_bytes); + IXL_SET_OBYTES(vsi, es->tx_bytes); + IXL_SET_IMCASTS(vsi, es->rx_multicast); + IXL_SET_OMCASTS(vsi, es->tx_multicast); + + IXL_SET_OERRORS(vsi, es->tx_errors); + IXL_SET_IQDROPS(vsi, es->rx_discards + nsd->eth.rx_discards); + IXL_SET_OQDROPS(vsi, tx_discards); + IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol); + IXL_SET_COLLISIONS(vsi, 0); } /** diff --git a/sys/dev/ixl/if_ixlv.c b/sys/dev/ixl/if_ixlv.c index 388c9e0..c0cdd8f 100644 --- a/sys/dev/ixl/if_ixlv.c +++ b/sys/dev/ixl/if_ixlv.c @@ -1363,6 +1363,10 @@ ixlv_setup_interface(device_t dev, struct ixlv_sc *sc) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ixlv_ioctl; +#if __FreeBSD_version >= 1100000 + if_setgetcounterfn(ifp, ixl_get_counter); +#endif + ifp->if_transmit = ixl_mq_start; ifp->if_qflush = ixl_qflush; diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h index 69be008..c240b02 100644 --- a/sys/dev/ixl/ixl.h +++ b/sys/dev/ixl/ixl.h @@ -264,6 +264,35 @@ #define IXL_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) #define IXL_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx) +#if __FreeBSD_version >= 1100000 +#define IXL_SET_IPACKETS(vsi, count) (vsi)->ipackets = (count) +#define IXL_SET_IERRORS(vsi, count) (vsi)->ierrors = (count) +#define IXL_SET_OPACKETS(vsi, count) (vsi)->opackets = (count) +#define IXL_SET_OERRORS(vsi, count) (vsi)->oerrors = (count) +#define IXL_SET_COLLISIONS(vsi, count) /* Do nothing; collisions is always 0. */ +#define IXL_SET_IBYTES(vsi, count) (vsi)->ibytes = (count) +#define IXL_SET_OBYTES(vsi, count) (vsi)->obytes = (count) +#define IXL_SET_IMCASTS(vsi, count) (vsi)->imcasts = (count) +#define IXL_SET_OMCASTS(vsi, count) (vsi)->omcasts = (count) +#define IXL_SET_IQDROPS(vsi, count) (vsi)->iqdrops = (count) +#define IXL_SET_OQDROPS(vsi, count) (vsi)->iqdrops = (count) +#define IXL_SET_NOPROTO(vsi, count) (vsi)->noproto = (count) +#else +#define IXL_SET_IPACKETS(vsi, count) (vsi)->ifp->if_ipackets = (count) +#define IXL_SET_IERRORS(vsi, count) (vsi)->ifp->if_ierrors = (count) +#define IXL_SET_OPACKETS(vsi, count) (vsi)->ifp->if_opackets = (count) +#define IXL_SET_OERRORS(vsi, count) (vsi)->ifp->if_oerrors = (count) +#define IXL_SET_COLLISIONS(vsi, count) (vsi)->ifp->if_collisions = (count) +#define IXL_SET_IBYTES(vsi, count) (vsi)->ifp->if_ibytes = (count) +#define IXL_SET_OBYTES(vsi, count) (vsi)->ifp->if_obytes = (count) +#define IXL_SET_IMCASTS(vsi, count) (vsi)->ifp->if_imcasts = (count) +#define IXL_SET_OMCASTS(vsi, count) (vsi)->ifp->if_omcasts = (count) +#define IXL_SET_IQDROPS(vsi, count) (vsi)->ifp->if_iqdrops = (count) +#define IXL_SET_OQDROPS(vsi, odrops) (vsi)->ifp->if_snd.ifq_drops = (odrops) +#define IXL_SET_NOPROTO(vsi, count) (vsi)->noproto = (count) +#endif + + /* ***************************************************************************** * vendor_info_array @@ -447,6 +476,17 @@ struct ixl_vsi { struct i40e_eth_stats eth_stats; struct i40e_eth_stats eth_stats_offsets; bool stat_offsets_loaded; + u64 ipackets; + u64 ierrors; + u64 opackets; + u64 oerrors; + u64 ibytes; + u64 obytes; + u64 imcasts; + u64 omcasts; + u64 iqdrops; + u64 oqdrops; + u64 noproto; /* Driver statistics */ u64 hw_filters_del; @@ -554,5 +594,8 @@ void ixl_free_que_rx(struct ixl_queue *); #ifdef IXL_FDIR void ixl_atr(struct ixl_queue *, struct tcphdr *, int); #endif +#if __FreeBSD_version >= 1100000 +uint64_t ixl_get_counter(if_t ifp, ift_counter cnt); +#endif #endif /* _IXL_H_ */ diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c index 306d4ec..1374d88 100755 --- a/sys/dev/ixl/ixl_txrx.c +++ b/sys/dev/ixl/ixl_txrx.c @@ -783,8 +783,6 @@ ixl_get_tx_head(struct ixl_queue *que) bool ixl_txeof(struct ixl_queue *que) { - struct ixl_vsi *vsi = que->vsi; - struct ifnet *ifp = vsi->ifp; struct tx_ring *txr = &que->txr; u32 first, last, head, done, processed; struct ixl_tx_buf *buf; @@ -857,7 +855,6 @@ ixl_txeof(struct ixl_queue *que) tx_desc = &txr->base[first]; } ++txr->packets; - ++ifp->if_opackets; /* See if there is more work now */ last = buf->eop_index; if (last != -1) { @@ -1529,7 +1526,6 @@ ixl_rxeof(struct ixl_queue *que, int count) if (eop) { sendmp->m_pkthdr.rcvif = ifp; /* gather stats */ - ifp->if_ipackets++; rxr->rx_packets++; rxr->rx_bytes += sendmp->m_pkthdr.len; /* capture data for dynamic ITR adjustment */ @@ -1625,3 +1621,43 @@ ixl_rx_checksum(struct mbuf * mp, u32 status, u32 error, u8 ptype) } return; } + +#if __FreeBSD_version >= 1100000 +uint64_t +ixl_get_counter(if_t ifp, ift_counter cnt) +{ + struct ixl_vsi *vsi; + + vsi = if_getsoftc(ifp); + + switch (cnt) { + case IFCOUNTER_IPACKETS: + return (vsi->ipackets); + case IFCOUNTER_IERRORS: + return (vsi->ierrors); + case IFCOUNTER_OPACKETS: + return (vsi->opackets); + case IFCOUNTER_OERRORS: + return (vsi->oerrors); + case IFCOUNTER_COLLISIONS: + /* Collisions are by standard impossible in 40G/10G Ethernet */ + return (0); + case IFCOUNTER_IBYTES: + return (vsi->ibytes); + case IFCOUNTER_OBYTES: + return (vsi->obytes); + case IFCOUNTER_IMCASTS: + return (vsi->imcasts); + case IFCOUNTER_OMCASTS: + return (vsi->omcasts); + case IFCOUNTER_IQDROPS: + return (vsi->iqdrops); + case IFCOUNTER_OQDROPS: + return (vsi->oqdrops); + case IFCOUNTER_NOPROTO: + return (vsi->noproto); + default: + return (if_get_counter_default(ifp, cnt)); + } +} +#endif diff --git a/sys/dev/ixl/ixlvc.c b/sys/dev/ixl/ixlvc.c index 87ebebe..938fa7a 100644 --- a/sys/dev/ixl/ixlvc.c +++ b/sys/dev/ixl/ixlvc.c @@ -773,22 +773,33 @@ ixlv_request_stats(struct ixlv_sc *sc) void ixlv_update_stats_counters(struct ixlv_sc *sc, struct i40e_eth_stats *es) { - struct ifnet *ifp = sc->vsi.ifp; + struct ixl_vsi *vsi; + uint64_t tx_discards; + int i; - ifp->if_ipackets = es->rx_unicast + + vsi = &sc->vsi; + + tx_discards = es->tx_discards; + for (i = 0; i < sc->vsi.num_queues; i++) + tx_discards += sc->vsi.queues[i].txr.br->br_drops; + + /* Update ifnet stats */ + IXL_SET_IPACKETS(vsi, es->rx_unicast + es->rx_multicast + - es->rx_broadcast; - ifp->if_opackets = es->tx_unicast + + es->rx_broadcast); + IXL_SET_OPACKETS(vsi, es->tx_unicast + es->tx_multicast + - es->tx_broadcast; - ifp->if_ibytes = es->rx_bytes; - ifp->if_obytes = es->tx_bytes; - ifp->if_imcasts = es->rx_multicast; - ifp->if_omcasts = es->tx_multicast; - - ifp->if_oerrors = es->tx_errors; - ifp->if_iqdrops = es->rx_discards; - ifp->if_noproto = es->rx_unknown_protocol; + es->tx_broadcast); + IXL_SET_IBYTES(vsi, es->rx_bytes); + IXL_SET_OBYTES(vsi, es->tx_bytes); + IXL_SET_IMCASTS(vsi, es->rx_multicast); + IXL_SET_OMCASTS(vsi, es->tx_multicast); + + IXL_SET_OERRORS(vsi, es->tx_errors); + IXL_SET_IQDROPS(vsi, es->rx_discards); + IXL_SET_OQDROPS(vsi, tx_discards); + IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol); + IXL_SET_COLLISIONS(vsi, 0); sc->vsi.eth_stats = *es; } -- 1.9.3