[PATCH] hw/net/fsl_etsec: implement RCTRL[CFA] FCS stripping on receive

Vivien LEGER posted 1 patch 1 month, 2 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260412134016.1640882-1-vivien.leger@gmail.com
Maintainers: Bernhard Beschow <shentey@gmail.com>, Jason Wang <jasowang@redhat.com>
hw/net/fsl_etsec/registers.h |  1 +
hw/net/fsl_etsec/rings.c     | 10 ++++++++++
2 files changed, 11 insertions(+)
[PATCH] hw/net/fsl_etsec: implement RCTRL[CFA] FCS stripping on receive
Posted by Vivien LEGER 1 month, 2 weeks ago
The eTSEC hardware strips the 4-byte FCS from received frames by
default (RCTRL[CFA]=0). When CFA=1, FCS is copied to the application
buffer and bd->length includes it.

Previously QEMU always included FCS in bd->length regardless of CFA,
causing guests using the default RCTRL to receive 4 extra bytes per
frame, breaking protocols that validate frame length (e.g. ARP).

Fix by subtracting 4 from bd->length when RCTRL[CFA]=0 (default).

Signed-off-by: Vivien LEGER <vivien.leger@gmail.com>
---
 hw/net/fsl_etsec/registers.h |  1 +
 hw/net/fsl_etsec/rings.c     | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/hw/net/fsl_etsec/registers.h b/hw/net/fsl_etsec/registers.h
index f085537ecd..1766e39a1a 100644
--- a/hw/net/fsl_etsec/registers.h
+++ b/hw/net/fsl_etsec/registers.h
@@ -103,6 +103,7 @@ extern const eTSEC_Register_Definition eTSEC_registers_def[];
 #define RCTRL_PRSDEP_MASK   (0x3)
 #define RCTRL_PRSDEP_OFFSET (6)
 #define RCTRL_RSF           (1 << 2)
+#define RCTRL_CFA           (1 << 11)  /* Copy FCS to application */
 
 /* Index of each register */
 
diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 22660c32b8..38e27ad6d8 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -442,6 +442,16 @@ static void fill_rx_bd(eTSEC          *etsec,
             cpu_physical_memory_write(bufptr, padd, rem);
         }
     }
+
+    /* Strip FCS unless RCTRL[CFA] requests copy to application.
+     * Per FSL eTSEC architecture (RCTRL field descriptions):
+     * CFA=0 (reset default): FCS is checked and discarded by hardware,
+     *   bd->length should not include the 4-byte FCS.
+     * CFA=1: FCS is copied to the application buffer, bd->length includes FCS.
+     */
+    if (!(etsec->regs[RCTRL].value & RCTRL_CFA) && bd->length >= 4) {
+        bd->length -= 4;
+    }
 }
 
 static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
-- 
2.53.0
Re: [PATCH] hw/net/fsl_etsec: implement RCTRL[CFA] FCS stripping on receive
Posted by Vivien LEGER 1 month, 2 weeks ago
Please disregard the previous patch.
The RCTRL[CFA] bit reference was incorrect; CFA appears in the DFVLAN
register context, not RCTRL.
The patch needs further research before resubmission.
Sorry for the noise.

On Sun, Apr 12, 2026 at 3:40 PM Vivien LEGER <vivien.leger@gmail.com> wrote:

> The eTSEC hardware strips the 4-byte FCS from received frames by
> default (RCTRL[CFA]=0). When CFA=1, FCS is copied to the application
> buffer and bd->length includes it.
>
> Previously QEMU always included FCS in bd->length regardless of CFA,
> causing guests using the default RCTRL to receive 4 extra bytes per
> frame, breaking protocols that validate frame length (e.g. ARP).
>
> Fix by subtracting 4 from bd->length when RCTRL[CFA]=0 (default).
>
> Signed-off-by: Vivien LEGER <vivien.leger@gmail.com>
> ---
>  hw/net/fsl_etsec/registers.h |  1 +
>  hw/net/fsl_etsec/rings.c     | 10 ++++++++++
>  2 files changed, 11 insertions(+)
>
> diff --git a/hw/net/fsl_etsec/registers.h b/hw/net/fsl_etsec/registers.h
> index f085537ecd..1766e39a1a 100644
> --- a/hw/net/fsl_etsec/registers.h
> +++ b/hw/net/fsl_etsec/registers.h
> @@ -103,6 +103,7 @@ extern const eTSEC_Register_Definition
> eTSEC_registers_def[];
>  #define RCTRL_PRSDEP_MASK   (0x3)
>  #define RCTRL_PRSDEP_OFFSET (6)
>  #define RCTRL_RSF           (1 << 2)
> +#define RCTRL_CFA           (1 << 11)  /* Copy FCS to application */
>
>  /* Index of each register */
>
> diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
> index 22660c32b8..38e27ad6d8 100644
> --- a/hw/net/fsl_etsec/rings.c
> +++ b/hw/net/fsl_etsec/rings.c
> @@ -442,6 +442,16 @@ static void fill_rx_bd(eTSEC          *etsec,
>              cpu_physical_memory_write(bufptr, padd, rem);
>          }
>      }
> +
> +    /* Strip FCS unless RCTRL[CFA] requests copy to application.
> +     * Per FSL eTSEC architecture (RCTRL field descriptions):
> +     * CFA=0 (reset default): FCS is checked and discarded by hardware,
> +     *   bd->length should not include the 4-byte FCS.
> +     * CFA=1: FCS is copied to the application buffer, bd->length
> includes FCS.
> +     */
> +    if (!(etsec->regs[RCTRL].value & RCTRL_CFA) && bd->length >= 4) {
> +        bd->length -= 4;
> +    }
>  }
>
>  static void rx_init_frame(eTSEC *etsec, const uint8_t *buf, size_t size)
> --
> 2.53.0
>
>