update 2026-07-28 01:38:11

This commit is contained in:
action committed 2026-07-28 01:38:11 +08:00
1 parent 20b786ab77
commit 25d570431d
6243 files changed
+2850542

No files matched your search

+379
View File
@@ -0,0 +1,379 @@
#!/bin/bash
# Copyright (C) 2006 OpenWrt.org
# Copyright 2022-2025 sirpdboy <herboy2008@gmail.com>
crrun=$1
crid=$2
NAME=eqosplus
IDLIST="/var/$NAME.idlist"
LOCK="/var/lock/$NAME.lock"
TMPID="/var/$NAME.tmpid"
LOG="/var/$NAME_log.log"
# idlist=`uci show $NAME | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]' `
if [ x$(uci get $NAME.@$NAME[0].ifname 2>/dev/null) = 'x1' ]; then
ifname=$(uci -q get network.lan.ifname)
[ "x$ifname" = "x" ] && ifname="device" || ifname="ifname"
dev=$(uci -q get network.wan.$ifname)
[ ! "$dev" ] && dev=br-lan
else
dev=$(uci -q get $NAME.@$NAME[0].ifname 2>/dev/null)
[ ! "$dev" ] && dev=br-lan
fi
bin_nft=$(which nft)
bin_tc=$(which tc)
bin_ip=$(which ip)
DEBUG=1
nft_type() {
if command -v nft >/dev/null; then
nftables_ver="true"
fi
}
# Debug functions
dbg_nft() {
[ "${DEBUG:-0}" -eq 0 ] || echo "DEBUG: nft $*"
$bin_nft "$@"
}
dbg_tc() {
[ "${DEBUG:-0}" -eq 0 ] || echo "DEBUG: tc $*"
$bin_tc "$@"
}
dbg_ip() {
[ "${DEBUG:-0}" -eq 0 ] || echo "DEBUG: ip $*"
$bin_ip "$@"
}
is_macaddr() {
ret=1
if echo "$1" | grep -qE '^([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2}$'; then
ret=0
fi
return $ret
}
# 数值比较函数
is_gt_zero() {
local value=$1
# 使用bc进行浮点数比较
echo "$value > 0" | bc -l 2>/dev/null | grep -q 1
}
# 转换为kbit
to_kbit() {
local mb=$1
# MB/s 转 kbit/s: 1 MB/s = 8192 kbit/s
echo "scale=0; $mb * 8192 / 1" | bc 2>/dev/null || echo "0"
}
# Default commands
tc="dbg_tc"
ip="dbg_ip"
nft="dbg_nft"
nft_type
stop_qos() {
for face in $(tc qdisc show 2>/dev/null | grep htb | awk '{print $5}'); do
$tc qdisc del dev $face root 2>/dev/null
done
$tc qdisc del dev ${dev} root 2>/dev/null
$tc qdisc del dev ${dev}_ifb root 2>/dev/null
$tc qdisc del dev ${dev} ingress 2>/dev/null
$ip link del dev ${dev}_ifb 2>/dev/null 2>&1
if [ -n "$nftables_ver" ]; then
$nft delete table inet ${NAME} 2>/dev/null
$nft delete table bridge ${NAME} 2>/dev/null
fi
echo "" > "$IDLIST" 2>/dev/null
}
init_qosplus() {
insmod sch_htb 2>/dev/null
insmod act_mirred 2>/dev/null
insmod ifb 2>/dev/null
$ip link del dev ${dev}_ifb 2>/dev/null
$ip link add dev ${dev}_ifb name ${dev}_ifb type ifb
$ip link set dev ${dev}_ifb up
$tc qdisc del dev ${dev} root 2>/dev/null
$tc qdisc add dev ${dev} root handle 1:0 htb default 1
$tc class add dev ${dev} parent 1:0 classid 1:1 htb rate 1000mbit ceil 1000mbit
$tc qdisc del dev ${dev}_ifb root 2>/dev/null
$tc qdisc add dev ${dev}_ifb root handle 1:0 htb default 1
$tc class add dev ${dev}_ifb parent 1:0 classid 1:1 htb rate 1000mbit ceil 1000mbit
lanipaddr=$(uci -q get network.lan.ipaddr 2>/dev/null | awk -F '.' '{print $1"."$2"."$3".0/24"}')
if [ -n "$lanipaddr" ]; then
$tc filter add dev $dev parent 1:0 protocol ip prio 1 u32 match ip src "$lanipaddr" match ip dst "$lanipaddr" flowid 1:1
$tc filter add dev ${dev}_ifb parent 1:0 protocol ip prio 1 u32 match ip src "$lanipaddr" match ip dst "$lanipaddr" flowid 1:1
fi
$tc qdisc del dev ${dev} ingress 2>/dev/null
$tc qdisc add dev ${dev} ingress
$tc filter add dev ${dev} parent ffff: protocol all prio 2 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ${dev}_ifb
if [ -n "$nftables_ver" ]; then
$nft delete table inet ${NAME} 2>/dev/null
$nft delete table bridge ${NAME} 2>/dev/null
$nft add table inet ${NAME}
$nft add chain inet ${NAME} mark_forward { type filter hook forward priority -200\; policy accept\; }
$nft add chain inet ${NAME} mark_output { type filter hook output priority -200\; policy accept\; }
$nft add chain inet ${NAME} mark_postrouting { type filter hook postrouting priority -200\; policy accept\; }
fi
return 0
}
del_id() {
local list_id=$1
id=$((list_id * 10 + 1000))
[ "${DEBUG:-0}" -eq 0 ] || echo "D: del_id $@ --$id --$mac"
$tc filter del dev ${dev} parent 1: handle 800::$(printf "%x" $id) 2>/dev/null
$tc class del dev ${dev} parent 1:1 classid 1:$id 2>/dev/null
$tc filter del dev ${dev}_ifb parent 1: handle 800::$(printf "%x" $id) 2>/dev/null
$tc class del dev ${dev}_ifb parent 1:1 classid 1:$id 2>/dev/null
mac=$(uci -q get $NAME.@device[$list_id].mac 2>/dev/null)
if [ -n "$nftables_ver" ] && [ -n "$mac" ]; then
if is_macaddr "$mac"; then
$nft delete rule inet ${NAME} mark_forward ether saddr $mac counter 2>/dev/null
$nft delete rule inet ${NAME} mark_output ether saddr $mac counter 2>/dev/null
$nft delete rule inet ${NAME} mark_postrouting ether saddr $mac counter 2>/dev/null
else
Z=$(echo $mac | awk -F '[/]' '{print $2}')
[ -n "$Z" ] && mac=$(echo $mac | awk -F '[/]' '{print $1}') || Z=32
$nft delete rule inet ${NAME} mark_forward ip saddr $mac/$Z counter 2>/dev/null
$nft delete rule inet ${NAME} mark_output ip saddr $mac/$Z counter 2>/dev/null
$nft delete rule inet ${NAME} mark_postrouting ip saddr $mac/$Z counter 2>/dev/null
fi
fi
}
add_mac() {
local list_id=$1
id=$((list_id * 10 + 1000))
M0=$(echo $mac | cut -d : -f 1)$(echo $mac | cut -d : -f 2)
M1=$(echo $mac | cut -d : -f 3)$(echo $mac | cut -d : -f 4)
M2=$(echo $mac | cut -d : -f 5)$(echo $mac | cut -d : -f 6)
[ "${DEBUG:-0}" -eq 0 ] || echo "D: add_mac $@ --id:$id --mac:$mac M012--$M0-$M1-$M2"
if is_gt_zero "$UL"; then
if [ -n "$nftables_ver" ]; then
$nft add rule inet ${NAME} mark_forward ether saddr $mac counter meta mark set $id
$nft add rule inet ${NAME} mark_output ether saddr $mac counter meta mark set $id
$nft add rule inet ${NAME} mark_postrouting ether saddr $mac counter meta mark set $id
fi
$tc class add dev ${dev}_ifb parent 1:1 classid 1:$id htb rate "${UL}kbit" ceil "${UL}kbit" prio $id burst 15k cburst 15k
$tc qdisc add dev ${dev}_ifb parent 1:$id handle ${id}: sfq perturb 10
$tc filter add dev ${dev}_ifb parent 1: protocol ip prio $id handle $id fw flowid 1:$id
$tc filter add dev ${dev}_ifb parent 1: protocol ip prio $((id + 100)) u32 \
match u16 0x0800 0xFFFF at -2 \
match u16 0x${M2} 0xFFFF at -4 \
match u32 0x${M0}${M1} 0xFFFFFFFF at -8 \
flowid 1:$id
fi
if is_gt_zero "$DL"; then
$tc class add dev ${dev} parent 1:1 classid 1:$id htb rate "${DL}kbit" ceil "${DL}kbit" prio $id burst 15k cburst 15k
$tc qdisc add dev ${dev} parent 1:$id handle ${id}: sfq perturb 10
$tc filter add dev ${dev} parent 1: protocol ip prio $id u32 \
match u16 0x0800 0xFFFF at -2 \
match u32 0x${M1}${M2} 0xFFFFFFFF at -12 \
match u16 0x${M0} 0xFFFF at -14 \
flowid 1:$id
fi
}
add_ip() {
local list_id=$1
id=$((list_id * 10 + 1000))
[ "${DEBUG:-0}" -eq 0 ] || echo "D: add_ip $@ --$id --$mac"
Z=$(echo $mac | awk -F '[/]' '{print $2}')
[ -n "$Z" ] && mac=$(echo $mac | awk -F '[/]' '{print $1}') || Z=32
if is_gt_zero "$UL"; then
if [ -n "$nftables_ver" ]; then
$nft add rule inet ${NAME} mark_forward ip saddr $mac/$Z counter meta mark set $id
$nft add rule inet ${NAME} mark_output ip saddr $mac/$Z counter meta mark set $id
$nft add rule inet ${NAME} mark_postrouting ip saddr $mac/$Z counter meta mark set $id
fi
$tc class add dev ${dev}_ifb parent 1:1 classid 1:$id htb rate "${UL}kbit" ceil "${UL}kbit" prio $id burst 15k cburst 15k
$tc qdisc add dev ${dev}_ifb parent 1:$id handle ${id}: sfq perturb 10
$tc filter add dev ${dev}_ifb parent 1: protocol ip prio $id handle $id fw flowid 1:$id
$tc filter add dev ${dev}_ifb parent 1:0 prio $((id + 100)) protocol ip u32 \
match ip src "$mac"/"$Z" \
flowid 1:$id
fi
if is_gt_zero "$DL"; then
$tc class add dev ${dev} parent 1:1 classid 1:$id htb rate "${DL}kbit" ceil "${DL}kbit" prio $id burst 15k cburst 15k
$tc qdisc add dev ${dev} parent 1:$id handle ${id}: sfq perturb 10
$tc filter add dev ${dev} parent 1:0 prio $id protocol ip u32 \
match ip dst "$mac"/"$Z" \
flowid 1:$id
fi
}
check_time() {
local start=$1
local end=$2
local current=$(date +%H%M)
local start_min=$((10#${start:0:2}*60 + 10#${start:3:2}))
local end_min=$((10#${end:0:2}*60 + 10#${end:3:2}))
local current_min=$((10#${current:0:2}*60 + 10#${current:2:2}))
if [[ $start_min -lt $end_min ]]; then
[[ $current_min -ge $start_min && $current_min -lt $end_min ]]
else
[[ $current_min -ge $start_min || $current_min -lt $end_min ]]
fi
}
check_list() {
local i=$1
local start_time=$(uci -q get $NAME.@device[$i].timestart 2>/dev/null)
local end_time=$(uci -q get $NAME.@device[$i].timeend 2>/dev/null)
local wweek=$(uci -q get $NAME.@device[$i].week 2>/dev/null)
local current_weekday=$(date +%u)
[ -z "$start_time" ] && [ -z "$end_time" ] && [ -z "$wweek" ] && return 0
if [ -n "$wweek" ] && [ "$wweek" != "0" ]; then
local day_match=0
for day in $(echo $wweek | tr ',' ' '); do
[ "$day" -eq "$current_weekday" ] && day_match=1 && break
done
[ "$day_match" -eq 0 ] && return 1
fi
if [ -n "$start_time" ] && [ -n "$end_time" ]; then
check_time "$start_time" "$end_time" || return 1
fi
return 0
}
case "$crrun" in
"stop")
stop_qos
;;
"start")
stop_qos > /dev/null 2>&1
sleep 2
init_qosplus
idlist=$(uci show $NAME 2>/dev/null | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]' | sort -nu | sed -e 's/^/!/g' -e 's/$/!/g' > $IDLIST; cat $IDLIST 2>/dev/null | sed -e 's/!//g')
if [ ! -s "$IDLIST" ]; then
return 1
fi
device_count=0
for list in $(echo $idlist | sed -e 's/!//g'); do
if check_list $list; then
mac=$(uci -q get $NAME.@device[$list].mac 2>/dev/null)
download_mb=$(uci -q get $NAME.@device[$list].download 2>/dev/null)
upload_mb=$(uci -q get $NAME.@device[$list].upload 2>/dev/null)
comment=$(uci -q get $NAME.@device[$list].comment 2>/dev/null)
# 转换为kbit
DL=$(to_kbit "$download_mb")
UL=$(to_kbit "$upload_mb")
if [ -n "$mac" ]; then
if is_macaddr "$mac"; then
add_mac $list >>$LOG
echo "✅ MAC限速: $comment ($mac) - 下载:${download_mb}MB/s(${DL}kbit/s) 上传:${upload_mb}MB/s(${UL}kbit/s)" >>$LOG
else
add_ip $list >>$LOG
echo "✅ IP限速: $comment ($mac) - 下载:${download_mb}MB/s(${DL}kbit/s) 上传:${upload_mb}MB/s(${UL}kbit/s)" >>$LOG
fi
device_count=$((device_count + 1))
fi
else
[ -f "$IDLIST" ] && [ $(grep "!${list}!" "$IDLIST" 2>/dev/null | wc -l) -gt 0 ] && {
del_id $list >>$LOG
sed -i "/!$list!/d" "$IDLIST" >/dev/null 2>&1
comment=$(uci -q get $NAME.@device[$list].comment 2>/dev/null)
}
fi
done
echo "EQOSPLUS限速服务启动完成,共配置 $device_count 个设备" >>$LOG
echo ""
echo "当前限速状态:" >>$LOG
tc -s class show dev $dev | grep "rate" | head -5 >>$LOG
tc -s class show dev ${dev}_ifb | grep "rate" | head -5 >>$LOG
;;
"add")
echo "➕ 添加限速规则..."
for list in $(echo $crid | sed -e 's/!//g' | sed 's/,/ /g'); do
mac=$(uci -q get $NAME.@device[$list].mac 2>/dev/null)
download_mb=$(uci -q get $NAME.@device[$list].download 2>/dev/null)
upload_mb=$(uci -q get $NAME.@device[$list].upload 2>/dev/null)
comment=$(uci -q get $NAME.@device[$list].comment 2>/dev/null)
DL=$(to_kbit "$download_mb")
UL=$(to_kbit "$upload_mb")
if is_macaddr $mac; then
add_mac $list
echo "✅ 添加MAC限速: $comment ($mac)" >>$LOG
else
add_ip $list
echo "✅ 添加IP限速: $comment ($mac)" >>$LOG
fi
done
;;
"del")
for list in $(echo $crid | sed -e 's/!//g' | sed 's/,/ /g'); do
comment=$(uci -q get $NAME.@device[$list].comment 2>/dev/null)
mac=$(uci -q get $NAME.@device[$list].mac 2>/dev/null)
del_id $list
done
;;
"status")
echo "EQOSPLUS限速服务状态"
echo "### 网络接口: $dev ###"
echo "# 下载队列统计 #"
tc -s qdisc show dev $dev 2>/dev/null || echo "无下载队列"
echo "# 下载类统计 #"
tc -s class show dev $dev 2>/dev/null | grep -E "class htb|rate [0-9]" || echo "无下载类"
echo "# 下载过滤器 #"
tc -s filter show dev $dev parent 1: 2>/dev/null | head -10 || echo "无下载过滤器"
echo "### 虚拟接口: ${dev}_ifb ###"
echo "# 上传队列统计 #"
tc -s qdisc show dev ${dev}_ifb 2>/dev/null || echo "无上传队列"
echo "# 上传类统计 #"
tc -s class show dev ${dev}_ifb 2>/dev/null | grep -E "class htb|rate [0-9]" || echo "无上传类"
echo "# 上传过滤器 #"
tc -s filter show dev ${dev}_ifb parent 1: 2>/dev/null | head -10 || echo "无上传过滤器"
if [ -n "$nftables_ver" ]; then
echo "### NFTables规则 ###"
nft list table inet ${NAME} 2>/dev/null || echo "没有NFTables规则"
else
echo "NFTables不可用"
fi
# 显示流量统计
echo "### 流量统计 ###"
echo "下载流量:"
tc -s class show dev $dev 2>/dev/null | grep "Sent" | head -5
echo "上传流量:"
tc -s class show dev ${dev}_ifb 2>/dev/null | grep "Sent" | head -5
;;
esac
@@ -0,0 +1,63 @@
#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
# Copyright 2022-2025 sirpdboy <herboy2008@gmail.com>
NAME=eqosplus
IDLIST="/var/$NAME.idlist"
TMPID="/var/$NAME.tmpid"
idlist=`uci show $NAME | grep "enable='1'" | grep "device" | grep -oE '\[.*?\]' | grep -o '[0-9]' `
check_list() {
i=$1
checki='0'
start_time=$(uci -q get $NAME.@device[$i].timestart 2>/dev/null)
end_time=$(uci -q get $NAME.@device[$i].timeend 2>/dev/null)
wweek=`uci -q get $NAME.@device[$i].week `
current_time=$(date +%H:%M)
current_weekday=$(date +%u)
for ww in `echo $wweek | sed 's/,/ /g' `; do
if [ $current_weekday = $ww ] || [ 'x0' = x$ww ] ;then
[ "$start_time" = "$end_time" ] && checki='1' || {
if [ "$start_time" \< "$end_time" ]; then
if [ "$current_time" \> "$start_time" ] && [ "$current_time" \< "$end_time" ] ; then
checki='1'
fi
else
if [ "$start_time" \> "$end_time" ] ; then
if [ "$current_time" \< "$start_time" ] && [ "$current_time" \> "$end_time" ] ; then
checki='1'
fi
fi
fi
}
fi
done
return
}
idlistusr(){
checki='0'
[ -s $IDLIST ] || touch $IDLIST
for list in $idlist ;do
check_list $list
if [ $checki == '1' ] ; then
[ `cat $IDLIST 2>/dev/null | grep "!${list}!" | wc -l ` -gt 0 ] || {
eqosplus add $list
echo "!${list}!" >> $IDLIST ; cat $IDLIST | sort | uniq > $TMPID ;cat $TMPID >$IDLIST ;rm -rf $TMPID
}
else
[ `cat $IDLIST 2>/dev/null | grep "!${list}!" | wc -l ` -gt 0 ] && {
eqosplus del $list
sed -i "/!$list!/d" $IDLIST >/dev/null 2>&1
}
fi
done
}
while :;do
sleep 30
idlistusr
sleep 30
done
@@ -0,0 +1,11 @@
{
"luci-app-eqosplus": {
"description": "Grant UCI access for luci-app-eqosplus",
"read": {
"uci": [ "eqosplus" ]
},
"write": {
"uci": [ "eqosplus" ]
}
}
}