Make qdisc modes apply to active interfaces

This commit is contained in:
byjoey
2026-06-14 12:22:57 +08:00
parent ef00d937e9
commit e482610409
3 changed files with 125 additions and 27 deletions
+2
View File
@@ -159,6 +159,8 @@ modinfo tcp_bbr 2>/dev/null | grep '^version:'
/etc/sysctl.d/99-joeyblog.conf /etc/sysctl.d/99-joeyblog.conf
``` ```
脚本不仅会写入 `net.core.default_qdisc`,还会尝试把当前默认路由出口网卡的 root qdisc 立即替换为所选算法,避免只对新建队列生效、当前网卡实际仍保持旧队列。
对于需要模块加载的队列算法,脚本会尝试加载对应 `sch_*` 模块,并在需要时写入: 对于需要模块加载的队列算法,脚本会尝试加载对应 `sch_*` 模块,并在需要时写入:
```text ```text
+111 -23
View File
@@ -509,28 +509,123 @@ clear_network_optimizations() {
load_qdisc_module() { load_qdisc_module() {
local qdisc_name="$1" local qdisc_name="$1"
local module_name="sch_$qdisc_name" local module_name="sch_$qdisc_name"
local previous_qdisc
local applied_qdisc
previous_qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || true)
if ! lsmod | grep -q "^${module_name//-/_}"; then
sudo modprobe "$module_name" 2>/dev/null || true
fi
# 检查队列算法是否已可用(通过尝试读取当前可用的 qdisc)
# 如果 sysctl 能成功设置,说明模块已存在
if sudo sysctl -w net.core.default_qdisc="$qdisc_name" > /dev/null 2>&1; then if sudo sysctl -w net.core.default_qdisc="$qdisc_name" > /dev/null 2>&1; then
# 恢复原设置 applied_qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || true)
sudo sysctl -w net.core.default_qdisc="$CURRENT_QDISC" > /dev/null 2>&1 if [[ -n "$previous_qdisc" ]]; then
return 0 sudo sysctl -w net.core.default_qdisc="$previous_qdisc" > /dev/null 2>&1 || true
fi
if [[ "$applied_qdisc" == "$qdisc_name" ]]; then
return 0
fi
fi fi
# 检查模块是否已加载
if lsmod | grep -q "^${module_name//-/_}"; then
return 0
fi
# 模块不存在,尝试加载
echo -e "\033[36m正在加载内核模块 $module_name...\033[0m" echo -e "\033[36m正在加载内核模块 $module_name...\033[0m"
if sudo modprobe "$module_name" 2>/dev/null; then if sudo modprobe "$module_name" 2>/dev/null; then
echo -e "\033[1;32m✔ 模块 $module_name 加载成功\033[0m" if sudo sysctl -w net.core.default_qdisc="$qdisc_name" > /dev/null 2>&1; then
applied_qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || true)
if [[ -n "$previous_qdisc" ]]; then
sudo sysctl -w net.core.default_qdisc="$previous_qdisc" > /dev/null 2>&1 || true
fi
if [[ "$applied_qdisc" == "$qdisc_name" ]]; then
echo -e "\033[1;32m✔ 队列算法 $qdisc_name 可用\033[0m"
return 0
fi
fi
fi
echo -e "\033[33m⚠ 队列算法 $qdisc_name 不可用,可能当前内核缺少 $module_name\033[0m"
return 1
}
# 函数:确保可以操作当前网卡队列
ensure_iproute2_tools() {
if command -v ip > /dev/null 2>&1 && command -v tc > /dev/null 2>&1; then
return 0 return 0
fi
echo -e "\033[36m正在安装 iproute2,用于立即切换当前网卡队列算法...\033[0m"
sudo apt-get update > /dev/null 2>&1 || true
if sudo apt-get install -y iproute2 > /dev/null 2>&1; then
return 0
fi
echo -e "\033[33m⚠ iproute2 安装失败,当前网卡队列无法立即替换;仍会写入 default_qdisc。\033[0m"
return 1
}
# 函数:获取默认路由出口网卡
get_default_route_interfaces() {
{
ip -o route show default 2>/dev/null || true
ip -o -6 route show default 2>/dev/null || true
} | awk '{for (i = 1; i <= NF; i++) if ($i == "dev") print $(i + 1)}' | sort -u
}
# 函数:让当前默认出口网卡立即切换队列算法
apply_qdisc_to_active_interfaces() {
local qdisc_name="$1"
local interfaces=()
local iface
local applied=0
local failed=0
if ! ensure_iproute2_tools; then
return 0
fi
while IFS= read -r iface; do
[[ -n "$iface" ]] && interfaces+=("$iface")
done < <(get_default_route_interfaces)
if [[ ${#interfaces[@]} -eq 0 ]]; then
echo -e "\033[33m⚠ 未找到默认路由出口网卡,已仅设置 default_qdisc。\033[0m"
return 0
fi
for iface in "${interfaces[@]}"; do
if sudo tc qdisc replace dev "$iface" root "$qdisc_name" 2>/dev/null; then
echo -e "\033[1;32m✔ 当前网卡 $iface 已切换为 $qdisc_name\033[0m"
applied=1
else
echo -e "\033[33m⚠ 当前网卡 $iface 切换 $qdisc_name 失败\033[0m"
failed=1
fi
done
if [[ "$applied" -eq 1 ]]; then
return 0
fi
[[ "$failed" -eq 1 ]] && return 1
return 0
}
# 函数:根据队列算法是否为模块,决定是否写入开机加载
persist_qdisc_module() {
local qdisc_name="$1"
local module_name="sch_$qdisc_name"
if [[ "$qdisc_name" == "fq" ]]; then
sudo rm -f "$MODULES_CONF"
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存啦~\033[0m"
return 0
fi
if modinfo "$module_name" > /dev/null 2>&1 || lsmod | grep -q "^${module_name//-/_}"; then
echo "$module_name" | sudo tee "$MODULES_CONF" > /dev/null
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存,模块 $module_name 将在开机时自动加载~\033[0m"
else else
echo -e "\033[33m⚠ 模块 $module_name 加载失败,可能内核不支持\033[0m" sudo rm -f "$MODULES_CONF"
return 1 echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存;$qdisc_name 可能为内置队列,无需写入模块加载配置~\033[0m"
fi fi
} }
@@ -619,6 +714,7 @@ ask_to_save() {
echo -e "\033[36m正在应用配置...\033[0m" echo -e "\033[36m正在应用配置...\033[0m"
sudo sysctl -w net.core.default_qdisc="$QDISC" > /dev/null 2>&1 sudo sysctl -w net.core.default_qdisc="$QDISC" > /dev/null 2>&1
sudo sysctl -w net.ipv4.tcp_congestion_control="$ALGO" > /dev/null 2>&1 sudo sysctl -w net.ipv4.tcp_congestion_control="$ALGO" > /dev/null 2>&1
apply_qdisc_to_active_interfaces "$QDISC" || return 1
# 验证是否生效 # 验证是否生效
NEW_QDISC=$(sysctl -n net.core.default_qdisc 2>/dev/null) NEW_QDISC=$(sysctl -n net.core.default_qdisc 2>/dev/null)
@@ -644,15 +740,7 @@ ask_to_save() {
echo "net.ipv4.tcp_congestion_control=$ALGO" | sudo tee -a "$SYSCTL_CONF" > /dev/null echo "net.ipv4.tcp_congestion_control=$ALGO" | sudo tee -a "$SYSCTL_CONF" > /dev/null
sudo sysctl --system > /dev/null 2>&1 sudo sysctl --system > /dev/null 2>&1
# 配置模块开机自动加载(fq 和 fq_codel 是内置的不需要) persist_qdisc_module "$QDISC"
if [[ "$QDISC" == "fq" || "$QDISC" == "fq_codel" ]]; then
# fq 和 fq_codel 是内核内置的,删除旧的模块配置文件
sudo rm -f "$MODULES_CONF"
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存啦~\033[0m"
else
echo "sch_$QDISC" | sudo tee "$MODULES_CONF" > /dev/null
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存,模块 sch_$QDISC 将在开机时自动加载~\033[0m"
fi
else else
echo -e "\033[33m(⌒_⌒;) 好吧,没有永久保存,重启后会恢复原设置呢~\033[0m" echo -e "\033[33m(⌒_⌒;) 好吧,没有永久保存,重启后会恢复原设置呢~\033[0m"
fi fi
+9 -1
View File
@@ -22,6 +22,10 @@ apply_policy_config() {
scripts/config --enable NET_SCH_DEFAULT scripts/config --enable NET_SCH_DEFAULT
scripts/config --enable NET_SCH_FQ scripts/config --enable NET_SCH_FQ
scripts/config --module NET_SCH_FQ_CODEL
scripts/config --module NET_SCH_PIE
scripts/config --module NET_SCH_FQ_PIE
scripts/config --module NET_SCH_CAKE
scripts/config --disable DEFAULT_FQ_CODEL scripts/config --disable DEFAULT_FQ_CODEL
scripts/config --disable DEFAULT_PFIFO_FAST scripts/config --disable DEFAULT_PFIFO_FAST
scripts/config --enable DEFAULT_FQ scripts/config --enable DEFAULT_FQ
@@ -89,6 +93,10 @@ validate_config() {
require_config_line 'CONFIG_DEFAULT_BBR=y' 'CONFIG_DEFAULT_BBR is not enabled.' require_config_line 'CONFIG_DEFAULT_BBR=y' 'CONFIG_DEFAULT_BBR is not enabled.'
require_config_line 'CONFIG_DEFAULT_TCP_CONG="bbr"' 'CONFIG_DEFAULT_TCP_CONG is not bbr.' require_config_line 'CONFIG_DEFAULT_TCP_CONG="bbr"' 'CONFIG_DEFAULT_TCP_CONG is not bbr.'
require_config_line 'CONFIG_NET_SCH_FQ=y' 'CONFIG_NET_SCH_FQ is not built in.' require_config_line 'CONFIG_NET_SCH_FQ=y' 'CONFIG_NET_SCH_FQ is not built in.'
require_config_line 'CONFIG_NET_SCH_FQ_CODEL=m' 'CONFIG_NET_SCH_FQ_CODEL is not module-enabled.'
require_config_line 'CONFIG_NET_SCH_PIE=m' 'CONFIG_NET_SCH_PIE is not module-enabled.'
require_config_line 'CONFIG_NET_SCH_FQ_PIE=m' 'CONFIG_NET_SCH_FQ_PIE is not module-enabled.'
require_config_line 'CONFIG_NET_SCH_CAKE=m' 'CONFIG_NET_SCH_CAKE is not module-enabled.'
require_config_line 'CONFIG_NET_SCH_DEFAULT=y' 'CONFIG_NET_SCH_DEFAULT is not enabled.' require_config_line 'CONFIG_NET_SCH_DEFAULT=y' 'CONFIG_NET_SCH_DEFAULT is not enabled.'
require_config_line 'CONFIG_DEFAULT_FQ=y' 'CONFIG_DEFAULT_FQ is not enabled.' require_config_line 'CONFIG_DEFAULT_FQ=y' 'CONFIG_DEFAULT_FQ is not enabled.'
require_config_line 'CONFIG_DEFAULT_NET_SCH="fq"' 'CONFIG_DEFAULT_NET_SCH is not fq.' require_config_line 'CONFIG_DEFAULT_NET_SCH="fq"' 'CONFIG_DEFAULT_NET_SCH is not fq.'
@@ -98,7 +106,7 @@ validate_config() {
require_config_line 'CONFIG_IP_NF_FILTER=m' 'CONFIG_IP_NF_FILTER is not module-enabled.' require_config_line 'CONFIG_IP_NF_FILTER=m' 'CONFIG_IP_NF_FILTER is not module-enabled.'
require_config_line 'CONFIG_IP_NF_TARGET_MASQUERADE=m' 'CONFIG_IP_NF_TARGET_MASQUERADE is not module-enabled.' require_config_line 'CONFIG_IP_NF_TARGET_MASQUERADE=m' 'CONFIG_IP_NF_TARGET_MASQUERADE is not module-enabled.'
grep -E 'CONFIG_(DEBUG_INFO_NONE|TCP_CONG_BBR|DEFAULT_BBR|DEFAULT_TCP_CONG|NET_SCH_DEFAULT|NET_SCH_FQ|DEFAULT_FQ|DEFAULT_NET_SCH|NETFILTER_XTABLES_LEGACY|IP_NF_IPTABLES_LEGACY|IP_NF_NAT|IP_NF_FILTER|IP_NF_TARGET_MASQUERADE|IP6_NF_IPTABLES_LEGACY|IP6_NF_NAT|IP6_NF_FILTER)=' .config grep -E 'CONFIG_(DEBUG_INFO_NONE|TCP_CONG_BBR|DEFAULT_BBR|DEFAULT_TCP_CONG|NET_SCH_DEFAULT|NET_SCH_FQ|NET_SCH_FQ_CODEL|NET_SCH_PIE|NET_SCH_FQ_PIE|NET_SCH_CAKE|DEFAULT_FQ|DEFAULT_NET_SCH|NETFILTER_XTABLES_LEGACY|IP_NF_IPTABLES_LEGACY|IP_NF_NAT|IP_NF_FILTER|IP_NF_TARGET_MASQUERADE|IP6_NF_IPTABLES_LEGACY|IP6_NF_NAT|IP6_NF_FILTER)=' .config
} }
case "$arch" in case "$arch" in