Message ID | 20240116-prevent_dsa_tags-v6-1-ec44ed59744b@bootlin.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [net,v6] net: stmmac: Prevent DSA tags from breaking COE | expand |
On 1/16/24 04:19, Romain Gantois wrote: > Some DSA tagging protocols change the EtherType field in the MAC header > e.g. DSA_TAG_PROTO_(DSA/EDSA/BRCM/MTK/RTL4C_A/SJA1105). On TX these tagged > frames are ignored by the checksum offload engine and IP header checker of > some stmmac cores. > > On RX, the stmmac driver wrongly assumes that checksums have been computed > for these tagged packets, and sets CHECKSUM_UNNECESSARY. > > Add an additional check in the stmmac TX and RX hotpaths so that COE is > deactivated for packets with ethertypes that will not trigger the COE and > IP header checks. > > Fixes: 6b2c6e4a938f ("net: stmmac: propagate feature flags to vlan") > Cc: <stable@vger.kernel.org> > Reported-by: Richard Tresidder <rtresidd@electromag.com.au> > Link: https://lore.kernel.org/netdev/e5c6c75f-2dfa-4e50-a1fb-6bf4cdb617c2@electromag.com.au/ > Reported-by: Romain Gantois <romain.gantois@bootlin.com> > Link: https://lore.kernel.org/netdev/c57283ed-6b9b-b0e6-ee12-5655c1c54495@bootlin.com/ > Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org> > Signed-off-by: Romain Gantois <romain.gantois@bootlin.com> Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Hello: This patch was applied to netdev/net.git (main) by David S. Miller <davem@davemloft.net>: On Tue, 16 Jan 2024 13:19:17 +0100 you wrote: > Some DSA tagging protocols change the EtherType field in the MAC header > e.g. DSA_TAG_PROTO_(DSA/EDSA/BRCM/MTK/RTL4C_A/SJA1105). On TX these tagged > frames are ignored by the checksum offload engine and IP header checker of > some stmmac cores. > > On RX, the stmmac driver wrongly assumes that checksums have been computed > for these tagged packets, and sets CHECKSUM_UNNECESSARY. > > [...] Here is the summary with links: - [net,v6] net: stmmac: Prevent DSA tags from breaking COE https://git.kernel.org/netdev/net/c/c2945c435c99 You are awesome, thank you!
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c78a96b8eb64..a0e46369ae15 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4435,6 +4435,28 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +/** + * stmmac_has_ip_ethertype() - Check if packet has IP ethertype + * @skb: socket buffer to check + * + * Check if a packet has an ethertype that will trigger the IP header checks + * and IP/TCP checksum engine of the stmmac core. + * + * Return: true if the ethertype can trigger the checksum engine, false + * otherwise + */ +static bool stmmac_has_ip_ethertype(struct sk_buff *skb) +{ + int depth = 0; + __be16 proto; + + proto = __vlan_get_protocol(skb, eth_header_parse_protocol(skb), + &depth); + + return (depth <= ETH_HLEN) && + (proto == htons(ETH_P_IP) || proto == htons(ETH_P_IPV6)); +} + /** * stmmac_xmit - Tx entry point of the driver * @skb : the socket buffer @@ -4499,9 +4521,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* DWMAC IPs can be synthesized to support tx coe only for a few tx * queues. In that case, checksum offloading for those queues that don't * support tx coe needs to fallback to software checksum calculation. + * + * Packets that won't trigger the COE e.g. most DSA-tagged packets will + * also have to be checksummed in software. */ if (csum_insertion && - priv->plat->tx_queues_cfg[queue].coe_unsupported) { + (priv->plat->tx_queues_cfg[queue].coe_unsupported || + !stmmac_has_ip_ethertype(skb))) { if (unlikely(skb_checksum_help(skb))) goto dma_map_err; csum_insertion = !csum_insertion; @@ -5066,7 +5092,7 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, stmmac_rx_vlan(priv->dev, skb); skb->protocol = eth_type_trans(skb, priv->dev); - if (unlikely(!coe)) + if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb)) skb_checksum_none_assert(skb); else skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -5589,7 +5615,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) skb->protocol = eth_type_trans(skb, priv->dev); - if (unlikely(!coe)) + if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb)) skb_checksum_none_assert(skb); else skb->ip_summed = CHECKSUM_UNNECESSARY;