#!/bin/sh /etc/rc.common # shellcheck disable=3043,3060,2086,2034 # # Copyright (c) 2014, 2019-2020 The Linux Foundation. All rights reserved. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # The shebang above has an extra space intentionally to avoid having # openwrt build scripts automatically enable this package starting # at boot. START=26 USE_PROCD=1 sysctl_update() { local name value file name=${1//\//\\/} value=${2//\//\\/} file=${3:-/etc/sysctl.d/qca-nss-ecm.conf} if [ -r "/proc/sys/${name//./\/}" ]; then sed -i -e '/^#\?\(\s*'"${name}"'\s*=\s*\).*/{s//\1'"${value}"'/;:a;n;ba;q}' \ -e '$a'"${name}"'='"${value}" "${file}" sysctl -w ${name}=${value} else # If the sysctl value is not available but it is found in the file, disable it to avoid # sysctl throwing warnings if grep -qE '^#?\s*'"${name}\s*?=" "${file}"; then sed -i -e '/^#\?\(\s*'"${name}"'\s*=\s*\).*/{s//\#\1'"${value}"'/;:a;n;ba;q}' \ -e '$a'"#${name}"'='"${value}" "${file}" fi fi } get_front_end_mode() { config_load "ecm" config_get front_end global acceleration_engine "auto" # shellcheck disable=2154 case $front_end in auto) echo '0' ;; nss) echo '1' ;; sfe) echo '2' ;; both) echo '4' ;; *) echo '0' ;; esac } disable_packet_steering() { uci -q set network.globals.packet_steering=0 && uci commit network.globals.packet_steering uci -q del network.globals.steering_flows && uci commit network.globals.steering_flows if [ -e "/usr/libexec/platform/packet-steering.sh" ]; then /usr/libexec/platform/packet-steering.sh 0 else /usr/libexec/network/packet-steering.uc -l 0 0 fi } disable_bridge_filtering() { sysctl_update net.bridge.bridge-nf-call-arptables 0 sysctl_update net.bridge.bridge-nf-call-iptables 0 sysctl_update net.bridge.bridge-nf-call-ip6tables 0 } enable_bridge_filtering() { # If bridge filtering is enabled, apply and persist the sysctl flags config_load ecm config_get enable_bridge_filtering general enable_bridge_filtering 0 # shellcheck disable=2154 if [ "$enable_bridge_filtering" -eq 1 ]; then sysctl_update net.bridge.bridge-nf-call-arptables 1 sysctl_update net.bridge.bridge-nf-call-iptables 1 sysctl_update net.bridge.bridge-nf-call-ip6tables 1 else disable_bridge_filtering fi } set_front_end() { local get_front_end_mode=${1:-0} local module_conf=/etc/modules.conf [ ! -r "$module_conf" ] && touch "$module_conf" # If "options ecm" exists, modify or append front_end_selection if grep -q "^options ecm" "$module_conf"; then if grep -q "front_end_selection=" "$module_conf"; then sed -i -E "s/(options ecm.*)front_end_selection=[0-9]+/\1front_end_selection=$get_front_end_mode/" "$module_conf" else # Append front_end_selection if missing sed -i -E "s/^(options ecm.*)/\1 front_end_selection=$get_front_end_mode/" "$module_conf" fi else # Add new "options ecm" line echo "options ecm front_end_selection=$get_front_end_mode" >> "$module_conf" fi } load_ecm() { [ -d /sys/module/ecm ] || { local get_front_end_mode get_front_end_mode="$(get_front_end_mode)" modinfo ecm | awk '/depends/{gsub(",","\n",$NF);print $NF}' | xargs -r -n 1 modprobe set_front_end $get_front_end_mode modprobe ecm echo 1 > /sys/kernel/debug/ecm/ecm_classifier_default/accel_delay_pkts } # shellcheck disable=1091 . /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) if [ "$kernel_major" -eq 6 ]; then echo 1 > /proc/sys/net/netfilter/nf_conntrack_events fi } unload_ecm() { disable_bridge_filtering # Change it back to 6.1 linux's default setting local kernel_major kernel_major="$(uname -r | cut -d. -f1)" if [ "$kernel_major" -eq 6 ]; then echo 2 > /proc/sys/net/netfilter/nf_conntrack_events fi if [ -d /sys/module/ecm ]; then # # Stop ECM frontends # echo 1 > /sys/kernel/debug/ecm/front_end_ipv4_stop echo 1 > /sys/kernel/debug/ecm/front_end_ipv6_stop # # Defunct the connections # echo 1 > /sys/kernel/debug/ecm/ecm_db/defunct_all echo f > /proc/net/nf_conntrack sleep 1 rmmod ecm fi } service_triggers() { procd_add_reload_trigger "network" procd_add_reload_trigger "packet_steering" } reload_service() { disable_packet_steering } start_service() { load_ecm disable_packet_steering # Only enable bridge filtering if using deprecated fw3 if [ ! -r /sbin/fw4 ]; then enable_bridge_filtering else disable_bridge_filtering fi # If the acceleration engine is NSS, enable wifi redirect [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=1 if [ -d /sys/module/qca_ovsmgr ]; then insmod ecm_ovs fi } stop_service() { # If ECM is already not loaded, just return if [ ! -d /sys/module/ecm ]; then return fi # If the acceleration engine is NSS, disable wifi redirect [ -d /sys/kernel/debug/ecm/ecm_nss_ipv4 ] && sysctl -w dev.nss.general.redirect=0 if [ -d /sys/module/ecm_ovs ]; then rmmod ecm_ovs fi unload_ecm }