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

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

Log:
   freebsd: ptnet_rx_eof: handle errors

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:43:10 2016	(r305821)
+++ soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c	Fri Jul  8 15:43:19 2016	(r305822)
@@ -1550,9 +1550,10 @@
 	kring->nr_kflags &= ~NKR_PENDINTR;
 
 	for (;;) {
+		unsigned int prev_head = head;
+		struct mbuf *mhead, *mtail;
 		struct netmap_slot *slot;
 		unsigned int nmbuf_len;
-		struct mbuf *mhead, *mtail;
 		uint8_t *nmbuf, *mdata;
 
 		if (budget == 0) {
@@ -1582,7 +1583,8 @@
 			}
 		}
 
-		/* We use m_getcl() to allocate an mbuf with standard cluster
+		/* Allocate the head of an mbuf chain.
+		 * We use m_getcl() to allocate an mbuf with standard cluster
 		 * size (MCLBYTES). In the future we could use m_getjcl()
 		 * to choose different sizes. */
 		mhead = mtail = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
@@ -1606,7 +1608,7 @@
 		mdata = mtod(mtail, uint8_t *);
 		mtail->m_len = 0;
 
-		do {
+		for (;;) {
 			slot = ring->slot + head;
 			nmbuf_len = slot->len;
 			nmbuf = NMB(na, slot);
@@ -1625,10 +1627,22 @@
 					struct mbuf *mf;
 
 					mf = m_getcl(M_NOWAIT, MT_DATA, 0);
-					if (!mf) {
-						/* XXX handle error */
-						break;
+					if (unlikely(!mf)) {
+						/* Ouch. We ran out of memory
+						 * while processing a packet.
+						 * We have to restore the
+						 * previous head position,
+						 * free the mbuf chain, and
+						 * schedule the taskqueue to
+						 * give the packet another
+						 * chance. */
+						head = prev_head;
+						m_freem(mhead);
+						taskqueue_enqueue(pq->taskq,
+								  &pq->task);
+						goto escape;
 					}
+
 					mtail->m_next = mf;
 					mtail = mf;
 					mdata = mtod(mtail, uint8_t *);
@@ -1649,7 +1663,20 @@
 			} while (nmbuf_len);
 
 			head = nm_next(head, lim);
-		} while (slot->flags & NS_MOREFRAG);
+
+			if (!(slot->flags & NS_MOREFRAG)) {
+				break;
+			}
+
+			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;
+			}
+		}
 
 		PTNET_Q_UNLOCK(pq);
 		(*ifp->if_input)(ifp, mhead);
@@ -1657,7 +1684,7 @@
 
 		budget--;
 	}
-
+escape:
 	if (head != ring->head) {
 		/* Some packets have been pushed to the network stack.
 		 * We need to update the CSB to tell the host about the new



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