mirror of
https://github.com/breeze303/nss-packages.git
synced 2025-12-16 08:44:52 +00:00
New option added to ecm config: `disable_gro_list` This config option defaults to '1' (AKA disable rx-gro-list) `rx-gro-list` is enabled by default in mainline OpenWrt, however it is very bug prone, and causes various issues related to UDP traffic (i.e DHCP, WireGuard, DNS, etc.) This option is not explicitly required. If a user sets this to '0', a warning will be shown in the logs everytime ECM is started. Signed-off-by: Sean Khan <datapronix@protonmail.com>
221 lines
5.9 KiB
Bash
221 lines
5.9 KiB
Bash
#!/bin/sh
|
|
# shellcheck disable=3014,3043,2086,1091,2154
|
|
#
|
|
# Helper script which uses ethtool to disable (most)
|
|
# interface offloads, if possible.
|
|
#
|
|
# Reference:
|
|
# https://forum.openwrt.org/t/how-to-make-ethtool-setting-persistent-on-br-lan/6433/14
|
|
#
|
|
. /lib/functions.sh
|
|
|
|
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: no changes performed on $interface"
|
|
fi
|
|
}
|
|
|
|
interface_is_virtual() {
|
|
local interface="$1"
|
|
[ -d /sys/devices/virtual/net/"$interface"/ ] || return 1
|
|
return 0
|
|
}
|
|
|
|
get_base_interface() {
|
|
local interface="$1"
|
|
echo "$interface" | grep -Eo '^[a-z]*[0-9]*' 2> /dev/null || return 1
|
|
return 0
|
|
}
|
|
|
|
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 column
|
|
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 '^$' \
|
|
| cut -d: -f1)
|
|
|
|
# Replace feature name by global keyword
|
|
echo $features
|
|
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 anything
|
|
if [ -z "$features" ]; then
|
|
logger "[ethtool] Offloads : no changes performed 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
|
|
}
|
|
|
|
disable_feature() {
|
|
local feature="$1"
|
|
local interface="$2"
|
|
local cmd
|
|
|
|
# Construct ethtool command line
|
|
cmd="-K $interface $feature off"
|
|
|
|
# Try to disable flow control
|
|
ethtool $cmd 1> /dev/null 2> /dev/null
|
|
log $? "Disabling feature: $feature" "($interface)"
|
|
}
|
|
|
|
disable_flow_control() {
|
|
local interface="$1"
|
|
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
|
|
}
|
|
|
|
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 anything
|
|
if [ -z "$features" ]; then
|
|
logger "[ethtool] Interrupt Moderation: no changes performed 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
|
|
}
|
|
|
|
disable_offload() {
|
|
config_load ecm
|
|
|
|
config_get_bool enable_bridge_filtering general enable_bridge_filtering 0
|
|
config_get_bool disable_offloads general disable_offloads 0
|
|
config_get_bool disable_flow_control general disable_flow_control 0
|
|
config_get_bool disable_interrupt_moderation general disable_interrupt_moderation 0
|
|
config_get_bool disable_gro general disable_gro 0
|
|
config_get_bool disable_gro_list general disable_gro_list 1
|
|
|
|
[ -z $1 ] && interface=$(echo /sys/class/net/*) || interface=$*
|
|
|
|
for iface in $interface; do
|
|
i=${iface##*/}
|
|
|
|
# Skip Loopback and Bonding Masters
|
|
if [ $i == lo ] || [ -f $iface ]; then
|
|
continue
|
|
fi
|
|
|
|
if [ "$disable_gro" -eq 1 ]; then
|
|
disable_feature gro "$i"
|
|
fi
|
|
|
|
if [ "$disable_gro_list" -eq 1 ]; then
|
|
disable_feature "rx-gro-list" "$i"
|
|
else
|
|
logger -p user.warn -s "[ethtool] Enabling rx-gro-list (GRO Fraglist) will break UDP related traffic. (e.g. DNS, DHCP)"
|
|
logger -p user.warn -s "[ethtool] Leave this feature enabled unless you know what you are doing."
|
|
logger -p user.warn -s "[ethtool] Run \`uci set ecm.general.disable_gro_list=1 && uci commit ecm && service qca-nss-ecm restart\`"
|
|
fi
|
|
|
|
if [ "$disable_offloads" -eq 1 ]; then
|
|
disable_offloads "$i"
|
|
fi
|
|
|
|
if [ "$disable_flow_control" -eq 1 ]; then
|
|
disable_flow_control "$i"
|
|
fi
|
|
|
|
if [ "$disable_interrupt_moderation" -eq 1 ]; then
|
|
disable_interrupt_moderation "$i"
|
|
fi
|
|
done
|
|
}
|