openwrt / openwrt/openwrt

Ath79 and Jumbo Frames

Open
#20,564 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug invalid
Dominant language
C
Stars
28.5k
Forks
13k
PR merge metrics
PR metrics pending

Description

Describe the bug

Hello,

In the migration from ar71xx to ath79 the max_frame_length of the ethernet frames for some ath79 devices went from allowing Jumbo Frames to a hard limit of 1540 bytes.

In the current code, the file target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c sets the max_frame_len:

static int ag71xx_probe(struct platform_device *pdev)
{
...
        if (of_device_is_compatible(np, "qca,ar9340-eth") ||
            of_device_is_compatible(np, "qca,qca9530-eth") ||
            of_device_is_compatible(np, "qca,qca9550-eth") ||
            of_device_is_compatible(np, "qca,qca9560-eth"))
                ag->desc_pktlen_mask = SZ_16K - 1;
        else
                ag->desc_pktlen_mask = SZ_4K - 1;

        if (ag->desc_pktlen_mask == SZ_16K - 1 &&
            !of_device_is_compatible(np, "qca,qca9550-eth") &&
            !of_device_is_compatible(np, "qca,qca9560-eth"))
                max_frame_len = ag->desc_pktlen_mask;
        else
                max_frame_len = 1540;

The code in OpenWRT 19.07.9 didn't work this way: it checked every SoC variant and for each it set the max mtu length.

For the aforementioned SoCs the code in target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c was:

void __init ath79_register_eth(unsigned int id)
{
...
        pdata->max_frame_len = 1540;
        pdata->desc_pktlen_mask = 0xfff;
...
        switch (ath79_soc) {
...
        case ATH79_SOC_QCA9556:
        case ATH79_SOC_QCA9558:
...
                /*
                 * Limit the maximum frame length to 4095 bytes.
                 * Although the documentation says that the hardware
                 * limit is 16383 bytes but that does not work in
                 * practice. It seems that the hardware only updates
                 * the lowest 12 bits of the packet length field
                 * in the RX descriptor.
                 */
                pdata->max_frame_len = SZ_4K - 1;
                pdata->desc_pktlen_mask = SZ_16K - 1;
                break;

So for the QCA9556/58 SoC Jumbo Frames up to of 4095 bytes were allowed, and I could set a MTU of 1508 bytes on the PPPoE link and avoid the typical fragmentation problems caused by the PPPoE headers.

To restore the old functionality I've been carrying the following patch on my local git repo:

+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
@@ -1604,9 +1604,18 @@ static int ag71xx_probe(struct platform_device *pdev)
        else
                ag->desc_pktlen_mask = SZ_4K - 1;

-       if (ag->desc_pktlen_mask == SZ_16K - 1 &&
-           !of_device_is_compatible(np, "qca,qca9550-eth") &&
-           !of_device_is_compatible(np, "qca,qca9560-eth"))
+       if (of_device_is_compatible(np, "qca,qca9550-eth") ||
+           of_device_is_compatible(np, "qca,qca9560-eth"))
+               /*
+                * Limit the maximum frame length to 4095 bytes.
+                * Although the documentation says that the hardware
+                * limit is 16383 bytes but that does not work in
+                * practice. It seems that the hardware only updates
+                * the lowest 12 bits of the packet length field
+                * in the RX descriptor.
+                */
+               max_frame_len = SZ_4K - 1;
+       else if (ag->desc_pktlen_mask == SZ_16K - 1)
                max_frame_len = ag->desc_pktlen_mask;
        else
                max_frame_len = 1540;

This works perfectly for my TP-Link Archer C7 v2 and v4 routers and restores the lost functionality I had in OpenWRT 19.

Do you think it's feasible to merge a patch like the above one?

OpenWrt version

r28978

OpenWrt release

'24.10-SNAPSHOT

OpenWrt target/subtarget

ath79/generic

Device

TP-Link Archer C7 v2

Image kind

Self-built image

Steps to reproduce

No response

Actual behaviour

No response

Expected behaviour

No response

Additional info

No response

Diffconfig

Terms
  • I am reporting an issue for OpenWrt, not an unsupported fork.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c, especially ag71xx_probe, and compare the current max_frame_len logic with the historical target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c behavior. Check the proposed compatibility handling for qca,qca9550-eth and qca,qca9560-eth, then validate on an Archer C7 that MTU values requiring jumbo frames work without fragmentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
embedded-iot, networking, operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.