git: a51aee0a9828 - stable/14 - vtnet: Adjust for ethernet alignment.

From: Warner Losh <imp_at_FreeBSD.org>
Date: Mon, 19 Feb 2024 04:48:49 UTC
The branch stable/14 has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=a51aee0a9828238ebdf2f55448d97f1f00acc5d4

commit a51aee0a9828238ebdf2f55448d97f1f00acc5d4
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2024-01-29 05:08:55 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-02-19 04:47:16 +0000

    vtnet: Adjust for ethernet alignment.
    
    If the header that we add to the packet's size is 0 % 4 and we're
    strictly aligning, then we need to adjust where we store the header so
    the packet that follows will have it's struct ip header properly
    aligned.  We do this on allocation (and when we check the length of the
    mbufs in the lro_nomrg case). We can't just adjust the clustersz in the
    softc, because it's also used to allocate the mbufs and it needs to be
    the proper size for that. Since we otherwise use the size of the mbuf
    (or sometimes the smaller size of the received packet) to compute how
    much we can buffer, this ensures no overflows. The 2 byte adjustment
    also does not affect how many packets we can receive in the lro_nomrg
    case.
    
    PR:                     271288
    Sponsored by:           Netflix
    Reviewed by:            bryanv
    Differential Revision:  https://reviews.freebsd.org/D43224
    
    (cherry picked from commit 3be59adbb5a2ae7600d46432d3bc82286e507e95)
---
 sys/dev/virtio/network/if_vtnet.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
index f7ad385b3955..ab77205000d5 100644
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -1543,6 +1543,15 @@ vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_tailp)
 		}
 
 		m->m_len = size;
+#ifndef __NO_STRICT_ALIGNMENT
+		/*
+		 * Need to offset the mbuf if the header we're going to add
+		 * will misalign.
+		 */
+		if (sc->vtnet_hdr_size % 4 == 0) {
+			m_adj(m, ETHER_ALIGN);
+		}
+#endif
 		if (m_head != NULL) {
 			m_tail->m_next = m;
 			m_tail = m;
@@ -1569,6 +1578,14 @@ vtnet_rxq_replace_lro_nomrg_buf(struct vtnet_rxq *rxq, struct mbuf *m0,
 
 	sc = rxq->vtnrx_sc;
 	clustersz = sc->vtnet_rx_clustersz;
+#ifndef __NO_STRICT_ALIGNMENT
+	/*
+	 * Need to offset the mbuf if the header we're going to add will
+	 * misalign, account for that here.
+	 */
+	if (sc->vtnet_hdr_size % 4 == 0)
+		clustersz -= ETHER_ALIGN;
+#endif
 
 	m_prev = NULL;
 	m_tail = NULL;
@@ -1692,6 +1709,10 @@ vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m)
 	header_inlined = vtnet_modern(sc) ||
 	    (sc->vtnet_flags & VTNET_FLAG_MRG_RXBUFS) != 0; /* TODO: ANY_LAYOUT */
 
+	/*
+	 * Note: The mbuf has been already adjusted when we allocate it if we
+	 * have to do strict alignment.
+	 */
 	if (header_inlined)
 		error = sglist_append_mbuf(sg, m);
 	else {