mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2026-03-14 21:10:11 +01:00
qosmngr: alternative
This commit is contained in:
parent
76a8f98a94
commit
dcba2de075
3 changed files with 190 additions and 111 deletions
|
|
@ -112,10 +112,10 @@ configure_classify() {
|
|||
sh /tmp/qos/classify.ip6tables
|
||||
sh /tmp/qos/classify.iprule
|
||||
|
||||
# Sync DSCP/PCP mappings to mapcontroller for WiFi QoS
|
||||
if [ -f /lib/qos/mapcontroller_sync.sh ]; then
|
||||
. /lib/qos/mapcontroller_sync.sh
|
||||
sync_mapcontroller_qos
|
||||
# Sync DSCP/PCP mappings to WiFi QoS Map on local AP interfaces
|
||||
if [ -f /lib/qos/wifi_qos.sh ]; then
|
||||
. /lib/qos/wifi_qos.sh
|
||||
sync_wifi_qos
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Sync DSCP/PCP mappings from qosmngr classify rules to mapcontroller
|
||||
# for WiFi QoS (EasyMesh QoS Map) integration.
|
||||
#
|
||||
# When device priority classify rules set dscp_mark/pcp_mark, this script
|
||||
# generates a mapcontroller qos_rule (type dscp_pcp) so all EasyMesh agents
|
||||
# apply the correct DSCP-to-WMM AC mapping on WiFi interfaces.
|
||||
|
||||
MAPCNTLR_CFG="mapcontroller"
|
||||
AUTO_RULE_ID="1000"
|
||||
AUTO_RULE_NAME="qos_auto_dscp_pcp"
|
||||
|
||||
# Collect dscp_mark/pcp_mark pairs from enabled classify sections.
|
||||
# Stores results in /tmp/qos/dscp_pcp_map (sorted by order, first wins).
|
||||
_collect_dscp_pcp_mapping() {
|
||||
local cid="$1"
|
||||
local is_enable dscp_mark pcp_mark c_order
|
||||
|
||||
config_get is_enable "$cid" "enable" "1"
|
||||
[ "$is_enable" = "0" ] && return
|
||||
|
||||
config_get dscp_mark "$cid" "dscp_mark"
|
||||
config_get pcp_mark "$cid" "pcp_mark"
|
||||
|
||||
# Skip rules without both dscp_mark and pcp_mark
|
||||
[ -z "$dscp_mark" ] && return
|
||||
[ -z "$pcp_mark" ] && return
|
||||
|
||||
# Skip negative values (means "no change" in TR-181)
|
||||
[ "$dscp_mark" -lt 0 ] 2>/dev/null && return
|
||||
[ "$pcp_mark" -lt 0 ] 2>/dev/null && return
|
||||
|
||||
# Validate ranges
|
||||
[ "$dscp_mark" -gt 63 ] 2>/dev/null && return
|
||||
[ "$pcp_mark" -gt 7 ] 2>/dev/null && return
|
||||
|
||||
config_get c_order "$cid" "order" "999"
|
||||
|
||||
# Format: order dscp pcp (sorted later, first occurrence per dscp wins)
|
||||
echo "$c_order $dscp_mark $pcp_mark" >> /tmp/qos/dscp_pcp_map
|
||||
}
|
||||
|
||||
# Remove previously auto-generated qos_rule sections from mapcontroller config
|
||||
_cleanup_auto_rules() {
|
||||
local section auto_gen
|
||||
|
||||
# Find all qos_rule sections with auto_generated='1'
|
||||
for section in $(uci -q show "$MAPCNTLR_CFG" | grep '\.auto_generated=.1.' | sed "s/\.auto_generated=.*//;s/${MAPCNTLR_CFG}\.//"); do
|
||||
uci -q delete "${MAPCNTLR_CFG}.${section}"
|
||||
done
|
||||
}
|
||||
|
||||
# Main sync function - called after configure_classify()
|
||||
sync_mapcontroller_qos() {
|
||||
# Guard: skip if mapcontroller/EasyMesh is not installed
|
||||
[ -f "/etc/config/$MAPCNTLR_CFG" ] || return 0
|
||||
|
||||
rm -f /tmp/qos/dscp_pcp_map
|
||||
|
||||
# Collect mappings from all classify rules
|
||||
config_load qos
|
||||
config_foreach _collect_dscp_pcp_mapping classify
|
||||
|
||||
# Remove old auto-generated rules
|
||||
_cleanup_auto_rules
|
||||
|
||||
# If no mappings found, just commit cleanup and signal
|
||||
if [ ! -s /tmp/qos/dscp_pcp_map ]; then
|
||||
uci -q commit "$MAPCNTLR_CFG"
|
||||
killall -HUP mapcontroller 2>/dev/null
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Deduplicate: sort by order (ascending), keep first occurrence per DSCP
|
||||
sort -n -k1 /tmp/qos/dscp_pcp_map | awk '!seen[$2]++ {print $2 "," $3}' > /tmp/qos/dscp_pcp_list
|
||||
|
||||
if [ ! -s /tmp/qos/dscp_pcp_list ]; then
|
||||
uci -q commit "$MAPCNTLR_CFG"
|
||||
killall -HUP mapcontroller 2>/dev/null
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ensure QoS is enabled in mapcontroller
|
||||
uci -q set "${MAPCNTLR_CFG}.qos=qos"
|
||||
uci -q set "${MAPCNTLR_CFG}.qos.enabled=1"
|
||||
|
||||
# Create auto-generated qos_rule
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}=qos_rule"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.id=${AUTO_RULE_ID}"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.type=dscp_pcp"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.precedence=200"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.output=0"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.always_match=1"
|
||||
uci -q set "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.auto_generated=1"
|
||||
|
||||
# Clear any existing dscp_pcp list entries and add new ones
|
||||
uci -q delete "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.dscp_pcp"
|
||||
while read -r mapping; do
|
||||
uci -q add_list "${MAPCNTLR_CFG}.${AUTO_RULE_NAME}.dscp_pcp=${mapping}"
|
||||
done < /tmp/qos/dscp_pcp_list
|
||||
|
||||
# Commit and signal mapcontroller to reload
|
||||
uci -q commit "$MAPCNTLR_CFG"
|
||||
killall -HUP mapcontroller 2>/dev/null
|
||||
|
||||
rm -f /tmp/qos/dscp_pcp_map /tmp/qos/dscp_pcp_list
|
||||
}
|
||||
186
qosmngr/files/common/lib/qos/wifi_qos.sh
Normal file
186
qosmngr/files/common/lib/qos/wifi_qos.sh
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
#!/bin/sh
|
||||
# Sync DSCP/PCP mappings from qosmngr classify rules to WiFi QoS Map.
|
||||
#
|
||||
# When device priority or QoS profile classify rules set dscp_mark/pcp_mark,
|
||||
# this script builds an IEEE 802.11 QoS Map and applies it directly to all
|
||||
# local WiFi AP interfaces via ubus (wifi.ap.* set_qos_map).
|
||||
#
|
||||
# QoS Map format (IEEE 802.11-2020, 9.4.2.93):
|
||||
# [exception pairs...] [8 UP ranges]
|
||||
# Exception pair: DSCP_value, User_Priority (2 bytes each)
|
||||
# UP range: DSCP_low, DSCP_high (2 bytes each, 16 bytes total for UP 0-7)
|
||||
# If DSCP_low=255 and DSCP_high=255, that UP is unused.
|
||||
|
||||
# Collect dscp_mark/pcp_mark pairs from enabled classify sections.
|
||||
_collect_dscp_pcp_mapping() {
|
||||
local cid="$1"
|
||||
local is_enable dscp_mark pcp_mark c_order
|
||||
|
||||
config_get is_enable "$cid" "enable" "1"
|
||||
[ "$is_enable" = "0" ] && return
|
||||
|
||||
config_get dscp_mark "$cid" "dscp_mark"
|
||||
config_get pcp_mark "$cid" "pcp_mark"
|
||||
|
||||
[ -z "$dscp_mark" ] && return
|
||||
[ -z "$pcp_mark" ] && return
|
||||
|
||||
# Skip negative values (means "no change" in TR-181)
|
||||
[ "$dscp_mark" -lt 0 ] 2>/dev/null && return
|
||||
[ "$pcp_mark" -lt 0 ] 2>/dev/null && return
|
||||
|
||||
# Validate ranges
|
||||
[ "$dscp_mark" -gt 63 ] 2>/dev/null && return
|
||||
[ "$pcp_mark" -gt 7 ] 2>/dev/null && return
|
||||
|
||||
config_get c_order "$cid" "order" "999"
|
||||
|
||||
echo "$c_order $dscp_mark $pcp_mark" >> /tmp/qos/dscp_pcp_map
|
||||
}
|
||||
|
||||
# Build IEEE 802.11 QoS Map byte array from DSCP->PCP mappings.
|
||||
# Input: /tmp/qos/dscp_pcp_list (lines of "dscp,pcp")
|
||||
# Output: prints space-separated byte array for ubus json
|
||||
_build_qos_map() {
|
||||
local dscp pcp default_up i
|
||||
|
||||
# Initialize 64-entry DSCP->PCP table with defaults (IP precedence: dscp/8)
|
||||
# Using a file since shell arrays aren't portable
|
||||
i=0
|
||||
while [ $i -lt 64 ]; do
|
||||
echo "$i $((i / 8))"
|
||||
i=$((i + 1))
|
||||
done > /tmp/qos/dscp_pcp_full
|
||||
|
||||
# Override with our explicit mappings
|
||||
while IFS=',' read -r dscp pcp; do
|
||||
sed -i "s/^${dscp} .*/${dscp} ${pcp}/" /tmp/qos/dscp_pcp_full
|
||||
done < /tmp/qos/dscp_pcp_list
|
||||
|
||||
# For each PCP (0-7), find the largest contiguous range of DSCPs
|
||||
# and collect exceptions (DSCPs outside the range)
|
||||
local exc=""
|
||||
local ranges=""
|
||||
|
||||
i=0
|
||||
while [ $i -lt 8 ]; do
|
||||
# Get all DSCPs mapped to this PCP, sorted numerically
|
||||
local dscp_list
|
||||
dscp_list=$(awk -v p="$i" '$2 == p {print $1}' /tmp/qos/dscp_pcp_full | sort -n)
|
||||
|
||||
if [ -z "$dscp_list" ]; then
|
||||
# No DSCPs map to this PCP - mark range as unused
|
||||
ranges="$ranges 255 255"
|
||||
i=$((i + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Find largest contiguous range
|
||||
local best_start="" best_end="" best_len=0
|
||||
local cur_start="" cur_end="" cur_len=0
|
||||
local prev=-2
|
||||
|
||||
for d in $dscp_list; do
|
||||
if [ $((prev + 1)) -eq "$d" ]; then
|
||||
cur_end=$d
|
||||
cur_len=$((cur_len + 1))
|
||||
else
|
||||
cur_start=$d
|
||||
cur_end=$d
|
||||
cur_len=1
|
||||
fi
|
||||
if [ $cur_len -gt $best_len ]; then
|
||||
best_start=$cur_start
|
||||
best_end=$cur_end
|
||||
best_len=$cur_len
|
||||
fi
|
||||
prev=$d
|
||||
done
|
||||
|
||||
ranges="$ranges $best_start $best_end"
|
||||
|
||||
# Exceptions: DSCPs outside the best range for this PCP
|
||||
for d in $dscp_list; do
|
||||
if [ "$d" -lt "$best_start" ] || [ "$d" -gt "$best_end" ]; then
|
||||
exc="$exc $d $i"
|
||||
fi
|
||||
done
|
||||
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
# Output: exceptions first, then 8 UP ranges (16 bytes)
|
||||
echo "$exc $ranges" | tr -s ' ' | sed 's/^ //'
|
||||
|
||||
rm -f /tmp/qos/dscp_pcp_full
|
||||
}
|
||||
|
||||
# Apply QoS Map to all local WiFi AP interfaces via ubus
|
||||
_apply_qos_map_to_aps() {
|
||||
local qos_map_bytes="$1"
|
||||
local ap json_array
|
||||
|
||||
# Build JSON array string from space-separated bytes
|
||||
json_array=$(echo "$qos_map_bytes" | tr ' ' ',' | sed 's/^/[/;s/$/]/')
|
||||
|
||||
for ap in $(ubus list 2>/dev/null | grep '^wifi\.ap\.'); do
|
||||
ubus call "$ap" set_qos_map "{\"set\": $json_array}" 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
# Send QoS Map Configuration frame to all connected STAs
|
||||
_notify_stas() {
|
||||
local ap sta_list sta
|
||||
|
||||
for ap in $(ubus list 2>/dev/null | grep '^wifi\.ap\.'); do
|
||||
# Get list of connected STAs
|
||||
sta_list=$(ubus call "$ap" stations 2>/dev/null | \
|
||||
jsonfilter -e '@.stations[*].macaddr' 2>/dev/null)
|
||||
for sta in $sta_list; do
|
||||
ubus call "$ap" send_qos_map_conf "{\"sta\": \"$sta\"}" 2>/dev/null
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# Clear QoS Map from all WiFi AP interfaces
|
||||
_clear_qos_map() {
|
||||
local ap
|
||||
|
||||
for ap in $(ubus list 2>/dev/null | grep '^wifi\.ap\.'); do
|
||||
ubus call "$ap" set_qos_map '{"set": []}' 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
# Main sync function - called after configure_classify()
|
||||
sync_wifi_qos() {
|
||||
rm -f /tmp/qos/dscp_pcp_map
|
||||
|
||||
# Collect mappings from all classify rules
|
||||
config_load qos
|
||||
config_foreach _collect_dscp_pcp_mapping classify
|
||||
|
||||
# If no mappings found, clear QoS Map
|
||||
if [ ! -s /tmp/qos/dscp_pcp_map ]; then
|
||||
_clear_qos_map
|
||||
rm -f /tmp/qos/dscp_pcp_map /tmp/qos/dscp_pcp_list
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Deduplicate: sort by order (ascending), keep first occurrence per DSCP
|
||||
sort -n -k1 /tmp/qos/dscp_pcp_map | awk '!seen[$2]++ {print $2 "," $3}' > /tmp/qos/dscp_pcp_list
|
||||
|
||||
if [ ! -s /tmp/qos/dscp_pcp_list ]; then
|
||||
_clear_qos_map
|
||||
rm -f /tmp/qos/dscp_pcp_map /tmp/qos/dscp_pcp_list
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Build and apply QoS Map
|
||||
local qos_map
|
||||
qos_map=$(_build_qos_map)
|
||||
|
||||
_apply_qos_map_to_aps "$qos_map"
|
||||
_notify_stas
|
||||
|
||||
rm -f /tmp/qos/dscp_pcp_map /tmp/qos/dscp_pcp_list
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue