socsvn commit: r305830 - soc2016/vincenzo/head/sys/dev/netmap
vincenzo at FreeBSD.org
vincenzo at FreeBSD.org
Fri Jul 8 15:44:38 UTC 2016
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;
More information about the svn-soc-all
mailing list