26

I would like to turn off tcp segmentation offload on a CentOS5 server. Using ethtool the command is ethtool -K eth0 tso off However, this setting only persists for this session. How can I make it persist through reboots?

1
  • 2
    put it in a start script somewhere.
    – Zoredache
    Jan 4, 2013 at 19:08

8 Answers 8

17

For RHEL7 in /etc/sysconfig/network-scripts/ifcfg-* you may have:

ETHTOOL_OPTS="-K ${DEVICE} gso off gro off tso off"

if more options then use like

ETHTOOL_OPTS="-K ${DEVICE} gso off;-K ${DEVICE} gro off;-K ${DEVICE} tso off"

you have to have naturally DEVICE defined in your ifcfg file.

No rc.local nor extra ifup scripts needed. Easy to you in generic deployment systems.

16

From this webpage:

You can enter the ethtool commands in /etc/rc.local (or your distribution's equivalent) where commands are run after the current runlevel completes, but this isn't ideal. Network services may have started during the runlevel and ethtool commands tend to interrupt network traffic. It would be more preferable to have the commands applied as the interface is brought up.

The network service in CentOS has the ability to do this. The script /etc/sysconfig/network-scripts/ifup-post checks for the existence of /sbin/ifup-local, and if it exists, runs it with the interface name as a parameter (eg: /sbin/ifup-local eth0)

We can create this file with touch /sbin/ifup-local make it executable with chmod +x /sbin/ifup-local set its SELinux context with chcon --reference /sbin/ifup /sbin/ifup-local and then open it in an editor.

A simple script to apply the same settings to all interfaces would be something like

#!/bin/bash
if [ -n "$1" ]; then
/sbin/ethtool -G $1 rx 4096 tx 4096
/sbin/ethtool -K $1 tso on gso on
fi

Keep in mind this will attempt to apply settings to ALL interfaces, even the loopback.

If we have different interfaces we want to apply different settings to, or want to skip the loopback, we can make a case statement

#!/bin/bash
case "$1" in
eth0)
/sbin/ethtool -G $1 rx 16384 tx 16384
/sbin/ethtool -K $1 gso on gro on
;;
eth1)
/sbin/ethtool -G $1 rx 64 tx 64
/sbin/ethtool -K $1 tso on gso on
/sbin/ip link set $1 txqueuelen 0
;;
esac
exit 0

Now ethtool settings are applied to interfaces as they start, all potential interruptions to network communication are done as the interface is brought up, and your server can continue to boot with full network capabilities.

1
15

If you are on RHEL7 (or alike) and use Network Manager instead of /etc/init.d/network to control your interfaces the proposed answer will not work, since /sbin/ifup-local (as well as ifdown-pre-local and ifdown-local) will never get executed.

Instead put your scripts into /etc/NetworkManager/dispatcher.d/ and make sure the NetworkManager-dispatcher service is enabled

systemctl enable NetworkManager-dispatcher

Hint: The dispatcher will only kick in once NetworkManager makes changes to an interface, it doesn't need to be running or anything, so if the status reads

Active: inactive (dead)

that's completely fine!

Also make sure your script is:

  1. executable (chmod +x)
  2. owned by root (chown root:root)
  3. writable by root only (chmod 755)

Now NetworkManager will pass two (2) variables to the dispatcher:

$1 being the interface (eno16777984, eth0, ppp0, etc...)

$2 holding the status (either up or down)

and it allows chaining the scripts (just like /etc/rc...) to have some control over the order in which the dispatcher will execute them:

10-first, 20-second and so on...

The order will be ascending on a connect

if [$2 = "up"] its 10-first followed by 20-second

and descending on a disconnect

if [$2 = "down"] you get 20-second followed by 10-first

and so on.

So to accomplish what OP was looking for you could put something like this:

#!/bin/bash
if [ "$1" = "eth0" ] && [ "$2" = "up" ]; then
  /sbin/ethtool --offload eth0 tso off
fi

in /etc/NetworkManager/dispatcher.d/20-ethtool

And call it a day.

Cheers

5
  • Please note that this question is very old and that it already has an accepted answer and your answer does not really add new. Please try to avoid answering very old posts as it tends to clutter up the front page. May 27, 2016 at 21:20
  • 5
    Search Google for "ifup-local" and you get this as the 6th hit. Nothing i would consider "old" May 27, 2016 at 21:28
  • 4
    This definitely adds something in regards to CentOS 7. No other solution worked for me in CentOS 7.
    – JDL
    Nov 14, 2016 at 18:34
  • 4
    The bash script has an error, it should be: if [ "$1" = "eth0" ] && [ "$2" = "up" ]; then
    – dreua
    Aug 1, 2018 at 12:36
  • On other distro's, ethtool is at /usr/bin/ethtool instead.
    – jobukkit
    Mar 9 at 18:22
5

I ran into problems with the accepted answer (which, I hasten to add, I found very helpful) because I was using bonded interfaces.

It took me a while to discover what was happening but I found that when bringing up a bond, or even when bringing up a bond slave individually, the ifup-local script would not be called for the slave interfaces. I assume that this is because the slave interfaces did not have any IP addresses assigned to them.

To get round this I modified my ifup-local to parse the contents of /proc/bonding/bondX for the interface which had been brought up, if it was a bond, to get the slave interface names, and then did the necessary stuff with them.

In the end my ifup-local looked like the following:

#!/bin/bash

if [ -n "$1" ]
then
  IFACE="$1"

  # If interface is physical
  if [[ $IFACE =~ ^eth[0-9]+$ ]]
  then
    # Do whatever you need for a physical interface here
    # example below
    /sbin/ethtool -K $IFACE rx off    

  # Else if it's a bond
  elif [[ $IFACE =~ ^bond[0-9]+$ ]]
  then
    # Do whatever you need for the bond here
    # example below
    /sbin/ethtool -K $IFACE gso off

    # Now deal with slaves
    # Pull out slave interface names from /proc/net/bonding/bondX
    SLAVES=$(/bin/grep -oP "Slave Interface: \K(eth[0-9]+)" /proc/net/bonding/$IFACE)
    for SLAVE in $SLAVES
    do
      # Do whatever you need with the slave here
      # example below
      /sbin/ethtool -K $SLAVE tso off gso off
    done
  fi
fi

Caveat: the contents of /proc/net/bonding/bondX may be different for different versions of RedHat/Fedora/CentOS to the one I was using when I wrote the script, so the command to pull out the slave interface names may not work.

3

Off-topic, for Ubuntu users who came here, like me, this as a note:

On Ubuntu, the textbook way to do it is to edit the /etc/network/interfaces file which in turn is read by the init.d/pre-up -up, etc. scripts. So an /etc/network/interfaces file might look like this:

auto eth0
iface eth0 inet static
pre-up /sbin/ethtool -s eth0 speed 10 duplex full

That's what the docs say, but it does not work. Might be that the parsing logic in the pre-up and up scripts is a bit dated and they don't parse out the required settings from the interfaces file. Don't know. At least, it was not working for me.

So the hack-ish but working solution for now is still to create/edit a local /etc/rc.local file and stating the command to be exuted there (but note that this may interrupt networking for a seconds after the interface has already been brought up). So having this:

ethtool -s eth0 speed 10 duplex full autoneg on

in /etc/rc.local is the working solution to slow down an interface as intended above.

On Ubuntu 17.04 and above

More recent Ubuntus use Systemd, and thus the rc.local file isn't necessarily executed upon reaching the 'start' runlevel, for example. The "rc-local" service has to be enabled. Although it seems to be by default, for backwards compatibility reasons, probably - make sure to check its status with sudo systemctl status rc-local

1
  • The pre-up directive worked for me on Linux Mint 17.3 for setting the TSO flag, thanks :)
    – Joril
    May 15, 2018 at 14:34
1

I found that setting this kind of configuration in /etc/network/interfaces actually works for Ubuntu (granted I used it for turning off large-receive-offload, but that shouldn't really matter):

auto eth1
iface eth1 inet static
    address xxx.xxx.xxx.xxx
    netmask xx
    pre-up /sbin/ethtool -K $IFACE lro off
1

For Ubuntu, you can do this by adding following line in /etc/network/interfaces:

auto eth0
iface eth0 inet static
[...]
post-up /sbin/ethtool -K eth0 tso off gso off gro off

post-up here will perform the given operation after bringing up the specific interface.

0

Yeah, it can't be done using configuration files for the moment. You can put up the command in /etc/init.d/rc.local and it should be done.

That file is executed at the last of the booting sequence and so tso would be turned off for the interface.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .