nft-qos: support mac address based speed limit

This patch makes it possible to configure and limit per-client internet
speed based on MAC address and it can work with SQM.
This feature is what OpenWRT currently lacks. This patch is largely based
on static.sh and the configuration file is similar to original nft-qos.

New configuration options and examples are listed below

config default 'default'
    option limit_mac_enable '1'
config client
	option drunit 'kbytes'
	option urunit 'kbytes'
	option hostname 'tv-box'
	option macaddr 'AB:CD:EF:01:23:45'
	option drate '1000'
	option urate '50'
config client
	option drunit 'kbytes'
	option urunit 'kbytes'
	option hostname 'my-pc'
	option macaddr 'AB:CD:EF:01:23:46'
	option drate '3000'
	option urate '2000'

limit_mac_enable - enable rate limit based on MAC address
drunit - download rate unit
urunit - upload rate unit
macaddr - client MAC address
drate - download rate
urate - upload rate

Signed-off-by: Tong Zhang <ztong0001@gmail.com>
This commit is contained in:
Tong Zhang 2020-08-14 07:21:33 -04:00
parent 9c1670ed61
commit 0483b8dc88
5 changed files with 108 additions and 1 deletions

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=nft-qos
PKG_VERSION:=1.0.6
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=Rosy Song <rosysong@rosinson.com>

View File

@ -34,6 +34,17 @@ qosdef_append_rule_ip_limit() { # <ipaddr> <operator> <unit> <rate>
"\t\tip $operator $ipaddr limit rate over $rate $unit/second drop\n"
}
# qosdef_append_rule_{MATCH}_{STATEMENT}
qosdef_append_rule_mac_limit() { # <macaddr> <operator> <unit> <rate>
local macaddr=$1
local operator=$2
local unit=$3
local rate=$4
qosdef_appendx \
"\t\tether $operator $macaddr limit rate over $rate $unit/second drop\n"
}
# qosdef_append_rule_{MATCH}_{POLICY}
qosdef_append_rule_ip_policy() { # <operator> <ipaddr> <policy>
qosdef_appendx "\t\tip $1 $2 $3\n"

View File

@ -0,0 +1,79 @@
#!/bin/sh
# based on static.sh
# Copyright (C) 2020 Tong Zhang<ztong0001@gmail.com>
#
. /lib/nft-qos/core.sh
qosdef_validate_mac() {
uci_load_validate nft-qos default "$1" "$2" \
'limit_mac_enable:bool:0'
}
# append rule for mac qos
qosdef_append_rule_mac() { # <section> <operator>
local macaddr unit rate
local operator=$2
config_get macaddr $1 macaddr
if [ "$operator" = "saddr" ]; then
config_get unit $1 urunit
config_get rate $1 urate
else
config_get unit $1 drunit
config_get rate $1 drate
fi
[ -z "$macaddr" ] && return
qosdef_append_rule_mac_limit $macaddr $operator $unit $rate
}
# append chain for mac qos
qosdef_append_chain_mac() { # <hook> <name> <section>
local hook=$1 name=$2
local config=$3 operator
case "$name" in
download) operator="daddr";;
upload) operator="saddr";;
esac
qosdef_appendx "\tchain $name {\n"
qosdef_append_chain_def filter $hook 0 accept
config_foreach qosdef_append_rule_mac $config $operator
qosdef_appendx "\t}\n"
}
qosdef_flush_mac() {
if [ -n "$NFT_QOS_HAS_BRIDGE" ]; then
qosdef_flush_table bridge nft-qos-mac
else
qosdef_flush_table "$NFT_QOS_INET_FAMILY" nft-qos-mac
fi
}
# limit rate by mac address init
qosdef_init_mac() {
local hook_ul="prerouting" hook_dl="postrouting"
[ "$2" = 0 ] || {
logger -t nft-qos-mac "validation failed"
return 1
}
[ $limit_mac_enable -eq 0 ] && return 1
table_name=$NFT_QOS_INET_FAMILY
if [ -z "$NFT_QOS_HAS_BRIDGE" ]; then
hook_ul="postrouting"
hook_dl="prerouting"
else
table_name="bridge"
fi
qosdef_appendx "table $table_name nft-qos-mac {\n"
qosdef_append_chain_mac $hook_ul upload client
qosdef_append_chain_mac $hook_dl download client
qosdef_appendx "}\n"
}

View File

@ -51,6 +51,9 @@ config default default
# list limit_whitelist '192.168.1.0/24'
# list limit_whitelist 'ABCD:CDEF::1/64'
# Option for Mac address based traffic control
option limit_mac_enable '0'
# Options for Traffic Priority
option priority_enable '0'
option priority_netdev 'lan'
@ -73,6 +76,15 @@ config default default
# option ipaddr 'ABCD:FFED::1/64'
# option rate '1024'
#
# For MAC address based traffic control Samples :
#
#config client
# option drunit 'kbytes'
# option urunit 'kbytes'
# option hostname 'tvbox'
# option macaddr '00:00:00:00:00:00'
# option drate '300'
# option urate '30'
#
# Traffic Priority Samples :
#

View File

@ -7,6 +7,7 @@
. /lib/nft-qos/monitor.sh
. /lib/nft-qos/dynamic.sh
. /lib/nft-qos/static.sh
. /lib/nft-qos/mac.sh
. /lib/nft-qos/priority.sh
START=99
@ -19,6 +20,7 @@ service_triggers() {
qosdef_validate_dynamic
qosdef_validate_static
qosdef_validate_priority
qosdef_validate_mac
procd_close_validate
}
@ -26,6 +28,7 @@ start_service() {
config_load nft-qos
qosdef_init_env
qosdef_flush_mac
qosdef_flush_static
qosdef_flush_dynamic
qosdef_remove_priority
@ -34,6 +37,7 @@ start_service() {
qosdef_init_monitor
qosdef_validate_dynamic default qosdef_init_dynamic
qosdef_validate_static default qosdef_init_static
qosdef_validate_mac default qosdef_init_mac
qosdef_validate_priority default qosdef_init_priority
qosdef_init_done
qosdef_start
@ -42,6 +46,7 @@ start_service() {
stop_service() {
qosdef_flush_dynamic
qosdef_flush_static
qosdef_flush_mac
qosdef_remove_priority
qosdef_clean_cache
}