1

On the Pi 4B, what is the correct way to persistently force the eth0 interface to 100 mbps Full Duplex? Thanks.

3
  • I know in distros like Majaro ARM it lets you configure this, however I'm not sure how exactly it does.
    – dominic03
    Sep 4, 2020 at 17:47
  • Have you tested your eth0 settings using ethtool?
    – Seamus
    Sep 4, 2020 at 20:19
  • Gigabit require a good-enough Ethernet cable. You could get an old one only suitable for 100 Mbit so higher negotiation fails May 12 at 12:38

4 Answers 4

5

You should have a utility named ethtool on your system. I presume you're acquainted with it. If not, please review man ethtool. Before making any settings persistent, you should first verify that the settings won't cause you to be locked out of your system. If you break something with ethtool before you make it persistent, you can recover by power cycling your RPi. If you make an erroneous change persistent, recovery may become more difficult - possibly requiring you to re-flash your SD card.

Also N.B. that forcing eth0 on your RPi to adopt fixed parameters may require the other side of the connection (e.g. switch, router, etc) be modified also. I am not sure that forcing your adapter to 100 Mbps & full duplex is the best way to achieve your objective. Consequently, this answer proposes a different approach using the advertise option in ethtool to set eth0 to always operate at 100-FD:

The approach: advertise only 100baseT Full

I suppose this could be considered inflexible negotiation, as you are instructing eth0 to negotiate, but accept only 100baseT Full from the connected device. Before changing any settings, use ethtool to review the current settings for eth0 and its "Link Partner" - the upstream device (router, switch, etc):

Verify eth0 and Link partner share the desired settings

$ ethtool eth0
...
$

In the output, review the settings for Advertised Link Modes for eth0, and for its Link Partner; for example:

    Advertised link modes:  10baseT/Half 10baseT/Full  
                            100baseT/Half 100baseT/Full  
                            1000baseT/Half 1000baseT/Full  
    Link partner advertised link modes:  10baseT/Half 10baseT/Full
                                         100baseT/Half 100baseT/Full
                                         1000baseT/Half 1000baseT/Full

Note that in this case, 100baseT/Full is common to eth0 and its Link partner. Once you've verified this common ground, make the following change:

Use ethtool to change eth0 advertisement

$ sudo ethtool -s eth0 advertise 0x008
$

It may take a few seconds for RPi to "digest" this change. Assuming it completes without error, verify the change was accepted:

$ ethtool eth0
...
$ 

The Advertised link modes should now show only the desired option:

    Advertised link modes:  100baseT/Full

Networking can be verified, and should be fully functional at this point - you may or may not notice a speed difference. If something has "gone wrong", and you find connectivity lost or impaired, reboot, or power-cycle the RPi to restore the defult configuration. Changes made with ethtool at the CLI are not persistent across reboots. If you're satisfied, you can make the change persistent by modifying /etc/network/if-pre-up.d/ethtool:

Modify /etc/network/if-pre-up.d/ethtool for persistent changes

/etc/network/if-pre-up.d/ethtool is a shell script run before the interface is brought up. A "default" script is provided - you will need to modify it to make any ethtool configuration changes persistent across reboots.

What follows is admittedly a hack. That is to say I'm sure the code can be made more elegant, but I have tried this on my RPi 4, and it does work:

$ sudo nano /etc/network/if-pre-up.d/ethtool

Use the editor to add the following line to the end of the script:

$ETHTOOL --change eth0 advertise 0x008

Following is the result used on my RPi 4 test system:

#!/bin/sh

ETHTOOL=/sbin/ethtool

test -x $ETHTOOL || exit 0

[ "$IFACE" != "lo" ] || exit 0

# Gather together the mixed bag of settings applied with -s/--change
SETTINGS="\
${IF_ETHERNET_PORT:+ port $IF_ETHERNET_PORT}\
${IF_DRIVER_MESSAGE_LEVEL:+ msglvl $IF_DRIVER_MESSAGE_LEVEL}\
"
[ -z "$SETTINGS" ] || $ETHTOOL --change "$IFACE" $SETTINGS

$ETHTOOL --change eth0 advertise 0x008
10
  • possibly requiring you to re-flash your SD card - or in the case of networking not working, simply attach a keyboard and monitor :p Sep 5, 2020 at 0:25
  • @JaromandaX: That would be a neat trick with the "Lite" version of RPi OS.
    – Seamus
    Sep 5, 2020 at 1:07
  • the lite version of RPi OS handles screen and keyboard perfectly well - I fail to see your point - lite just means no GUI - the CLI is perfectly functional over keyboard and monitor Sep 5, 2020 at 1:08
  • @JaromandaX: I did not know that - thanks for the enlightenment. But it does require "stuff" (keyboard, monitor, cable) that may not be on hand... thus the word, "possibly".
    – Seamus
    Sep 5, 2020 at 1:16
  • true - but you'd probably have keyboard and monitor on the PC you flashed the SD card on (OK, laptops are way more popular these days than 10 years ago, but still ...) Sep 5, 2020 at 1:55
4

I know this is an old topic, but I wanted to share an alternate solution in case anyone else runs into this problem.

The ethtool advertise approach described by Seamus works, but finding usable hooks to configure the interface at boot time and whenever the interface gets reset is not easy. Not to mention that the configuration inevitably happens after the interface has been started. I ended up writing a custom systemd service, but it definitely felt like a hack.

Eventually, I found a much simpler solution using a custom device tree overlay. The overlay configures the max-speed of the phy at boot time. This effectively disables gigabit on the interface. I am using this on a custom CM4 carrier board and it works perfectly every time.

Here is the device tree overlay source: cm4-disable-gigabit-ethernet.dts:

/dts-v1/;
/plugin/;

/ {
    /* Change the phy max-speed to 100 Mbps */
    fragment@0 {
        target = <&phy1>;
        __overlay__ {
            max-speed = <100>;
        };
    };
};

The overlay is compiled and installed as follows. Then add "dtoverlay=cm4-disable-gigabit-ethernet" to /boot/config.txt

dtc -@ -Hepapr -I dts -O dtb -o cm4-disable-gigabit-ethernet.dtbo cm4-disable-gigabit-ethernet.dts
sudo cp cm4-disable-gigabit-ethernet.dtbo /boot/overlays/
1
  • Thanks for posting. The ethtool solution worked, but I'll keep this alternative in mind if facing the situation again.
    – MAXdB
    Aug 10 at 14:09
1

There is a setting to force 100Mbps.

The commands are (although you may need to use in a different order):-

sudo ethtool -s eth0 autoneg off
sudo ethtool -s eth0 speed 100

You should check man ethtool

See https://raspberrypi.stackexchange.com/a/112682/8697

0

You could simply just connect the devices with a cat 5 Ethernet cable which has a maximum throughput of 100mbps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.