How to make ethtool setting persistent on br-lan

#1

I would like to automate these command instead of running it from putty.
ethtool -K eth0 tso off gso off gro off
ethtool -K br-lan tso off gso off gro off
ethtool -K ifb4br-lan tso off gso off gro off
I have tried applying these command in /etc/rc.local and also in /etc/init.d/sqm.
However, only eth0 changes are applied when I rebooted the router.
The changes for br-lan and ifb4br-lan are not applied automatically when the router starts up.
Can someone help please?
I have verified it by using ethtool -k and also tc -s qdisc.

0 Likes

WoL, ethtool and reboot problem
#2

br-lan is available after netifd sets it up

and ifb4br-lan may be available after the qos part ran

You could add a hotplug script.
I think it's under /etc/hotplug.d/iface (not sure if you need to make it executable).
Whenever an interface comes up, those scripts will run ( I am not sure atm which process runs them ; could be netifd )

When those scripts run, they have some env vars.
I think DEVICE should be available.
Check for ACTION as well.
I'd run the ethtool cmd on "ifup" action.
You could do ethtool $DEVICE

2 Likes

#3

Thank you for the response.
I don't know how to do that.
However you gave me an idea.
I have set a sleep time in rc.local
This seems an OK solution though not the best I guess.

0 Likes

#4

Ummm.
So that would be simple too.

cd /etc/hotplug.d/iface
vi 10-ethtool

in that file add

[ ifup = "$ACTION" ] || exit 0
[ -n "$DEVICE" ] || exit 0

if [ "$DEVICE" == eth0 ] || [ "$DEVICE" == br-lan ] || [ "$DEVICE" == ifb4br-lan ] ; then
      ethtool -K "$DEVICE" tso off gso off gro off
fi

or maybe you don't want/need the check for

if [ "$DEVICE" == eth0 ] || [ "$DEVICE" == br-lan ] || [ "$DEVICE" == ifb4br-lan ] ; then
2 Likes

#5

Did I do it wrong?
It seems to not have an effect on eth0 after reboot.

Code
[ ifup = "$ACTION" ] || exit 0
[ -n "$DEVICE" ] || exit 0
ethtool -K "$DEVICE" tso off gso off gro off
0 Likes

#6

It should be fine.
Maybe eth0 is initialized before the event processing takes place.

You could also add ethtool -K eth0 tso off gso off gro off explicitly there.

If you want to debug this, you could add some messages with logger
Something like

logger "Got event '$ACTION' for '$DEVICE'"

then you can check the logs with logread | grep "Got event"

1 Like

#7

Alright.
Thank you very much.

0 Likes

#8

ssh into your router
install ethtool if you already haven't

cd /etc
nano disable_offloads.sh

( copy the script below and paste into disable_offloads.sh using nano )

#!/bin/bash

# Disable Offloads for all interfaces

for DEV in $(ls /sys/class/net) ; do
echo -n "$DEV "
ethtool -K ${DEV} tso off
ethtool -K ${DEV} ufo off
ethtool -K ${DEV} gso off
ethtool -K ${DEV} gro off
ethtool -K ${DEV} lro off
ethtool -K ${DEV} rxvlan off
ethtool -K ${DEV} txvlan off
echo "Offloads Disabled"
done 

exit nano and save
chmod a+rx disable_offloads.sh ( this makes it writeable and readable for all)

nano edit /etc/rc.local

You mave have to adjust your sleep time to according to your estimated boot time

sleep 10 &&
sh /etc/disable_offloads.sh 
exit 0

(exit nano and save)

reboot && exit

test using:
ethtool -k (insert your device) | grep offload
fixed means at the nic level it cannot be changed
Note: by adding the sleep action we can wait for virtual devices to be created

2 Likes

#9

i use this as an init.d script

#!/bin/sh /etc/rc.common
#

START=99

start() {
	local count=1
	local eth
	while true ; do
		eth=`ls /sys/class/net | grep 'eth' | sed -n "$count"p`
		if [ "$eth" == "" ]; then
			break
		fi
		ethtool -K $eth tso off gso off gro off
		if [ $? -eq 0 ]; then
			logger -s "$eth offload turned off"
		else
			logger -s "[ERR] $eth offload turn off FAILED: '$?'"
		fi 
		count=$((count+1))
	done
}
0 Likes

#10

Super helpful, thanks.

0 Likes

#11

These instructions should be add to the wiki.

0 Likes

#12

How to make the ethtool init.d follow the state of sqm scripts? Such as a script that when sqm is started or restart/reloaded that ethtool init.d will run again?

0 Likes

#13

Here is what I came up with and works well
credit to shm0 for the ethtool script to start!
1.) /etc/init.d/ethtool

#!/bin/sh /etc/rc.common
#

START=99

start() {
	local count=1
	local eth
	while true ; do
		eth=`ls /sys/class/net | sed -n "$count"p`
		if [ "$eth" == "" ]; then
			break
		fi
		ethtool -K $eth gro off
		if [ $? -eq 0 ]; then
			logger -s "$eth offload turned off"
		else
			logger -s "[ERR] $eth offload turn off FAILED: '$?'"
		fi 
		count=$((count+1))
	done
}

stop() {
	local count=1
	local eth
	while true ; do
		eth=`ls /sys/class/net | sed -n "$count"p`
		if [ "$eth" == "" ]; then
			break
		fi
		ethtool -K $eth gro on
		if [ $? -eq 0 ]; then
			logger -s "$eth offload turned on"
		else
			logger -s "[ERR] $eth offload turn on FAILED: '$?'"
		fi 
		count=$((count+1))
	done
}

2.) Here we edit the existing /etc/init.d/sqm script ( make a backup of this file first)

#!/bin/sh /etc/rc.common

START=50
USE_PROCD=1

service_triggers()
{
	procd_add_reload_trigger "sqm"
}

reload_service()
{
	stop "$@"
	start "$@"
}

start_service()
{
	/usr/lib/sqm/run.sh start "$@"
	/etc/init.d/ethtool start "$@"
}

stop_service()
{
	/usr/lib/sqm/run.sh stop "$@"
	/etc/init.d/ethtool stop "$@"
}

boot()
{
	export SQM_VERBOSITY_MIN=5 # Silence errors
	start "$@"
}

The second script is edited to disable offloads for sqm=on or enable offloads when sqm=off. One could choose to not edit the sqm script and just run the ethtool script by itself as a service also.

0 Likes

#14

The script wasn't my work. i found it on this forum or some other forum.
i can't remember who wrote this. so please no credit here :smiley:

i made this script some weeks ago.
which does disable everything.

#!/bin/sh

sleep 15

function log()
{
	local status="$1"
	local feature="$2"
	local interface="$3"
	
	if [ $status -eq 0 ]; then		
		logger "[ETHTOOL] $feature: Disabled on $interface"
	fi
	
	if [ $status -eq 1 ]; then
		logger -s "[ETHTOOL] $feature: Failed to disable on $interface"
	fi
	
	if [ $status -gt 1 ]; then
		logger "[ETHTOOL] $feature: Nothing changed on $interface"
	fi

}
	
function disable_offloads()
{
	local interface="$1"
	local features
	local cmd
	
	# Check if we can change features
	if ethtool -k $interface 1>/dev/null 2>/dev/null;then
		
		# Filter whitespaces
		# Get only enabled/not fixed features
		# Filter features that are only changeable by global keyword
		# Filter empty lines
		# Cut to First colum
		features=$(ethtool -k "$interface" | awk '{$1=$1;print}' \
										   | grep -E '^.+: on$' \
										   | grep -v -E '^tx-checksum-.+$' \
										   | grep -v -E '^tx-scatter-gather.+$' \
										   | grep -v -E '^tx-tcp.+segmentation.+$' \
										   | grep -v -E '^tx-udp-fragmentation$' \
										   | grep -v -E '^tx-generic-segmentation$' \
										   | grep -v -E '^rx-gro$' \
										   | grep -v -E '^rx-gro$' \
										   | grep -v -E '^$' \
										   | cut -d: -f1)

		# Replace feature name by global key word
		features=$(echo "$features" | sed -e s/rx-checksumming/rx/ \
										  -e s/tx-checksumming/tx/ \
										  -e s/scatter-gather/sg/ \
										  -e s/tcp-segmentation-offload/tso/ \
										  -e s/udp-fragmentation-offload/ufo/ \
										  -e s/generic-segmentation-offload/gso/ \
										  -e s/generic-receive-offload/gro/ \
										  -e s/large-receive-offload/lro/ \
										  -e s/rx-vlan-offload/rxvlan/ \
										  -e s/tx-vlan-offload/txvlan/ \
										  -e s/ntuple-filters/ntuple/ \
										  -e s/receive-hashing/rxhash/)
										  
		# Check if we can disable someting								  
		if [ -z "$features" ]; then
			logger "[ETHTOOL] Offloads: Nothing changed on $interface"
			return 0
		fi
								  
		# Construct ethtool command line								  
		cmd="-K $interface"
			  
		for feature in $features; do			
			cmd="$cmd $feature off"
		done
		
		# Try to disable offloads		
		ethtool $cmd 1>/dev/null 2>/dev/null
		log $? "Offloads" "$interface"
		
	else
		log $? "Offloads" "$interface"	
	fi
}

function disable_flow_control()
{
	local interface="$1"
	local features
	local cmd
	
	# Check if we can change settings
	if ethtool -a $interface 1>/dev/null 2>/dev/null;then
										  
		# Construct ethtool command line								  
		cmd="-A $interface autoneg off tx off rx off"
		
		# Try to disable flow control				
		ethtool $cmd 1>/dev/null 2>/dev/null
		log $? "Flow Control" "$interface"
		
	else
		log $? "Flow Control" "$interface"		
	fi	
}

function disable_interrupt_moderation()
{
	local interface="$1"
	local features
	local cmd
	
	# Check if we can change settings
	if ethtool -c $interface 1>/dev/null 2>/dev/null;then
															
		# Construct ethtool command line								  
		cmd="-C $interface adaptive-tx off adaptive-rx off" 

		# Try to disable adaptive interrupt moderation				
		ethtool $cmd 1>/dev/null 2>/dev/null
		log $? "Adaptive Interrupt Moderation" "$interface"
		
		features=$(ethtool -c $interface | awk '{$1=$1;print}' \
										 | grep -v -E '^.+: 0$|Adaptive|Coalesce' \
										 | grep -v -E '^$' \
										 | cut -d: -f1)	
			
		# Check if we can disable someting								  
		if [ -z "$features" ]; then
			logger "[ETHTOOL] Interrupt Moderation: Nothing changed on $interface"
			return 0
		fi
		
		# Construct ethtool command line								  
		cmd="-C $interface"
			  
		for feature in $features; do			
			cmd="$cmd $feature 0"
		done
			
		# Try to disable interrupt Moderation		
		ethtool $cmd 1>/dev/null 2>/dev/null
		log $? "Interrupt Moderation" "$interface"
		
	else
		log $? "Interrupt Moderation" "$interface"		
	fi	
}

function main()
{

for interface in /sys/class/net/*; do
	interface=$(basename $interface)

	# Skip Loopback
	if [ $interface == lo ]; then
		continue
	fi
	
	disable_offloads "$interface"
	disable_flow_control "$interface"
	disable_interrupt_moderation "$interface"
	
done
}


main

Disabling offloads globally through sysctl would be much better.
Some distros have a feature to disable offloads in the network config directly.

1 Like

#15

Works as expected and appeals to my OCD!

0 Likes