On the Pi 4B, what is the correct way to persistently force the eth0 interface to 100 mbps Full Duplex? Thanks.
4 Answers
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 reboot
s.
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

- 21,900
- 3
- 33
- 70
-
possibly requiring you to re-flash your SD card
- or in the case of networking not working, simply attach a keyboard and monitor :p – Jaromanda X Sep 05 '20 at 00:25 -
@JaromandaX: That would be a neat trick with the "Lite" version of RPi OS. – Seamus Sep 05 '20 at 01: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 – Jaromanda X Sep 05 '20 at 01: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 05 '20 at 01: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 ...) – Jaromanda X Sep 05 '20 at 01:55
-
@JaromandaX: "possibly". "probably". Perhaps you should take it up here. :) Or just edit the answer if it bothers you. – Seamus Sep 05 '20 at 02:37
-
Thank you, Seamus. I had put
sleep 5
;ethtool -s eth0 speed 100 duplex full autoneg off
;systemctl restart networking
in rc.local to get it going, naively on my own, knowing it was a hack. I will go back and try your fine-tuned suggestions, which I was asking for in re "correct way" to do it. – MAXdB Sep 05 '20 at 20:55 -
-
Adding the line to
/etc/network/if-pre-up.d/ethtool
didn't persist the setting across reboots, for me (RPI4, Raspbian10). I had to add the line to add the ethtool command to/etc/rc.local
instead. – Mendhak Feb 16 '21 at 08:32 -
@Mendhak: That's odd because it does work on my RPi4/buster. I'd suggest you submit this as a new question. You should include all the details of what you did. I will say this about
rc.local
: 1) Its use is discouraged as it's no longer maintained, 2) It shouldn't make any difference unless something on your system is preventingethtool
being run during the boot process. – Seamus Feb 16 '21 at 18:53
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/

- 141
- 1
-
Thanks for posting. The ethtool solution worked, but I'll keep this alternative in mind if facing the situation again. – MAXdB Aug 10 '23 at 14:09
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

- 59,890
- 31
- 101
- 209
You could simply just connect the devices with a cat 5 Ethernet cable which has a maximum throughput of 100mbps.

- 197
- 1
- 3
- 16
-
...But with Cat.5 it will try to negotiate (and probably succeed in establishing) a 1 Gbit connection. Also, Cat. 5E is perfectly capable of carrying 1 Gbps. The only way you can force 100 Mbps or lower is by using 2-pair cables. – StarCat Jan 21 '24 at 10:19
eth0
settings usingethtool
? – Seamus Sep 04 '20 at 20:19