-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ffda-wireless-rate-limiter: add package
This adds a package which can be used to shape traffic on the wireless interfaces interface-wide or per-client. Signed-off-by: David Bauer <[email protected]>
- Loading branch information
1 parent
0bc5c69
commit 833fccd
Showing
3 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
include $(TOPDIR)/rules.mk | ||
|
||
PKG_NAME:=ffda-wireless-rate-limiter | ||
PKG_RELEASE:=1 | ||
|
||
PKG_SOURCE_PROTO:=git | ||
PKG_SOURCE_URL=https://github.com/blocktrron/wireless-rate-limiter.git | ||
PKG_SOURCE_DATE:=2024-08-24 | ||
PKG_SOURCE_VERSION:=1fedb08ba7ce347d5c3f7c8ddcac8a5e2f5d14b6 | ||
|
||
PKG_MAINTAINER:=David Bauer <[email protected]> | ||
PKG_LICENSE:=GPL-2.0 | ||
|
||
include $(TOPDIR)/../package/gluon.mk | ||
include $(INCLUDE_DIR)/cmake.mk | ||
|
||
CMAKE_SOURCE_SUBDIR:=src | ||
|
||
define Package/ffda-wireless-rate-limiter | ||
TITLE:=Wireless rate-limiter | ||
DEPENDS:=+libubox +libubus +libblobmsg-json +tc +kmod-sched-core +kmod-ifb +gluon-core | ||
endef | ||
|
||
define Package/ffda-wireless-rate-limiter/description | ||
Package to impose per-interface and per-client rate limits on a wireless interface | ||
endef | ||
|
||
define Package/ffda-wireless-rate-limiter/conffiles | ||
/etc/config/wireless-rate-limiter | ||
endef | ||
|
||
define Package/ffda-wireless-rate-limiter/install | ||
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/config $(1)/lib/wireless-rate-limiter $(1)/lib/gluon/upgrade | ||
|
||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/wireless-rate-limiter $(1)/usr/bin/wireless-rate-limiter | ||
|
||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/wireless-rate-limiter/files/wireless-rate-limiter.init $(1)/etc/init.d/wireless-rate-limiter | ||
|
||
$(CP) $(PKG_BUILD_DIR)/openwrt/wireless-rate-limiter/files/wireless-rate-limiter.uci $(1)/etc/config/wireless-rate-limiter | ||
|
||
$(CP) $(PKG_BUILD_DIR)/openwrt/wireless-rate-limiter/files/htb-shared.sh $(1)/lib/wireless-rate-limiter/htb-shared.sh | ||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/wireless-rate-limiter/files/htb-client.sh $(1)/lib/wireless-rate-limiter/htb-client.sh | ||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/wireless-rate-limiter/files/htb-netdev.sh $(1)/lib/wireless-rate-limiter/htb-netdev.sh | ||
|
||
$(INSTALL_BIN) ./files/wireless-rate-limiter.upgrade.lua $(1)/lib/gluon/upgrade/880-wireless-rate-limiter | ||
endef | ||
|
||
$(eval $(call BuildPackageGluon,ffda-wireless-rate-limiter)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# ffda-wireless-rate-limiter | ||
|
||
This package provides a rate-limiter which can shape traffic per client | ||
and per interface. The limit is user-configurable and defaults can be | ||
applied and updated via the site-config. | ||
|
||
## Examples | ||
### Site | ||
|
||
Below you can see an example of how to configure the rate-limiter | ||
in the site-configuration. | ||
|
||
Each client is shaped to a different rate. | ||
|
||
- On 5 GHz, only the uplink will be shaped. | ||
- On 2.4 GHz, both uplink and downlink will be shaped. Additionally, | ||
all traffic on the 2.4 GHz radios will each be shaped to a maximum | ||
of 10 Mbit/s downlink and 5 Mbit/s uplink. | ||
|
||
When using OWE, the limits are imposed for the unencrypted and OWE network | ||
indepedently. | ||
|
||
```lua | ||
wifi24 = { | ||
channel = 5, -- 2432 MHz | ||
|
||
rate_limit = { | ||
client = { | ||
down = 6000, -- 6 Mbit/s | ||
up = 3000, -- 3 Mbit/s | ||
}, | ||
iface = { | ||
down = 10000, -- 10 Mbit/s | ||
up = 5000, -- 5 Mbit/s | ||
}, | ||
}, | ||
|
||
mesh = { | ||
mcast_rate = 12000, | ||
}, | ||
}, | ||
wifi5 = { | ||
channel = 48, -- 5230 MHz | ||
outdoor_chanlist = '96-116 132-140', | ||
|
||
rate_limit = { | ||
client = { | ||
up = 6000, -- 6 Mbit/s | ||
}, | ||
}, | ||
|
||
mesh = { | ||
mcast_rate = 12000, | ||
}, | ||
}, | ||
``` | ||
|
||
### UCI | ||
|
||
The rate-limiter can also be configured via UCI. The following example is | ||
for a configuration which is equivalent to the site-configuration above. | ||
|
||
Take note however: If you intend to remove | ||
limits imposed by the site-configuration, you need to set the values to | ||
`0` instead of removing the sections. | ||
|
||
```sh | ||
uci set gluon.rate_limit_2g=ffda-rate-limit | ||
uci set gluon.rate_limit_2g.band='2g' | ||
uci set gluon.rate_limit_2g.client_down=6000 | ||
uci set gluon.rate_limit_2g.client_up=3000 | ||
uci set gluon.rate_limit_2g.iface_down=10000 | ||
uci set gluon.rate_limit_2g.iface_up=5000 | ||
|
||
uci set gluon.rate_limit_5g=ffda-rate-limit | ||
uci set gluon.rate_limit_5g.band='5g' | ||
uci set gluon.rate_limit_5g.client_down=0 | ||
uci set gluon.rate_limit_5g.client_up=2000 | ||
uci set gluon.rate_limit_5g.iface_down=10000 | ||
uci set gluon.rate_limit_5g.iface_up=5000 | ||
|
||
uci commit gluon | ||
``` |
120 changes: 120 additions & 0 deletions
120
ffda-wireless-rate-limiter/files/wireless-rate-limiter.upgrade.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/lua | ||
|
||
local uci = require('simple-uci').cursor() | ||
local wireless = require('gluon.wireless') | ||
|
||
local function get_uci_section_for_band(band) | ||
local section_name = nil | ||
uci:foreach('gluon', 'ffda-rate-limit', function(section) | ||
if section.band == band then | ||
section_name = section['.name'] | ||
end | ||
end) | ||
|
||
return section_name | ||
end | ||
|
||
local function get_user_limit(band, limit_type) | ||
local uci_section = get_uci_section_for_band(band) | ||
if uci_section then | ||
return uci:get('gluon', uci_section, limit_type) | ||
end | ||
|
||
return nil | ||
end | ||
|
||
local function wireless_limits_get() | ||
local output_limits = {} | ||
wireless.foreach_radio(uci, function(radio, _, site_config) | ||
local radio_band = radio.band | ||
local radio_index = radio['.name']:match('^radio(%d+)$') | ||
|
||
local limit_table = { | ||
client = { | ||
up = { | ||
['user'] = get_user_limit(radio_band, 'client_up'), | ||
['site'] = site_config.rate_limit.client.up(0) | ||
}, | ||
down = { | ||
['user'] = get_user_limit(radio_band, 'client_down'), | ||
['site'] = site_config.rate_limit.client.down(0) | ||
} | ||
}, | ||
iface = { | ||
up = { | ||
['user'] = get_user_limit(radio_band, 'iface_up'), | ||
['site'] = site_config.rate_limit.up(0) | ||
}, | ||
down = { | ||
['user'] = get_user_limit(radio_band, 'iface_down'), | ||
['site'] = site_config.rate_limit.down(0) | ||
} | ||
} | ||
} | ||
|
||
output_limits[radio_band] = { | ||
index = radio_index, | ||
limits = { | ||
client = { | ||
up = limit_table.client.up.user or limit_table.client.up.site, | ||
down = limit_table.client.down.user or limit_table.client.down.site | ||
}, | ||
iface = { | ||
up = limit_table.iface.up.user or limit_table.iface.up.site, | ||
down = limit_table.iface.down.user or limit_table.iface.down.site | ||
} | ||
}, | ||
} | ||
end) | ||
|
||
return output_limits | ||
end | ||
|
||
local function wireless_limits_set(index, limits) | ||
local limit_applied = false | ||
for type_key, type_value in pairs(limits) do | ||
local limit_down = type_value.down | ||
local limit_up = type_value.up | ||
|
||
for _, iface_type in ipairs({'client', 'owe'}) do | ||
local section_name = type_key .. '_limit_' .. iface_type .. index | ||
|
||
uci:delete('wireless-rate-limiter', section_name) | ||
|
||
if limit_down ~= 0 or limit_up ~= 0 then | ||
local section_type = type_key == 'client' and 'limit-client' or 'limit-interface' | ||
uci:section('wireless-rate-limiter', section_type, section_name, { | ||
interface = iface_type .. index, | ||
download = limit_down, | ||
upload = limit_up, | ||
disabled = 0 | ||
}) | ||
|
||
limit_applied = true | ||
end | ||
end | ||
end | ||
|
||
return limit_applied | ||
end | ||
|
||
-- Delete existing config | ||
uci:delete_all('wireless-rate-limiter', 'limit-client') | ||
uci:delete_all('wireless-rate-limiter', 'limit-interface') | ||
|
||
-- Apply config | ||
local limits = wireless_limits_get() | ||
local limits_applied = false | ||
for _, value in pairs(limits) do | ||
if wireless_limits_set(value.index, value.limits) then | ||
limits_applied = true | ||
end | ||
end | ||
|
||
-- Decide daemon necessity | ||
uci:set('wireless-rate-limiter', 'core', 'disabled', not limits_applied) | ||
|
||
-- Save | ||
uci:commit('wireless-rate-limiter') | ||
|
||
return 0 |