Persistent ethtool TSO Configuration: Maintaining TCP Segmentation Offload Settings Across Reboots in CentOS


1 views

When working with network tuning on Linux systems, many admins encounter this frustrating scenario: you carefully configure your NIC parameters using ethtool, only to find all settings reverted after the next reboot. This is particularly problematic when disabling TCP Segmentation Offload (TSO) for performance tuning or debugging purposes.

Running ethtool -K eth0 tso off does indeed disable TSO immediately, but these changes only affect the runtime configuration. The Linux network subsystem doesn't automatically persist these settings to survive reboots.

Method 1: Network Manager Configuration (Modern Systems)

For newer CentOS/RHEL versions (7+) with NetworkManager:

nmcli connection modify eth0 ethtool.feature-tso off
nmcli connection up eth0

Method 2: /etc/sysconfig/network-scripts (Traditional Approach)

For CentOS 5 specifically, edit your interface configuration:

vi /etc/sysconfig/network-scripts/ifcfg-eth0

Add or modify this line:

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

Method 3: rc.local Fallback

As a last resort, you can add the command to /etc/rc.local:

echo "ethtool -K eth0 tso off" >> /etc/rc.local
chmod +x /etc/rc.local

After implementing any method, verify with:

ethtool -k eth0 | grep tcp-segmentation-offload

Common issues include:

  • Interface name mismatch (eth0 vs actual interface)
  • Syntax errors in configuration files
  • Missing permissions for rc.local execution

On systemd-based systems, create a service:

cat << EOF > /etc/systemd/system/ethtool-tso.service
[Unit]
Description=Disable TSO for eth0
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/ethtool -K eth0 tso off

[Install]
WantedBy=multi-user.target
EOF

systemctl enable ethtool-tso.service
systemctl start ethtool-tso.service

When working with network interface tuning on Linux systems, many sysadmins discover that ethtool changes don't survive reboots. The command:

ethtool -K eth0 tso off

only affects the current runtime configuration. This behavior occurs because ethtool modifies settings in the running kernel's network stack rather than writing to persistent configuration files.

The classic solution involves adding the command to /etc/rc.local:

#!/bin/sh
ethtool -K eth0 tso off
exit 0

While functional, this method has several drawbacks:

  • Execution timing isn't guaranteed relative to network service startup
  • Limited error handling capabilities
  • Becomes unwieldy with multiple interface configurations

For systems using NetworkManager (common in modern CentOS/RHEL), create a dispatcher script:

#!/bin/bash
# /etc/NetworkManager/dispatcher.d/99-ethtool-settings

INTERFACE=$1
STATUS=$2

if [ "$STATUS" = "up" ] && [ "$INTERFACE" = "eth0" ]; then
    /sbin/ethtool -K $INTERFACE tso off
fi

Make the script executable:

chmod +x /etc/NetworkManager/dispatcher.d/99-ethtool-settings

For systems using systemd-networkd, create a service unit:

# /etc/systemd/system/ethtool.service
[Unit]
Description=Ethtool settings
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/ethtool -K eth0 tso off

[Install]
WantedBy=multi-user.target

Then enable it:

systemctl enable ethtool.service

Another robust method uses udev rules:

# /etc/udev/rules.d/99-persistent-net.rules
ACTION=="add", SUBSYSTEM=="net", KERNEL=="eth0", RUN+="/sbin/ethtool -K eth0 tso off"

Reload udev rules:

udevadm control --reload-rules

After implementing any solution, verify with:

ethtool -k eth0 | grep tcp-segmentation-offload

Expected output:

tcp-segmentation-offload: off

Common issues to check:

  • Script permissions (must be executable)
  • Interface name changes (use consistent naming)
  • Timing issues (add sleep if needed)