qca-nss-ecm: refactor disable offload scripts

This commit is contained in:
Qosmio 2024-03-15 19:34:39 -04:00
parent 5900f254b9
commit 088f830466
4 changed files with 204 additions and 345 deletions

View File

@ -55,7 +55,7 @@ define KernelPackage/qca-nss-ecm/install
$(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm $(INSTALL_DATA) ./files/qca-nss-ecm.firewall $(1)/etc/firewall.d/qca-nss-ecm
$(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm $(INSTALL_BIN) ./files/qca-nss-ecm.init $(1)/etc/init.d/qca-nss-ecm
$(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/ $(INSTALL_BIN) ./files/ecm_dump.sh $(1)/usr/bin/
$(INSTALL_BIN) ./files/disable_offloads.sh $(1)/usr/bin/ $(INSTALL_BIN) ./files/disable_offloads.sh $(1)/lib/netifd/offload
$(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down $(INSTALL_BIN) ./files/on-demand-down $(1)/lib/netifd/offload/on-demand-down
$(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm $(INSTALL_DATA) ./files/qca-nss-ecm.uci $(1)/etc/config/ecm
$(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm $(INSTALL_DATA) ./files/qca-nss-ecm.defaults $(1)/etc/uci-defaults/99-qca-nss-ecm

View File

@ -2,186 +2,10 @@
[ "$ACTION" != "add" ] && exit [ "$ACTION" != "add" ] && exit
function log() . /lib/netifd/offload/disable_offloads.sh
{
local status="$1"
local feature="$2"
local interface="$3"
if [ $status -eq 0 ]; then if [ "$ACTION" = add ] && [ -n "$INTERFACE" ]; then
logger "[ethtool] $feature: disabled on $interface" disable_offload "$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
}
function interface_is_virtual()
{
local interface="$1"
[ -d /sys/devices/virtual/net/"$interface"/ ] || return 1
return 0
}
function get_base_interface()
{
local interface="$1"
echo "$interface" | grep -Eo '^[a-z]*[0-9]*' 2>/dev/null || return 1
return 0
}
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 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 '^rx-gro$' \
| grep -v -E '^$' \
| cut -d: -f1)
# Replace feature name by global keyword
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
}
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 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
}
function disable_interface_offloads() {
#local interface=$(get_base_interface "$1")
#{ [ -z "$interface" ] || interface_is_virtual "$interface"; } && exit 0
local interface="$1"
local disable_offloads="$(uci get ecm.@general[0].disable_offloads)"
if [ "$disable_offloads" -eq 1 ]; then
disable_offloads "$interface"
fi
local disable_flow_control="$(uci get ecm.@general[0].disable_flow_control)"
if [ "$disable_flow_control" -eq 1 ]; then
disable_flow_control "$interface"
fi
local disable_interrupt_moderation="$(uci get ecm.@general[0].disable_interrupt_moderation)"
if [ "$disable_interrupt_moderation" -eq 1 ]; then
disable_interrupt_moderation "$interface"
fi
}
if [ "$ACTION" = add ]; then
disable_interface_offloads "$INTERFACE"
fi fi
exit 0 exit 0

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# shellcheck disable=3014
# #
# Helper script which uses ethtool to disable (most) # Helper script which uses ethtool to disable (most)
# interface offloads, if possible. # interface offloads, if possible.
@ -6,9 +7,9 @@
# Reference: # Reference:
# https://forum.openwrt.org/t/how-to-make-ethtool-setting-persistent-on-br-lan/6433/14 # https://forum.openwrt.org/t/how-to-make-ethtool-setting-persistent-on-br-lan/6433/14
# #
. /lib/functions.sh
function log() log() {
{
local status="$1" local status="$1"
local feature="$2" local feature="$2"
local interface="$3" local interface="$3"
@ -26,28 +27,25 @@ function log()
fi fi
} }
function interface_is_virtual() interface_is_virtual() {
{
local interface="$1" local interface="$1"
[ -d /sys/devices/virtual/net/"$interface"/ ] || return 1 [ -d /sys/devices/virtual/net/"$interface"/ ] || return 1
return 0 return 0
} }
function get_base_interface() get_base_interface() {
{
local interface="$1" local interface="$1"
echo "$interface" | grep -Eo '^[a-z]*[0-9]*' 2>/dev/null || return 1 echo "$interface" | grep -Eo '^[a-z]*[0-9]*' 2> /dev/null || return 1
return 0 return 0
} }
function disable_offloads() disable_offloads() {
{
local interface="$1" local interface="$1"
local features local features
local cmd local cmd
# Check if we can change features # Check if we can change features
if ethtool -k $interface 1>/dev/null 2>/dev/null; then if ethtool -k $interface 1> /dev/null 2> /dev/null; then
# Filter whitespaces # Filter whitespaces
# Get only enabled/not fixed features # Get only enabled/not fixed features
@ -62,11 +60,11 @@ function disable_offloads()
| grep -v -E '^tx-udp-fragmentation$' \ | grep -v -E '^tx-udp-fragmentation$' \
| grep -v -E '^tx-generic-segmentation$' \ | grep -v -E '^tx-generic-segmentation$' \
| grep -v -E '^rx-gro$' \ | grep -v -E '^rx-gro$' \
| grep -v -E '^rx-gro$' \
| grep -v -E '^$' \ | grep -v -E '^$' \
| cut -d: -f1) | cut -d: -f1)
# Replace feature name by global keyword # Replace feature name by global keyword
echo $features
features=$(echo "$features" | sed -e s/rx-checksumming/rx/ \ features=$(echo "$features" | sed -e s/rx-checksumming/rx/ \
-e s/tx-checksumming/tx/ \ -e s/tx-checksumming/tx/ \
-e s/scatter-gather/sg/ \ -e s/scatter-gather/sg/ \
@ -82,7 +80,7 @@ function disable_offloads()
# Check if we can disable anything # Check if we can disable anything
if [ -z "$features" ]; then if [ -z "$features" ]; then
logger "[ethtool] offloads: no changes performed on $interface" logger "[ethtool] Offloads : no changes performed on $interface"
return 0 return 0
fi fi
@ -94,7 +92,7 @@ function disable_offloads()
done done
# Try to disable offloads # Try to disable offloads
ethtool $cmd 1>/dev/null 2>/dev/null ethtool $cmd 1> /dev/null 2> /dev/null
log $? "Offloads" "$interface" log $? "Offloads" "$interface"
else else
@ -102,20 +100,30 @@ function disable_offloads()
fi fi
} }
function disable_flow_control() disable_gro() {
{ local interface="$1"
local cmd
# Construct ethtool command line
cmd="-K $interface gro off"
# Try to disable flow control
ethtool $cmd 1> /dev/null 2> /dev/null
log $? "Generic Receive Offload" "$interface"
}
disable_flow_control() {
local interface="$1" local interface="$1"
local features
local cmd local cmd
# Check if we can change settings # Check if we can change settings
if ethtool -a $interface 1>/dev/null 2>/dev/null; then if ethtool -a $interface 1> /dev/null 2> /dev/null; then
# Construct ethtool command line # Construct ethtool command line
cmd="-A $interface autoneg off tx off rx off" cmd="-A $interface autoneg off tx off rx off"
# Try to disable flow control # Try to disable flow control
ethtool $cmd 1>/dev/null 2>/dev/null ethtool $cmd 1> /dev/null 2> /dev/null
log $? "Flow Control" "$interface" log $? "Flow Control" "$interface"
else else
@ -123,19 +131,18 @@ function disable_flow_control()
fi fi
} }
function disable_interrupt_moderation() disable_interrupt_moderation() {
{
local interface="$1" local interface="$1"
local features local features
local cmd local cmd
# Check if we can change settings # Check if we can change settings
if ethtool -c $interface 1>/dev/null 2>/dev/null; then if ethtool -c $interface 1> /dev/null 2> /dev/null; then
# Construct ethtool command line # Construct ethtool command line
cmd="-C $interface adaptive-tx off adaptive-rx off" cmd="-C $interface adaptive-tx off adaptive-rx off"
# Try to disable adaptive interrupt moderation # Try to disable adaptive interrupt moderation
ethtool $cmd 1>/dev/null 2>/dev/null ethtool $cmd 1> /dev/null 2> /dev/null
log $? "Adaptive Interrupt Moderation" "$interface" log $? "Adaptive Interrupt Moderation" "$interface"
features=$(ethtool -c $interface | awk '{$1=$1;print}' \ features=$(ethtool -c $interface | awk '{$1=$1;print}' \
@ -157,7 +164,7 @@ function disable_interrupt_moderation()
done done
# Try to disable interrupt Moderation # Try to disable interrupt Moderation
ethtool $cmd 1>/dev/null 2>/dev/null ethtool $cmd 1> /dev/null 2> /dev/null
log $? "Interrupt Moderation" "$interface" log $? "Interrupt Moderation" "$interface"
else else
@ -165,25 +172,37 @@ function disable_interrupt_moderation()
fi fi
} }
function main() disable_offload() {
{ local interface disable_flow_control disable_interrupt_moderation disable_offloads
for interface in /sys/class/net/*; do disable_offloads="$(uci_get ecm.@general[0].disable_offloads)"
interface=$(basename $interface) disable_gro="$(uci_get ecm.@general[0].disable_gro)"
disable_flow_control="$(uci_get ecm.@general[0].disable_flow_control)"
disable_interrupt_moderation="$(uci_get ecm.@general[0].disable_interrupt_moderation)"
#interface=$(get_base_interface "$interface") [ -z $1 ] && interface=$(echo /sys/class/net/*) || interface=$*
#{ [ -z "$interface" ] || interface_is_virtual "$interface"; } && exit 0
for i in $interface; do
i=${i##*/}
# Skip Loopback # Skip Loopback
if [ $interface == lo ]; then if [ $i == lo ]; then
continue continue
fi fi
disable_offloads "$interface" if [ "$disable_gro" -eq 1 ]; then
disable_flow_control "$interface" disable_gro "$i"
disable_interrupt_moderation "$interface" 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 done
} }
main
exit 0

View File

@ -41,8 +41,14 @@ get_front_end_mode() {
nss) nss)
echo '1' echo '1'
;; ;;
sfe)
echo '2'
;;
both)
echo '4'
;;
*) *)
echo 'uci_option_acceleration_engine is invalid' echo '0'
esac esac
} }
@ -60,10 +66,20 @@ disable_bridge_filtering() {
load_ecm() { load_ecm() {
[ -d /sys/module/ecm ] || { [ -d /sys/module/ecm ] || {
insmod ecm front_end_selection="$(get_front_end_mode)" local get_front_end_mode
get_front_end_mode="$(get_front_end_mode)"
insmod ecm front_end_selection="$get_front_end_mode"
echo 1 > /sys/kernel/debug/ecm/ecm_classifier_default/accel_delay_pkts echo 1 > /sys/kernel/debug/ecm/ecm_classifier_default/accel_delay_pkts
} }
. /lib/netifd/offload/disable_offloads.sh
disable_offload
#Flushout stale accelerated connections if any
echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all
echo f > /proc/net/nf_conntrack
# Set conntrack event mode to 1 for 6.1 kernel to get the conntrack events from ECM # Set conntrack event mode to 1 for 6.1 kernel to get the conntrack events from ECM
local kernel_major local kernel_major
kernel_major=$(uname -r |cut -d. -f1) kernel_major=$(uname -r |cut -d. -f1)
@ -93,10 +109,10 @@ unload_ecm() {
# Defunct the connections # Defunct the connections
# #
echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all
sleep 5 echo f > /proc/net/nf_conntrack
rmmod ecm
sleep 1 sleep 1
rmmod ecm
fi fi
} }