socsvn commit: r306424 - soc2016/vincenzo/head/sys/dev/netmap

vincenzo at FreeBSD.org vincenzo at FreeBSD.org
Mon Jul 18 09:09:58 UTC 2016


Author: vincenzo
Date: Mon Jul 18 09:09:57 2016
New Revision: 306424
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=306424

Log:
   freebsd: ptnet: collect interface statistics

Modified:
  soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c

Modified: soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c
==============================================================================
--- soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c	Mon Jul 18 09:09:48 2016	(r306423)
+++ soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c	Mon Jul 18 09:09:57 2016	(r306424)
@@ -103,18 +103,27 @@
 
 struct ptnet_softc;
 
+struct ptnet_queue_stats {
+	uint64_t	packets; /* if_[io]packets */
+	uint64_t	bytes;	 /* if_[io]bytes */
+	uint64_t	errors;	 /* if_[io]errors */
+	uint64_t	iqdrops; /* if_iqdrops */
+	uint64_t	mcasts;  /* if_[io]mcasts */
+};
+
 struct ptnet_queue {
-	struct ptnet_softc	*sc;
-	struct			resource *irq;
-	void			*cookie;
-	int			kring_id;
-	struct ptnet_ring	*ptring;
-	unsigned int		kick;
-	struct mtx		lock;
-	struct buf_ring		*bufring; /* for TX queues */
-	struct taskqueue	*taskq;
-	struct task		task;
-	char			lock_name[16];
+	struct ptnet_softc		*sc;
+	struct				resource *irq;
+	void				*cookie;
+	int				kring_id;
+	struct ptnet_ring		*ptring;
+	unsigned int			kick;
+	struct mtx			lock;
+	struct buf_ring			*bufring; /* for TX queues */
+	struct ptnet_queue_stats	stats;
+	struct taskqueue		*taskq;
+	struct task			task;
+	char				lock_name[16];
 };
 
 #define PTNET_Q_LOCK(_pq)	mtx_lock(&(_pq)->lock)
@@ -988,8 +997,33 @@
 {
 	struct ptnet_softc *sc = opaque;
 	struct ifnet *ifp = sc->ifp;
+	struct ptnet_queue_stats stats[2];
+	int i;
+
+	/* Accumulate statistics over the queues. */
+	memset(stats, 0, sizeof(stats));
+	for (i = 0; i < sc->num_rings; i++) {
+		struct ptnet_queue *pq = sc->queues + i;
+		int idx = (i < sc->num_tx_rings) ? 0 : 1;
+
+		stats[idx].packets	+= pq->stats.packets;
+		stats[idx].bytes	+= pq->stats.bytes;
+		stats[idx].errors	+= pq->stats.errors;
+		stats[idx].iqdrops	+= pq->stats.iqdrops;
+		stats[idx].mcasts	+= pq->stats.mcasts;
+	}
+
+	/* Update interface statistics. */
+	ifp->if_opackets	= stats[0].packets;
+	ifp->if_obytes		= stats[0].bytes;
+	ifp->if_omcasts		= stats[0].mcasts;
+	ifp->if_oerrors		= stats[0].errors;
+	ifp->if_ipackets	= stats[1].packets;
+	ifp->if_ibytes		= stats[1].bytes;
+	ifp->if_imcasts		= stats[1].mcasts;
+	ifp->if_ierrors		= stats[1].errors;
+	ifp->if_iqdrops		= stats[1].iqdrops;
 
-	(void)ifp;
 	callout_schedule(&sc->tick, hz);
 }
 
@@ -1759,6 +1793,7 @@
 					 * occurred while preparing the vnet
 					 * header. Let's go ahead with the next
 					 * packet. */
+					pq->stats.errors ++;
 					drbr_advance(ifp, pq->bufring);
 					continue;
 				}
@@ -1818,6 +1853,12 @@
 		/* Copy the packet to listeners. */
 		ETHER_BPF_MTAP(ifp, mhead);
 
+		pq->stats.packets ++;
+		pq->stats.bytes += mhead->m_pkthdr.len;
+		if (mhead->m_flags & M_MCAST) {
+			pq->stats.mcasts ++;
+		}
+
 		m_freem(mhead);
 
 		count ++;
@@ -1876,6 +1917,7 @@
 		/* ENOBUFS when the bufring is full */
 		RD(1, "%s: drbr_enqueue() failed %d\n",
 			__func__, err);
+		pq->stats.errors ++;
 		return err;
 	}
 
@@ -1969,7 +2011,7 @@
 		struct netmap_slot *slot;
 		unsigned int nmbuf_len;
 		uint8_t *nmbuf;
-
+host_sync:
 		if (head == ring->tail) {
 			/* We ran out of slot, let's see if the host has
 			 * added some, by reading hwcur and hwtail from
@@ -2004,8 +2046,10 @@
 				/* There is no good reason why host should
 				 * put the header in multiple netmap slots.
 				 * If this is the case, discard. */
+				RD(1, "Fragmented vnet-hdr: dropping");
 				head = ptnet_rx_discard(kring, head);
-				continue;
+				pq->stats.iqdrops ++;
+				goto skip;
 			}
 			ND(1, "%s: vnet hdr: flags %x csum_start %u "
 			      "csum_ofs %u hdr_len = %u gso_size %u "
@@ -2024,6 +2068,7 @@
 		if (unlikely(mhead == NULL)) {
 			device_printf(sc->dev, "%s: failed to allocate mbuf "
 				      "head\n", __func__);
+			pq->stats.errors ++;
 			break;
 		}
 
@@ -2050,6 +2095,7 @@
 					__func__, head, prev_head);
 				head = prev_head;
 				m_freem(mhead);
+				pq->stats.errors ++;
 				if (may_resched) {
 					taskqueue_enqueue(pq->taskq,
 							  &pq->task);
@@ -2067,11 +2113,12 @@
 
 			if (unlikely(head == ring->tail)) {
 				/* The very last slot prepared by the host has
-				 * the NS_MOREFRAG set. This is an error that
-				 * we handle by accepting the truncated packet,
-				 * and let the network stack drop it. */
-				RD(1, "Warning: Truncating incomplete packet");
-				break;
+				 * the NS_MOREFRAG set. Drop it and continue
+				 * the outer cycle (to do the double-check). */
+				RD(1, "Incomplete packet: dropping");
+				m_freem(mhead);
+				pq->stats.iqdrops ++;
+				goto host_sync;
 			}
 
 			slot = ring->slot + head;
@@ -2104,9 +2151,17 @@
 
 		if (have_vnet_hdr && (vh->flags & (VIRTIO_NET_HDR_F_NEEDS_CSUM
 					| VIRTIO_NET_HDR_F_DATA_VALID))) {
-			ptnet_rx_csum(mhead, vh);
+			if (unlikely(ptnet_rx_csum(mhead, vh))) {
+				m_freem(mhead);
+				RD(1, "Csum offload error: dropping");
+				pq->stats.iqdrops ++;
+				goto skip;
+			}
 		}
 
+		pq->stats.packets ++;
+		pq->stats.bytes += mhead->m_pkthdr.len;
+
 		PTNET_Q_UNLOCK(pq);
 		(*ifp->if_input)(ifp, mhead);
 		PTNET_Q_LOCK(pq);
@@ -2116,7 +2171,7 @@
 			 * have the lock. Stop any processing and exit. */
 			goto unlock;
 		}
-
+skip:
 		count ++;
 		if (++batch_count == PTNET_RX_BATCH) {
 			/* Some packets have been pushed to the network stack.


More information about the svn-soc-all mailing list