On Wed, Jan 26, 2022 at 01:29:42AM +0100, Alexander Bluhm wrote:
> Hi,
>
> There were some problems with ix(4) and ixl(4) hardware checksumming
> for the output path on strict alignment architectures.
>
> I have merged jan@'s diffs and added some sanity checks and
> workarounds.
>
> - If the first mbuf is not aligned or not contigous, use m_copydata()
> to extract the IP, IPv6, TCP header.
> - If the header is in the first mbuf, use m_data for the fast path.
> - Add netstat counter for invalid header chains. This makes
> us aware when hardware checksumming fails.
> - Add netstat counter for header copies. This indicates that
> better storage allocation in the network stack is possible.
> It also allows to recognize alignment problems on non-strict
> architectures.
> - There is not risk of crashes on sparc64.
>
> Does this aproach make sense?
>
> ix(4) works quite well, but finds some UDP packets that need copy.
> ixl(4) has not been tested yet. I would like to have some feedback
> for the idea first.
>
> bluhm
>
> Index: sys/dev/pci/if_ixl.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ixl.c,v
> retrieving revision 1.78
> diff -u -p -r1.78 if_ixl.c
> --- sys/dev/pci/if_ixl.c 9 Jan 2022 05:42:54 -0000 1.78
> +++ sys/dev/pci/if_ixl.c 25 Jan 2022 23:50:01 -0000
> @@ -1388,6 +1398,7 @@ static int ixl_rxeof(struct ixl_softc *,
> static void ixl_rxfill(struct ixl_softc *, struct ixl_rx_ring *);
> static void ixl_rxrefill(void *);
> static int ixl_rxrinfo(struct ixl_softc *, struct if_rxrinfo *);
> +static void ixl_rx_checksum(struct mbuf *, uint64_t);
>
> #if NKSTAT > 0
> static void ixl_kstat_attach(struct ixl_softc *);
> @@ -3190,6 +3318,7 @@ ixl_rxeof(struct ixl_softc *sc, struct i
> m->m_pkthdr.csum_flags |= M_FLOWID;
> }
>
> + ixl_rx_checksum(m, word);
> ml_enqueue(&ml, m);
> } else {
> ifp->if_ierrors++; /* XXX */
> @@ -3320,6 +3449,23 @@ ixl_rxrinfo(struct ixl_softc *sc, struct
> free(ifr, M_TEMP, ixl_nqueues(sc) * sizeof(*ifr));
>
> return (rv);
> +}
> +
> +static void
> +ixl_rx_checksum(struct mbuf *m, uint64_t word)
> +{
> + if (!ISSET(word, IXL_RX_DESC_L3L4P))
> + return;
> +
> + if (ISSET(word, IXL_RX_DESC_IPE))
> + return;
> +
> + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
> +
> + if (ISSET(word, IXL_RX_DESC_L4E))
> + return;
> +
> + m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
> }
>
> static int
this is ok by me. tested on both amd64 and sparc64.
dlg