Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jul 2016 15:44:37 GMT
From:      vincenzo@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r305830 - soc2016/vincenzo/head/sys/dev/netmap
Message-ID:  <201607081544.u68FibOd008520@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: vincenzo
Date: Fri Jul  8 15:44:36 2016
New Revision: 305830
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305830

Log:
   freebsd: ptnet_rx_eof: strip virtio-net header if needed

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	Fri Jul  8 15:44:28 2016	(r305829)
+++ soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c	Fri Jul  8 15:44:36 2016	(r305830)
@@ -184,6 +184,8 @@
 static void	ptnet_tx_intr(void *opaque);
 static void	ptnet_rx_intr(void *opaque);
 
+static unsigned	ptnet_rx_discard(struct netmap_kring *kring,
+				 unsigned int head);
 static int	ptnet_rx_eof(struct ptnet_queue *pq);
 static void	ptnet_rx_task(void *context, int pending);
 
@@ -1336,7 +1338,7 @@
 ptnet_drain_transmit_queue(struct ptnet_queue *pq)
 {
 	struct ptnet_softc *sc = pq->sc;
-	bool use_vnet_hdr = (sc->ptfeatures & NET_PTN_FEATURES_VNET_HDR);
+	bool have_vnet_hdr = (sc->ptfeatures & NET_PTN_FEATURES_VNET_HDR);
 	struct netmap_adapter *na = &sc->ptna_dr.hwup.up;
 	struct ifnet *ifp = sc->ifp;
 	unsigned int batch_count = 0;
@@ -1415,7 +1417,7 @@
 
 		/* If needed, prepare the virtio-net header at the beginning
 		 * of the first slot. */
-		if (use_vnet_hdr) {
+		if (have_vnet_hdr) {
 			/* For performance, we could replace this memset() with
 			 * two 8-bytes-wide writes. */
 			memset(nmbuf, 0, PTNET_HDR_SIZE);
@@ -1533,6 +1535,23 @@
 	return ptnet_drain_transmit_queue(pq);
 }
 
+static unsigned int
+ptnet_rx_discard(struct netmap_kring *kring, unsigned int head)
+{
+	struct netmap_ring *ring = kring->ring;
+	struct netmap_slot *slot = ring->slot + head;
+
+	for (;;) {
+		head = nm_next(head, kring->nkr_num_slots - 1);
+		if (!(slot->flags & NS_MOREFRAG) || head == ring->tail) {
+			break;
+		}
+		slot = ring->slot + head;
+	}
+
+	return head;
+}
+
 static inline struct mbuf *
 ptnet_rx_slot(struct mbuf *mtail, uint8_t *nmbuf, unsigned int nmbuf_len)
 {
@@ -1575,6 +1594,7 @@
 ptnet_rx_eof(struct ptnet_queue *pq)
 {
 	struct ptnet_softc *sc = pq->sc;
+	bool have_vnet_hdr = (sc->ptfeatures & NET_PTN_FEATURES_VNET_HDR);
 	struct ptnet_ring *ptring = pq->ptring;
 	struct netmap_adapter *na = &sc->ptna_dr.hwup.up;
 	struct netmap_kring *kring = na->rx_rings + pq->kring_id;
@@ -1591,7 +1611,10 @@
 	do {
 		unsigned int prev_head = head;
 		struct mbuf *mhead, *mtail;
+		struct virtio_net_hdr *vh;
 		struct netmap_slot *slot;
+		unsigned int nmbuf_len;
+		uint8_t *nmbuf;
 
 		if (head == ring->tail) {
 			/* We ran out of slot, let's see if the host has
@@ -1615,6 +1638,30 @@
 			}
 		}
 
+		/* Initialize ring state variables, possibly grabbing the
+		 * virtio-net header. */
+		slot = ring->slot + head;
+		nmbuf = NMB(na, slot);
+		nmbuf_len = slot->len;
+
+		vh = (struct virtio_net_hdr *)nmbuf;
+		if (have_vnet_hdr) {
+			if (unlikely(nmbuf_len < PTNET_HDR_SIZE)) {
+				/* There is no good reason why host should
+				 * put the header in multiple netmap slots.
+				 * If this is the case, discard. */
+				head = ptnet_rx_discard(kring, head);
+				continue;
+			}
+			RD(1, "%s: vnet hdr: flags %x csum_start %u "
+			      "csum_ofs %u hdr_len = %u gso_size %u "
+			      "gso_type %x", __func__, vh->flags,
+			      vh->csum_start, vh->csum_offset, vh->hdr_len,
+			      vh->gso_size, vh->gso_type);
+			nmbuf += PTNET_HDR_SIZE;
+			nmbuf_len -= PTNET_HDR_SIZE;
+		}
+
 		/* Allocate the head of a new mbuf chain.
 		 * We use m_getcl() to allocate an mbuf with standard cluster
 		 * size (MCLBYTES). In the future we could use m_getjcl()
@@ -1626,21 +1673,18 @@
 			break;
 		}
 
-		/* Initialize state variables. */
-		mhead->m_pkthdr.len = 0;
+		/* Initialize the mbuf state variables. */
+		mhead->m_pkthdr.len = nmbuf_len;
 		mtail->m_len = 0;
 
 		/* Scan all the netmap slots containing the current packet. */
 		for (;;) {
-			slot = ring->slot + head;
-			mhead->m_pkthdr.len += slot->len;
-
 			DBG(device_printf(sc->dev, "%s: h %u t %u rcv frag "
 					  "len %u, flags %u\n", __func__,
 					  head, ring->tail, slot->len,
 					  slot->flags));
 
-			mtail = ptnet_rx_slot(mtail, NMB(na, slot), slot->len);
+			mtail = ptnet_rx_slot(mtail, nmbuf, nmbuf_len);
 			if (unlikely(!mtail)) {
 				/* Ouch. We ran out of memory while processing
 				 * a packet. We have to restore the previous
@@ -1656,6 +1700,9 @@
 						  &pq->task);
 				goto escape;
 			}
+
+			/* We have to increment head irrespective of the
+			 * NS_MOREFRAG being set or not. */
 			head = nm_next(head, lim);
 
 			if (!(slot->flags & NS_MOREFRAG)) {
@@ -1670,6 +1717,11 @@
 				RD(1, "Warning: Truncating incomplete packet");
 				break;
 			}
+
+			slot = ring->slot + head;
+			nmbuf = NMB(na, slot);
+			nmbuf_len = slot->len;
+			mhead->m_pkthdr.len += nmbuf_len;
 		}
 
 		mhead->m_pkthdr.rcvif = ifp;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607081544.u68FibOd008520>