diff --git a/qca-nss-ecm/Makefile b/qca-nss-ecm/Makefile index 64167a5..720dd51 100644 --- a/qca-nss-ecm/Makefile +++ b/qca-nss-ecm/Makefile @@ -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_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/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_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 diff --git a/qca-nss-ecm/files/disable_offloads.hotplug b/qca-nss-ecm/files/disable_offloads.hotplug index 01c5647..585aa57 100755 --- a/qca-nss-ecm/files/disable_offloads.hotplug +++ b/qca-nss-ecm/files/disable_offloads.hotplug @@ -2,186 +2,10 @@ [ "$ACTION" != "add" ] && exit -function log() -{ - local status="$1" - local feature="$2" - local interface="$3" +. /lib/netifd/offload/disable_offloads.sh - 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 -} - -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" +if [ "$ACTION" = add ] && [ -n "$INTERFACE" ]; then + disable_offload "$INTERFACE" fi exit 0 diff --git a/qca-nss-ecm/files/disable_offloads.sh b/qca-nss-ecm/files/disable_offloads.sh index 9f8394f..b93cf0c 100755 --- a/qca-nss-ecm/files/disable_offloads.sh +++ b/qca-nss-ecm/files/disable_offloads.sh @@ -1,4 +1,5 @@ #!/bin/sh +# shellcheck disable=3014 # # Helper script which uses ethtool to disable (most) # interface offloads, if possible. @@ -6,184 +7,202 @@ # Reference: # https://forum.openwrt.org/t/how-to-make-ethtool-setting-persistent-on-br-lan/6433/14 # +. /lib/functions.sh -function log() -{ - local status="$1" - local feature="$2" - local interface="$3" +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 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 -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 + 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 +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 +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 +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 + # 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) + # 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 - 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/) + # 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 + # 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" + # 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 main() -{ - for interface in /sys/class/net/*; do - interface=$(basename $interface) - - #interface=$(get_base_interface "$interface") - #{ [ -z "$interface" ] || interface_is_virtual "$interface"; } && exit 0 - - # Skip Loopback - if [ $interface == lo ]; then - continue - fi - - disable_offloads "$interface" - disable_flow_control "$interface" - disable_interrupt_moderation "$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 } -main +disable_gro() { + local interface="$1" + local cmd -exit 0 + # 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 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() { + local interface disable_flow_control disable_interrupt_moderation disable_offloads + disable_offloads="$(uci_get ecm.@general[0].disable_offloads)" + 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)" + + [ -z $1 ] && interface=$(echo /sys/class/net/*) || interface=$* + + for i in $interface; do + i=${i##*/} + + # Skip Loopback + if [ $i == lo ]; then + continue + fi + + if [ "$disable_gro" -eq 1 ]; then + disable_gro "$i" + 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 +} diff --git a/qca-nss-ecm/files/qca-nss-ecm.init b/qca-nss-ecm/files/qca-nss-ecm.init index e67608d..c359483 100644 --- a/qca-nss-ecm/files/qca-nss-ecm.init +++ b/qca-nss-ecm/files/qca-nss-ecm.init @@ -41,8 +41,14 @@ get_front_end_mode() { nss) echo '1' ;; + sfe) + echo '2' + ;; + both) + echo '4' + ;; *) - echo 'uci_option_acceleration_engine is invalid' + echo '0' esac } @@ -60,10 +66,20 @@ disable_bridge_filtering() { load_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 } + . /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 local kernel_major kernel_major=$(uname -r |cut -d. -f1) @@ -93,10 +109,10 @@ unload_ecm() { # Defunct the connections # echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all - sleep 5 + echo f > /proc/net/nf_conntrack - rmmod ecm sleep 1 + rmmod ecm fi }