Download raw body.
em(4): fix I210/I350 handling of crc stripping
On Mon, Jul 07, 2025 at 08:03:33PM +1000, Jonathan Matthew wrote:
> dtucker@ reported that I210 em(4) interfaces behaved weirdly at specific
> larger-than-default-MTU packet sizes.
>
> The handling of packets with very short final segments for I210/I350 looks
> fishy to me. On these chips the CRC is always stripped (see if_em.c r1.378 line 2850),
> but the code in em_rxeof() dealing with stripping the CRC will still remove the
> final 4 bytes of the packet if they happen to be split across segments.
>
> The diff below, which reorders the tests in the if-else block so we never
> truncate packets in the name of CRC stripping on I210/I350, reportedly fixes this.
> Darren's test for reproducing the problem was just using ping:
>
> $ for i in `seq 64 9000`; do ping -c1 -w1 -s$i 192.168.32.248 >/dev/null || printf "$i "; done; echo
> 2007 2008 2009 4055 4056 4057 6103 6104 6105 8151 8152 8153
>
> If you use large packets with em(4) interfaces, or would like to but haven't
> been able to, you might want to test this yourself.
>
> ok?
>
Diff makes sense, ok stsp@
I cannot test these particular em devices myself.
> Index: if_em.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_em.c,v
> diff -u -p -r1.378 if_em.c
> --- if_em.c 31 Aug 2024 16:23:09 -0000 1.378
> +++ if_em.c 7 Jul 2025 03:31:22 -0000
> @@ -3116,13 +3116,14 @@ em_rxeof(struct em_queue *que)
>
> if (status & E1000_RXD_STAT_EOP) {
> eop = 1;
> - if (desc_len < ETHER_CRC_LEN) {
> + if (sc->hw.mac_type == em_i210 ||
> + sc->hw.mac_type == em_i350) {
> + /* crc has already been stripped */
> + len = desc_len;
> + } else if (desc_len < ETHER_CRC_LEN) {
> len = 0;
> prev_len_adj = ETHER_CRC_LEN - desc_len;
> - } else if (sc->hw.mac_type == em_i210 ||
> - sc->hw.mac_type == em_i350)
> - len = desc_len;
> - else
> + } else
> len = desc_len - ETHER_CRC_LEN;
> } else {
> eop = 0;
>
>
em(4): fix I210/I350 handling of crc stripping