Merge pull request #918 from hnyman/sqm-backport
Sqm-scripts backport to BB14.07
This commit is contained in:
commit
c13e819dfc
17 changed files with 1750 additions and 0 deletions
67
net/luci-app-sqm/Makefile
Normal file
67
net/luci-app-sqm/Makefile
Normal file
|
@ -0,0 +1,67 @@
|
|||
#
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-sqm
|
||||
PKG_VERSION:=3
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=GPLv2
|
||||
LUCI_DIR:=/usr/lib/lua/luci
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/luci-app-sqm
|
||||
SECTION:=luci
|
||||
CATEGORY:=LuCI
|
||||
TITLE:=SQM Scripts - LuCI interface
|
||||
MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
PKGARCH:=all
|
||||
DEPENDS:= lua luci-base +sqm-scripts
|
||||
SUBMENU:=3. Applications
|
||||
endef
|
||||
|
||||
define Package/luci-app-sqm/description
|
||||
Control the simple_qos SQM script
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Package/luci-app-sqm/install
|
||||
$(INSTALL_DIR) $(1)$(LUCI_DIR)/controller $(1)$(LUCI_DIR)/model/cbi
|
||||
$(INSTALL_DATA) ./files/sqm-controller.lua $(1)$(LUCI_DIR)/controller/sqm.lua
|
||||
$(INSTALL_DATA) ./files/sqm-cbi.lua $(1)$(LUCI_DIR)/model/cbi/sqm.lua
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/uci-defaults-sqm $(1)/etc/uci-defaults/luci-sqm
|
||||
endef
|
||||
|
||||
define Package/luci-app-sqm/postinst
|
||||
#!/bin/sh
|
||||
which uci > /dev/null || exit 0
|
||||
uci -q get ucitrack.@sqm[0] > /dev/null || {
|
||||
uci add ucitrack sqm > /dev/null
|
||||
uci set ucitrack.@sqm[0].init=sqm
|
||||
uci add_list ucitrack.@firewall[0].affects=sqm
|
||||
uci commit
|
||||
}
|
||||
endef
|
||||
|
||||
define Package/luci-app-sqm/postrm
|
||||
#!/bin/sh
|
||||
which uci > /dev/null || exit 0
|
||||
uci -q get ucitrack.@sqm[0] > /dev/null && {
|
||||
uci delete ucitrack.@sqm[0]
|
||||
uci del_list ucitrack.@firewall[0].affects=sqm
|
||||
uci commit
|
||||
}
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,luci-app-sqm))
|
217
net/luci-app-sqm/files/sqm-cbi.lua
Normal file
217
net/luci-app-sqm/files/sqm-cbi.lua
Normal file
|
@ -0,0 +1,217 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2014 Steven Barth <steven@midlink.org>
|
||||
Copyright 2014 Dave Taht <dave.taht@bufferbloat.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local fs = require "nixio.fs"
|
||||
local net = require "luci.model.network".init()
|
||||
local sys = require "luci.sys"
|
||||
--local ifaces = net:get_interfaces()
|
||||
local ifaces = sys.net:devices()
|
||||
local path = "/usr/lib/sqm"
|
||||
|
||||
m = Map("sqm", translate("Smart Queue Management"),
|
||||
translate("With <abbr title=\"Smart Queue Management\">SQM</abbr> you " ..
|
||||
"can enable traffic shaping, better mixing (Fair Queueing)," ..
|
||||
" active queue length management (AQM) " ..
|
||||
" and prioritisation on one " ..
|
||||
"network interface."))
|
||||
|
||||
s = m:section(TypedSection, "queue", translate("Queues"))
|
||||
s:tab("tab_basic", translate("Basic Settings"))
|
||||
s:tab("tab_qdisc", translate("Queue Discipline"))
|
||||
s:tab("tab_linklayer", translate("Link Layer Adaptation"))
|
||||
s.addremove = true -- set to true to allow adding SQM instances in the GUI
|
||||
s.anonymous = true
|
||||
|
||||
-- BASIC
|
||||
e = s:taboption("tab_basic", Flag, "enabled", translate("Enable"))
|
||||
e.rmempty = false
|
||||
|
||||
n = s:taboption("tab_basic", ListValue, "interface", translate("Interface name"))
|
||||
-- sm lifted from luci-app-wol, the original implementation failed to show pppoe-ge00 type interface names
|
||||
for _, iface in ipairs(ifaces) do
|
||||
-- if iface:is_up() then
|
||||
-- n:value(iface:name())
|
||||
-- end
|
||||
if iface ~= "lo" then
|
||||
n:value(iface)
|
||||
end
|
||||
end
|
||||
n.rmempty = false
|
||||
|
||||
|
||||
dl = s:taboption("tab_basic", Value, "download", translate("Download speed (kbit/s) (ingress):"))
|
||||
dl.datatype = "and(uinteger,min(0))"
|
||||
dl.rmempty = false
|
||||
|
||||
ul = s:taboption("tab_basic", Value, "upload", translate("Upload speed (kbit/s) (egress):"))
|
||||
ul.datatype = "and(uinteger,min(0))"
|
||||
ul.rmempty = false
|
||||
|
||||
-- QDISC
|
||||
|
||||
c = s:taboption("tab_qdisc", ListValue, "qdisc", translate("Queueing discipline"))
|
||||
c:value("fq_codel", "fq_codel ("..translate("default")..")")
|
||||
c:value("efq_codel")
|
||||
c:value("nfq_codel")
|
||||
c:value("sfq")
|
||||
c:value("codel")
|
||||
c:value("ns2_codel")
|
||||
c:value("pie")
|
||||
c:value("sfq")
|
||||
c.default = "fq_codel"
|
||||
c.rmempty = false
|
||||
|
||||
local qos_desc = ""
|
||||
sc = s:taboption("tab_qdisc", ListValue, "script", translate("Queue setup script"))
|
||||
for file in fs.dir(path) do
|
||||
if string.find(file, ".qos$") then
|
||||
sc:value(file)
|
||||
end
|
||||
if string.find(file, ".qos.help$") then
|
||||
fh = io.open(path .. "/" .. file, "r")
|
||||
qos_desc = qos_desc .. "<p><b>" .. file:gsub(".help$", "") .. ":</b><br />" .. fh:read("*a") .. "</p>"
|
||||
end
|
||||
end
|
||||
sc.default = "simple.qos"
|
||||
sc.rmempty = false
|
||||
sc.description = qos_desc
|
||||
|
||||
ad = s:taboption("tab_qdisc", Flag, "qdisc_advanced", translate("Show Advanced Configuration"))
|
||||
ad.default = false
|
||||
ad.rmempty = true
|
||||
|
||||
squash_dscp = s:taboption("tab_qdisc", ListValue, "squash_dscp", translate("Squash DSCP on inbound packets (ingress):"))
|
||||
squash_dscp:value("1", "SQUASH")
|
||||
squash_dscp:value("0", "DO NOT SQUASH")
|
||||
squash_dscp.default = "1"
|
||||
squash_dscp.rmempty = true
|
||||
squash_dscp:depends("qdisc_advanced", "1")
|
||||
|
||||
squash_ingress = s:taboption("tab_qdisc", ListValue, "squash_ingress", translate("Ignore DSCP on ingress:"))
|
||||
squash_ingress:value("1", "Ignore")
|
||||
squash_ingress:value("0", "Allow")
|
||||
squash_ingress.default = "1"
|
||||
squash_ingress.rmempty = true
|
||||
squash_ingress:depends("qdisc_advanced", "1")
|
||||
|
||||
iecn = s:taboption("tab_qdisc", ListValue, "ingress_ecn", translate("Explicit congestion notification (ECN) status on inbound packets (ingress):"))
|
||||
iecn:value("ECN", "ECN ("..translate("default")..")")
|
||||
iecn:value("NOECN")
|
||||
iecn.default = "ECN"
|
||||
iecn.rmempty = true
|
||||
iecn:depends("qdisc_advanced", "1")
|
||||
|
||||
eecn = s:taboption("tab_qdisc", ListValue, "egress_ecn", translate("Explicit congestion notification (ECN) status on outbound packets (egress)."))
|
||||
eecn:value("NOECN", "NOECN ("..translate("default")..")")
|
||||
eecn:value("ECN")
|
||||
eecn.default = "NOECN"
|
||||
eecn.rmempty = true
|
||||
eecn:depends("qdisc_advanced", "1")
|
||||
|
||||
ad2 = s:taboption("tab_qdisc", Flag, "qdisc_really_really_advanced", translate("Show Dangerous Configuration"))
|
||||
ad2.default = false
|
||||
ad2.rmempty = true
|
||||
ad2:depends("qdisc_advanced", "1")
|
||||
|
||||
ilim = s:taboption("tab_qdisc", Value, "ilimit", translate("Hard limit on ingress queues; leave empty for default."))
|
||||
-- ilim.default = 1000
|
||||
ilim.isnumber = true
|
||||
ilim.datatype = "and(uinteger,min(0))"
|
||||
ilim.rmempty = true
|
||||
ilim:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
elim = s:taboption("tab_qdisc", Value, "elimit", translate("Hard limit on egress queues; leave empty for default."))
|
||||
-- elim.default = 1000
|
||||
elim.datatype = "and(uinteger,min(0))"
|
||||
elim.rmempty = true
|
||||
elim:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
|
||||
itarg = s:taboption("tab_qdisc", Value, "itarget", translate("Latency target for ingress, e.g 5ms [units: s, ms, or us]; leave empty for default, or auto for automatic selection."))
|
||||
itarg.datatype = "string"
|
||||
itarg.rmempty = true
|
||||
itarg:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
etarg = s:taboption("tab_qdisc", Value, "etarget", translate("Latency target for egress, e.g. 5ms [units: s, ms, or us]; leave empty for default, or auto for automatic selection."))
|
||||
etarg.datatype = "string"
|
||||
etarg.rmempty = true
|
||||
etarg:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
|
||||
|
||||
iqdisc_opts = s:taboption("tab_qdisc", Value, "iqdisc_opts", translate("Advanced option string to pass to the ingress queueing disciplines; no error checking, use very carefully."))
|
||||
iqdisc_opts.rmempty = true
|
||||
iqdisc_opts:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
eqdisc_opts = s:taboption("tab_qdisc", Value, "eqdisc_opts", translate("Advanced option string to pass to the egress queueing disciplines; no error checking, use very carefully."))
|
||||
eqdisc_opts.rmempty = true
|
||||
eqdisc_opts:depends("qdisc_really_really_advanced", "1")
|
||||
|
||||
-- LINKLAYER
|
||||
ll = s:taboption("tab_linklayer", ListValue, "linklayer", translate("Which link layer to account for:"))
|
||||
ll:value("none", "none ("..translate("default")..")")
|
||||
ll:value("ethernet", "Ethernet with overhead: select for e.g. VDSL2.")
|
||||
ll:value("atm", "ATM: select for e.g. ADSL1, ADSL2, ADSL2+.")
|
||||
-- ll:value("adsl") -- reduce the options
|
||||
ll.default = "none"
|
||||
|
||||
po = s:taboption("tab_linklayer", Value, "overhead", translate("Per Packet Overhead (byte):"))
|
||||
po.datatype = "and(integer,min(-1500))"
|
||||
po.default = 0
|
||||
po.isnumber = true
|
||||
po.rmempty = true
|
||||
po:depends("linklayer", "ethernet")
|
||||
-- po:depends("linklayer", "adsl")
|
||||
po:depends("linklayer", "atm")
|
||||
|
||||
|
||||
adll = s:taboption("tab_linklayer", Flag, "linklayer_advanced", translate("Show Advanced Linklayer Options, (only needed if MTU > 1500)"))
|
||||
adll.rmempty = true
|
||||
adll:depends("linklayer", "ethernet")
|
||||
-- adll:depends("linklayer", "adsl")
|
||||
adll:depends("linklayer", "atm")
|
||||
|
||||
smtu = s:taboption("tab_linklayer", Value, "tcMTU", translate("Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= interface MTU + overhead:"))
|
||||
smtu.datatype = "and(uinteger,min(0))"
|
||||
smtu.default = 2047
|
||||
smtu.isnumber = true
|
||||
smtu.rmempty = true
|
||||
smtu:depends("linklayer_advanced", "1")
|
||||
|
||||
stsize = s:taboption("tab_linklayer", Value, "tcTSIZE", translate("Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU + 1) / 16:"))
|
||||
stsize.datatype = "and(uinteger,min(0))"
|
||||
stsize.default = 128
|
||||
stsize.isnumber = true
|
||||
stsize.rmempty = true
|
||||
stsize:depends("linklayer_advanced", "1")
|
||||
|
||||
smpu = s:taboption("tab_linklayer", Value, "tcMPU", translate("Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:"))
|
||||
smpu.datatype = "and(uinteger,min(0))"
|
||||
smpu.default = 0
|
||||
smpu.isnumber = true
|
||||
smpu.rmempty = true
|
||||
smpu:depends("linklayer_advanced", "1")
|
||||
|
||||
lla = s:taboption("tab_linklayer", ListValue, "linklayer_adaptation_mechanism", translate("Which linklayer adaptation mechanism to use; for testing only"))
|
||||
lla:value("htb_private")
|
||||
lla:value("tc_stab", "tc_stab ("..translate("default")..")")
|
||||
lla.default = "tc_stab"
|
||||
lla.rmempty = true
|
||||
lla:depends("linklayer_advanced", "1")
|
||||
|
||||
-- PRORITIES?
|
||||
|
||||
return m
|
26
net/luci-app-sqm/files/sqm-controller.lua
Normal file
26
net/luci-app-sqm/files/sqm-controller.lua
Normal file
|
@ -0,0 +1,26 @@
|
|||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
module("luci.controller.sqm", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/sqm") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
|
||||
page = entry({"admin", "network", "sqm"}, cbi("sqm"), _("SQM QoS"))
|
||||
page.dependent = true
|
||||
end
|
12
net/luci-app-sqm/files/uci-defaults-sqm
Normal file
12
net/luci-app-sqm/files/uci-defaults-sqm
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@sqm[-1]
|
||||
add ucitrack sqm
|
||||
set ucitrack.@sqm[-1].init=sqm
|
||||
add_list ucitrack.@firewall[0].affects=sqm
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
59
net/sqm-scripts/Makefile
Normal file
59
net/sqm-scripts/Makefile
Normal file
|
@ -0,0 +1,59 @@
|
|||
#
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=sqm-scripts
|
||||
PKG_VERSION:=8
|
||||
PKG_RELEASE:=2
|
||||
PKG_LICENSE:=GPLv2
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/sqm-scripts
|
||||
SECTION:=net
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+tc +kmod-sched +kmod-ifb iptables +ip \
|
||||
+iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra
|
||||
TITLE:=SQM Scripts (QoS)
|
||||
PKGARCH:=all
|
||||
MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
endef
|
||||
|
||||
define Package/sqm-scripts/description
|
||||
A set of scripts that does simple SQM configuration.
|
||||
endef
|
||||
|
||||
define Package/sqm-scripts/conffiles
|
||||
/etc/config/sqm
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/sqm-scripts/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/etc/init.d/sqm $(1)/etc/init.d/sqm
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_BIN) ./files/etc/hotplug.d/iface/11-sqm $(1)/etc/hotplug.d/iface/11-sqm
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) ./files/etc/config/sqm $(1)/etc/config/sqm
|
||||
$(INSTALL_DIR) $(1)/usr/lib/sqm
|
||||
$(INSTALL_BIN) ./files/usr/lib/sqm/*.sh $(1)/usr/lib/sqm/
|
||||
$(INSTALL_BIN) ./files/usr/lib/sqm/*.qos $(1)/usr/lib/sqm/
|
||||
$(INSTALL_DATA) ./files/usr/lib/sqm/*.help $(1)/usr/lib/sqm/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,sqm-scripts))
|
16
net/sqm-scripts/files/etc/config/sqm
Normal file
16
net/sqm-scripts/files/etc/config/sqm
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
config queue 'eth1'
|
||||
option enabled '0'
|
||||
option interface 'eth1'
|
||||
option download '85000'
|
||||
option upload '10000'
|
||||
option qdisc 'fq_codel'
|
||||
option script 'simple.qos'
|
||||
option qdisc_advanced '0'
|
||||
option ingress_ecn 'ECN'
|
||||
option egress_ecn 'NOECN'
|
||||
option qdisc_really_really_advanced '0'
|
||||
option itarget 'auto'
|
||||
option etarget 'auto'
|
||||
option linklayer 'none'
|
||||
|
3
net/sqm-scripts/files/etc/hotplug.d/iface/11-sqm
Executable file
3
net/sqm-scripts/files/etc/hotplug.d/iface/11-sqm
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
[ "$ACTION" = ifup ] && /usr/lib/sqm/run.sh interface ${DEVICE}
|
23
net/sqm-scripts/files/etc/init.d/sqm
Normal file
23
net/sqm-scripts/files/etc/init.d/sqm
Normal file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=50
|
||||
|
||||
reload()
|
||||
{
|
||||
/usr/lib/sqm/run.sh
|
||||
}
|
||||
|
||||
restart()
|
||||
{
|
||||
reload
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
reload
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
/usr/lib/sqm/run.sh stop
|
||||
}
|
458
net/sqm-scripts/files/usr/lib/sqm/functions.sh
Normal file
458
net/sqm-scripts/files/usr/lib/sqm/functions.sh
Normal file
|
@ -0,0 +1,458 @@
|
|||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
#improve the logread output
|
||||
sqm_logger() {
|
||||
logger -t SQM -s ${1}
|
||||
}
|
||||
|
||||
insmod() {
|
||||
lsmod | grep -q ^$1 || $INSMOD $1
|
||||
}
|
||||
|
||||
ipt() {
|
||||
d=`echo $* | sed s/-A/-D/g`
|
||||
[ "$d" != "$*" ] && {
|
||||
iptables $d > /dev/null 2>&1
|
||||
ip6tables $d > /dev/null 2>&1
|
||||
}
|
||||
d=`echo $* | sed s/-I/-D/g`
|
||||
[ "$d" != "$*" ] && {
|
||||
iptables $d > /dev/null 2>&1
|
||||
ip6tables $d > /dev/null 2>&1
|
||||
}
|
||||
iptables $* > /dev/null 2>&1
|
||||
ip6tables $* > /dev/null 2>&1
|
||||
}
|
||||
|
||||
do_modules() {
|
||||
#sm TODO: check first whether the modules exist and only load then
|
||||
insmod act_ipt
|
||||
insmod sch_$QDISC
|
||||
insmod sch_ingress
|
||||
insmod act_mirred
|
||||
insmod cls_fw
|
||||
insmod sch_htb
|
||||
}
|
||||
|
||||
|
||||
# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
|
||||
|
||||
[ -z "$UPLINK" ] && UPLINK=2302
|
||||
[ -z "$DOWNLINK" ] && DOWNLINK=14698
|
||||
[ -z "$IFACE" ] && IFACE=ge00
|
||||
[ -z "$QDISC" ] && QDISC=fq_codel
|
||||
[ -z "$LLAM" ] && LLAM="tc_stab"
|
||||
[ -z "$LINKLAYER" ] && LINKLAYER="none"
|
||||
[ -z "$OVERHEAD" ] && OVERHEAD=0
|
||||
[ -z "$STAB_MTU" ] && STAB_MTU=2047
|
||||
[ -z "$STAB_MPU" ] && STAB_MPU=0
|
||||
[ -z "$STAB_TSIZE" ] && STAB_TSIZE=512
|
||||
[ -z "$AUTOFLOW" ] && AUTOFLOW=0
|
||||
[ -z "$LIMIT" ] && LIMIT=1001 # sane global default for *LIMIT for fq_codel on a small memory device
|
||||
[ -z "$ILIMIT" ] && ILIMIT=
|
||||
[ -z "$ELIMIT" ] && ELIMIT=
|
||||
[ -z "$ITARGET" ] && ITARGET=
|
||||
[ -z "$ETARGET" ] && ETARGET=
|
||||
[ -z "$IECN" ] && IECN="ECN"
|
||||
[ -z "$EECN" ] && EECN="NOECN"
|
||||
[ -z "$SQUASH_DSCP" ] && SQUASH_DSCP="1"
|
||||
[ -z "$SQUASH_INGRESS" ] && SQUASH_INGRESS="1"
|
||||
[ -z "$IQDISC_OPTS" ] && IQDISC_OPTS=""
|
||||
[ -z "$EQDISC_OPTS" ] && EQDISC_OPTS=""
|
||||
[ -z "$TC" ] && TC=`which tc`
|
||||
#[ -z "$TC" ] && TC="sqm_logger tc"# this redirects all tc calls into the log
|
||||
[ -z "$IP" ] && IP=$( which ip )
|
||||
[ -z "$INSMOD" ] && INSMOD=`which insmod`
|
||||
[ -z "$TARGET" ] && TARGET="5ms"
|
||||
[ -z "$IPT_MASK" ] && IPT_MASK="0xff"
|
||||
[ -z "$IPT_MASK_STRING" ] && IPT_MASK_STRING="/${IPT_MASK}" # for set-mark
|
||||
|
||||
#sqm_logger "${0} IPT_MASK: ${IPT_MASK_STRING}"
|
||||
|
||||
|
||||
|
||||
# find the ifb device associated with a specific interface, return nothing of no ifb is associated with IF
|
||||
get_ifb_associated_with_if() {
|
||||
CUR_IF=$1
|
||||
# CUR_IFB=$( tc -p filter show parent ffff: dev ${CUR_IF} | grep -o -e ifb'[[:digit:]]\+' )
|
||||
CUR_IFB=$( tc -p filter show parent ffff: dev ${CUR_IF} | grep -o -e ifb'[^)]\+' ) # my editor's syntax coloration is limitied so I need a single quote in this line (between eiditor and s)
|
||||
sqm_logger "ifb associated with interface ${CUR_IF}: ${CUR_IFB}"
|
||||
echo ${CUR_IFB}
|
||||
}
|
||||
|
||||
# ATTENTION, IFB names can only be 15 chararcters, so we chop of excessive characters at the start of the interface name
|
||||
# if required
|
||||
create_new_ifb_for_if() {
|
||||
CUR_IF=$1
|
||||
MAX_IF_NAME_LENGTH=15
|
||||
IFB_PREFIX="ifb4"
|
||||
NEW_IFB="${IFB_PREFIX}${CUR_IF}"
|
||||
IFB_NAME_LENGTH=${#NEW_IFB}
|
||||
if [ ${IFB_NAME_LENGTH} -gt ${MAX_IF_NAME_LENGTH} ];
|
||||
then
|
||||
sqm_logger "The requsted IFB name ${NEW_IFB} is longer than the allowed 15 characters, trying to make it shorter"
|
||||
OVERLIMIT=$(( ${#NEW_IFB} - ${MAX_IF_NAME_LENGTH} ))
|
||||
NEW_IFB=${IFB_PREFIX}${CUR_IF:${OVERLIMIT}:$(( ${MAX_IF_NAME_LENGTH} - ${#IFB_PREFIX} ))}
|
||||
fi
|
||||
sqm_logger "trying to create new IFB: ${NEW_IFB}"
|
||||
$IP link add name ${NEW_IFB} type ifb #>/dev/null 2>&1 # better be verbose
|
||||
echo ${NEW_IFB}
|
||||
}
|
||||
|
||||
# the best match is either the IFB already associated with the current interface or a new named IFB
|
||||
get_ifb_for_if() {
|
||||
CUR_IF=$1
|
||||
# if an ifb is already associated return that
|
||||
CUR_IFB=$( get_ifb_associated_with_if ${CUR_IF} )
|
||||
[ -z "$CUR_IFB" ] && CUR_IFB=$( create_new_ifb_for_if ${CUR_IF} )
|
||||
[ -z "$CUR_IFB" ] && sqm_logger "Could not find existing IFB for ${CUR_IF}, nor create a new IFB instead..."
|
||||
echo ${CUR_IFB}
|
||||
}
|
||||
|
||||
#sm: we need the functions above before trying to set the ingress IFB device
|
||||
[ -z "$DEV" ] && DEV=$( get_ifb_for_if ${IFACE} ) # automagically get the right IFB device for the IFACE"
|
||||
|
||||
|
||||
get_htb_adsll_string() {
|
||||
ADSLL=""
|
||||
if [ "$LLAM" = "htb_private" -a "$LINKLAYER" != "none" ];
|
||||
then
|
||||
# HTB defaults to MTU 1600 and an implicit fixed TSIZE of 256, but HTB as of around 3.10.0
|
||||
# does not actually use a table in the kernel
|
||||
ADSLL="mpu ${STAB_MPU} linklayer ${LINKLAYER} overhead ${OVERHEAD} mtu ${STAB_MTU}"
|
||||
sqm_logger "ADSLL: ${ADSLL}"
|
||||
fi
|
||||
echo ${ADSLL}
|
||||
}
|
||||
|
||||
get_stab_string() {
|
||||
STABSTRING=""
|
||||
if [ "${LLAM}" = "tc_stab" -a "$LINKLAYER" != "none" ];
|
||||
then
|
||||
STABSTRING="stab mtu ${STAB_MTU} tsize ${STAB_TSIZE} mpu ${STAB_MPU} overhead ${OVERHEAD} linklayer ${LINKLAYER}"
|
||||
sqm_logger "STAB: ${STABSTRING}"
|
||||
fi
|
||||
echo ${STABSTRING}
|
||||
}
|
||||
|
||||
sqm_stop() {
|
||||
$TC qdisc del dev $IFACE ingress
|
||||
$TC qdisc del dev $IFACE root
|
||||
$TC qdisc del dev $DEV root
|
||||
}
|
||||
|
||||
# Note this has side effects on the prio variable
|
||||
# and depends on the interface global too
|
||||
|
||||
fc() {
|
||||
$TC filter add dev $interface protocol ip parent $1 prio $prio u32 match ip tos $2 0xfc classid $3
|
||||
prio=$(($prio + 1))
|
||||
$TC filter add dev $interface protocol ipv6 parent $1 prio $prio u32 match ip6 priority $2 0xfc classid $3
|
||||
prio=$(($prio + 1))
|
||||
}
|
||||
|
||||
fc_pppoe() {
|
||||
PPPOE_SESSION_ETHERTYPE="0x8864"
|
||||
PPPOE_DISCOVERY_ETHERTYPE="0x8863"
|
||||
PPP_PROTO_IP4="0x0021"
|
||||
PPP_PROTO_IP6="0x0057"
|
||||
ARP_PROTO_IP4="0x0806"
|
||||
$TC filter add dev $interface protocol ip parent $1 prio $prio u32 match ip tos $2 0xfc classid $3
|
||||
$TC filter add dev $interface parent $1 protocol ${PPPOE_SESSION_ETHERTYPE} prio $(( 400 + ${prio} )) u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 $2 0xfc at 9 \
|
||||
flowid $3
|
||||
|
||||
prio=$(($prio + 1))
|
||||
$TC filter add dev $interface protocol ipv6 parent $1 prio $prio u32 match ip6 priority $2 0xfc classid $3
|
||||
$TC filter add dev $interface parent $1 protocol ${PPPOE_SESSION_ETHERTYPE} prio $(( 600 + ${prio} )) u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0${2:2:2}0 0x0fc0 at 8 \
|
||||
flowid $3
|
||||
|
||||
|
||||
|
||||
|
||||
prio=$(($prio + 1))
|
||||
|
||||
|
||||
}
|
||||
# FIXME: actually you need to get the underlying MTU on PPOE thing
|
||||
|
||||
get_mtu() {
|
||||
BW=$2
|
||||
F=`cat /sys/class/net/$1/mtu`
|
||||
if [ -z "$F" ]
|
||||
then
|
||||
F=1500
|
||||
fi
|
||||
if [ $BW -gt 20000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
if [ $BW -gt 30000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
if [ $BW -gt 40000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
if [ $BW -gt 50000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
if [ $BW -gt 60000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
if [ $BW -gt 80000 ]
|
||||
then
|
||||
F=$(($F * 2))
|
||||
fi
|
||||
echo $F
|
||||
}
|
||||
|
||||
# FIXME should also calculate the limit
|
||||
# Frankly I think Xfq_codel can pretty much always run with high numbers of flows
|
||||
# now that it does fate sharing
|
||||
# But right now I'm trying to match the ns2 model behavior better
|
||||
# So SET the autoflow variable to 1 if you want the cablelabs behavior
|
||||
|
||||
get_flows() {
|
||||
if [ "$AUTOFLOW" -eq "1" ]
|
||||
then
|
||||
FLOWS=8
|
||||
[ $1 -gt 999 ] && FLOWS=16
|
||||
[ $1 -gt 2999 ] && FLOWS=32
|
||||
[ $1 -gt 7999 ] && FLOWS=48
|
||||
[ $1 -gt 9999 ] && FLOWS=64
|
||||
[ $1 -gt 19999 ] && FLOWS=128
|
||||
[ $1 -gt 39999 ] && FLOWS=256
|
||||
[ $1 -gt 69999 ] && FLOWS=512
|
||||
[ $1 -gt 99999 ] && FLOWS=1024
|
||||
case $QDISC in
|
||||
codel|ns2_codel|pie|*fifo|pfifo_fast) ;;
|
||||
fq_codel|*fq_codel|sfq) echo flows $FLOWS ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# set the target parameter, also try to only take well formed inputs
|
||||
# Note, the link bandwidth in the current direction (ingress or egress)
|
||||
# is required to adjust the target for slow links
|
||||
get_target() {
|
||||
local CUR_TARGET=${1}
|
||||
local CUR_LINK_KBPS=${2}
|
||||
[ ! -z "$CUR_TARGET" ] && sqm_logger "cur_target: ${CUR_TARGET} cur_bandwidth: ${CUR_LINK_KBPS}"
|
||||
CUR_TARGET_STRING=
|
||||
# either e.g. 100ms or auto
|
||||
CUR_TARGET_VALUE=$( echo ${CUR_TARGET} | grep -o -e \^'[[:digit:]]\+' )
|
||||
CUR_TARGET_UNIT=$( echo ${CUR_TARGET} | grep -o -e '[[:alpha:]]\+'\$ )
|
||||
# [ ! -z "$CUR_TARGET" ] && sqm_logger "CUR_TARGET_VALUE: $CUR_TARGET_VALUE"
|
||||
# [ ! -z "$CUR_TARGET" ] && sqm_logger "CUR_TARGET_UNIT: $CUR_TARGET_UNIT"
|
||||
|
||||
AUTO_TARGET=
|
||||
UNIT_VALID=
|
||||
|
||||
case $QDISC in
|
||||
*codel|*pie)
|
||||
if [ ! -z "${CUR_TARGET_VALUE}" -a ! -z "${CUR_TARGET_UNIT}" ];
|
||||
then
|
||||
case ${CUR_TARGET_UNIT} in
|
||||
# permissible units taken from: tc_util.c get_time()
|
||||
s|sec|secs|ms|msec|msecs|us|usec|usecs)
|
||||
CUR_TARGET_STRING="target ${CUR_TARGET_VALUE}${CUR_TARGET_UNIT}"
|
||||
UNIT_VALID="1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case ${CUR_TARGET_UNIT} in
|
||||
auto|Auto|AUTO)
|
||||
if [ ! -z "${CUR_LINK_KBPS}" ];
|
||||
then
|
||||
TMP_TARGET_US=$( adapt_target_to_slow_link $CUR_LINK_KBPS )
|
||||
TMP_INTERVAL_STRING=$( adapt_interval_to_slow_link $TMP_TARGET_US )
|
||||
CUR_TARGET_STRING="target ${TMP_TARGET_US}us ${TMP_INTERVAL_STRING}"
|
||||
AUTO_TARGET="1"
|
||||
else
|
||||
sqm_logger "required link bandwidth in kbps not passed to get_target()."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ ! -z "${CUR_TARGET}" ];
|
||||
then
|
||||
if [ -z "${CUR_TARGET_VALUE}" -o -z "${UNIT_VALID}" ];
|
||||
then
|
||||
[ -z "$AUTO_TARGET" ] && sqm_logger "${CUR_TARGET} is not a well formed tc target specifier; e.g.: 5ms (or s, us), or the string auto."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
# sqm_logger "target: ${CUR_TARGET_STRING}"
|
||||
echo $CUR_TARGET_STRING
|
||||
}
|
||||
|
||||
# for low bandwidth links fq_codels default target of 5ms does not work too well
|
||||
# so increase target for slow links (note below roughly 2500kbps a single packet will \
|
||||
# take more than 5 ms to be tansfered over the wire)
|
||||
adapt_target_to_slow_link() {
|
||||
CUR_LINK_KBPS=$1
|
||||
CUR_EXTENDED_TARGET_US=
|
||||
MAX_PAKET_DELAY_IN_US_AT_1KBPS=$(( 1000 * 1000 *1540 * 8 / 1000 ))
|
||||
CUR_EXTENDED_TARGET_US=$(( ${MAX_PAKET_DELAY_IN_US_AT_1KBPS} / ${CUR_LINK_KBPS} )) # note this truncates the decimals
|
||||
# do not change anything for fast links
|
||||
[ "$CUR_EXTENDED_TARGET_US" -lt 5000 ] && CUR_EXTENDED_TARGET_US=5000
|
||||
case ${QDISC} in
|
||||
*codel|pie)
|
||||
echo "${CUR_EXTENDED_TARGET_US}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# codel looks at a whole interval to figure out wether observed latency stayed below target
|
||||
# if target >= interval that will not work well, so increase interval by the same amonut that target got increased
|
||||
adapt_interval_to_slow_link() {
|
||||
CUR_TARGET_US=$1
|
||||
case ${QDISC} in
|
||||
*codel)
|
||||
CUR_EXTENDED_INTERVAL_US=$(( (100 - 5) * 1000 + ${CUR_TARGET_US} ))
|
||||
echo "interval ${CUR_EXTENDED_INTERVAL_US}us"
|
||||
;;
|
||||
pie)
|
||||
## not sure if pie needs this, probably not
|
||||
#CUR_EXTENDED_TUPDATE_US=$(( (30 - 20) * 1000 + ${CUR_TARGET_US} ))
|
||||
#echo "tupdate ${CUR_EXTENDED_TUPDATE_US}us"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# set quantum parameter if available for this qdisc
|
||||
get_quantum() {
|
||||
case $QDISC in
|
||||
*fq_codel|fq_pie|drr) echo quantum $1 ;;
|
||||
*) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# only show limits to qdiscs that can handle them...
|
||||
# Note that $LIMIT contains the default limit
|
||||
get_limit() {
|
||||
CURLIMIT=$1
|
||||
case $QDISC in
|
||||
*codel|*pie|pfifo_fast|sfq|pfifo) [ -z ${CURLIMIT} ] && CURLIMIT=${LIMIT} # use the global default limit
|
||||
;;
|
||||
bfifo) [ -z "$CURLIMIT" ] && [ ! -z "$LIMIT" ] && CURLIMIT=$(( ${LIMIT} * $( cat /sys/class/net/${IFACE}/mtu ) )) # bfifo defaults to txquelength * MTU,
|
||||
;;
|
||||
*) sqm_logger "${QDISC} does not support a limit"
|
||||
;;
|
||||
esac
|
||||
sqm_logger "get_limit: $1 CURLIMIT: ${CURLIMIT}"
|
||||
|
||||
if [ ! -z "$CURLIMIT" ]
|
||||
then
|
||||
echo "limit ${CURLIMIT}"
|
||||
fi
|
||||
}
|
||||
|
||||
get_ecn() {
|
||||
CURECN=$1
|
||||
#sqm_logger CURECN: $CURECN
|
||||
case ${CURECN} in
|
||||
ECN)
|
||||
case $QDISC in
|
||||
*codel|*pie|*red)
|
||||
CURECN=ecn
|
||||
;;
|
||||
*)
|
||||
CURECN=""
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
NOECN)
|
||||
case $QDISC in
|
||||
*codel|*pie|*red)
|
||||
CURECN=noecn
|
||||
;;
|
||||
*)
|
||||
CURECN=""
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
sqm_logger "ecn value $1 not handled"
|
||||
;;
|
||||
esac
|
||||
#sqm_logger "get_ECN: $1 CURECN: ${CURECN} IECN: ${IECN} EECN: ${EECN}"
|
||||
echo ${CURECN}
|
||||
|
||||
}
|
||||
|
||||
# This could be a complete diffserv implementation
|
||||
|
||||
diffserv() {
|
||||
|
||||
interface=$1
|
||||
prio=1
|
||||
|
||||
# Catchall
|
||||
|
||||
$TC filter add dev $interface parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# Find the most common matches fast
|
||||
#fc_pppoe() instead of fc() with effectice ingress classification for pppoe is very expensive and destroys LUL
|
||||
|
||||
fc 1:0 0x00 1:12 # BE
|
||||
fc 1:0 0x20 1:13 # CS1
|
||||
fc 1:0 0x10 1:11 # IMM
|
||||
fc 1:0 0xb8 1:11 # EF
|
||||
fc 1:0 0xc0 1:11 # CS3
|
||||
fc 1:0 0xe0 1:11 # CS6
|
||||
fc 1:0 0x90 1:11 # AF42 (mosh)
|
||||
|
||||
# Arp traffic
|
||||
$TC filter add dev $interface protocol arp parent 1:0 prio $prio handle 500 fw flowid 1:11
|
||||
|
||||
|
||||
prio=$(($prio + 1))
|
||||
|
||||
|
||||
}
|
||||
|
||||
diffserv_pppoe() {
|
||||
|
||||
interface=$1
|
||||
prio=1
|
||||
|
||||
# Catchall
|
||||
|
||||
$TC filter add dev $interface parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# Find the most common matches fast
|
||||
#fc_pppoe() instead of fc() with effectice ingress classification for pppoe is very expensive and destroys LUL
|
||||
|
||||
fc_pppoe 1:0 0x00 1:12 # BE
|
||||
fc_pppoe 1:0 0x20 1:13 # CS1
|
||||
fc_pppoe 1:0 0x10 1:11 # IMM
|
||||
fc_pppoe 1:0 0xb8 1:11 # EF
|
||||
fc_pppoe 1:0 0xc0 1:11 # CS3
|
||||
fc_pppoe 1:0 0xe0 1:11 # CS6
|
||||
fc_pppoe 1:0 0x90 1:11 # AF42 (mosh)
|
||||
|
||||
# Arp traffic
|
||||
$TC filter add dev $interface protocol arp parent 1:0 prio $prio handle 500 fw flowid 1:11
|
||||
|
||||
|
||||
prio=$(($prio + 1))
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
123
net/sqm-scripts/files/usr/lib/sqm/run.sh
Executable file
123
net/sqm-scripts/files/usr/lib/sqm/run.sh
Executable file
|
@ -0,0 +1,123 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
STOP=
|
||||
ACTIVE_STATE_PREFIX="SQM_active_on_"
|
||||
ACTIVE_STATE_FILE_DIR="/var/run/SQM"
|
||||
mkdir -p ${ACTIVE_STATE_FILE_DIR}
|
||||
PROTO_STATE_FILE_LIST=$( ls ${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}* 2> /dev/null )
|
||||
|
||||
|
||||
case ${1} in
|
||||
stop)
|
||||
logger -t SQM -s "run.sh stop"
|
||||
STOP=$1
|
||||
;;
|
||||
interface)
|
||||
START_ON_IF=$2 # only process this interface
|
||||
logger -t SQM -s "Trying to re-start SQM on interface ${START_ON_IF}"
|
||||
# TODO if $2 is empty just bail...
|
||||
if [ -z ${START_ON_IF} ] ;
|
||||
then
|
||||
logger -t SQM -s "Interface name missing, nothing to do, bailing out"
|
||||
return 0
|
||||
fi
|
||||
# only try to restart the just hotplugged interface, so reduce the list of interfaces to stop to the specified one
|
||||
PROTO_STATE_FILE_LIST=${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}${START_ON_IF}
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# the current uci config file does not necessarily contain sections for all interfaces with active
|
||||
# SQM instances, so use the ACTIVE_STATE_FILES to detect the interfaces on which to stop SQM.
|
||||
# Currently the .qos scripts start with stopping any existing traffic shaping so this should not
|
||||
# effectively change anything...
|
||||
for STATE_FILE in ${PROTO_STATE_FILE_LIST} ; do
|
||||
if [ -f ${STATE_FILE} ] ;
|
||||
then
|
||||
STATE_FILE_BASE_NAME=$( basename ${STATE_FILE} )
|
||||
CURRENT_INTERFACE=${STATE_FILE_BASE_NAME:${#ACTIVE_STATE_PREFIX}:$(( ${#STATE_FILE_BASE_NAME} - ${#ACTIVE_STATE_PREFIX} ))}
|
||||
logger -t SQM -s "${0} Stopping SQM on interface: ${CURRENT_INTERFACE}"
|
||||
/usr/lib/sqm/stop.sh ${CURRENT_INTERFACE}
|
||||
rm ${STATE_FILE} # well, we stop it so it is not running anymore and hence no active state file needed...
|
||||
fi
|
||||
done
|
||||
|
||||
config_load sqm
|
||||
|
||||
run_simple_qos() {
|
||||
local section="$1"
|
||||
export IFACE=$(config_get "$section" interface)
|
||||
|
||||
# If called explicitly for one interface only , so ignore anything else
|
||||
[ -n "${START_ON_IF}" -a "$START_ON_IF" != "$IFACE" ] && return
|
||||
#logger -t SQM -s "marching on..."
|
||||
|
||||
ACTIVE_STATE_FILE_FQN="${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}${IFACE}" # this marks interfaces as active with SQM
|
||||
[ -f "${ACTIVE_STATE_FILE_FQN}" ] && logger -t SQM -s "Uh, oh, ${ACTIVE_STATE_FILE_FQN} should already be stopped." # Not supposed to happen
|
||||
|
||||
if [ $(config_get "$section" enabled) -ne 1 ];
|
||||
then
|
||||
if [ -f "${ACTIVE_STATE_FILE_FQN}" ];
|
||||
then
|
||||
# this should not be possible, delete after testing
|
||||
local SECTION_STOP="stop" # it seems the user just de-selected enable, so stop the active SQM
|
||||
else
|
||||
logger -t SQM -s "${0} SQM for interface ${IFACE} is not enabled, skipping over..."
|
||||
return 0 # since SQM is not active on the current interface nothing to do here
|
||||
fi
|
||||
fi
|
||||
|
||||
export UPLINK=$(config_get "$section" upload)
|
||||
export DOWNLINK=$(config_get "$section" download)
|
||||
export LLAM=$(config_get "$section" linklayer_adaptation_mechanism)
|
||||
export LINKLAYER=$(config_get "$section" linklayer)
|
||||
export OVERHEAD=$(config_get "$section" overhead)
|
||||
export STAB_MTU=$(config_get "$section" tcMTU)
|
||||
export STAB_TSIZE=$(config_get "$section" tcTSIZE)
|
||||
export STAB_MPU=$(config_get "$section" tcMPU)
|
||||
export ILIMIT=$(config_get "$section" ilimit)
|
||||
export ELIMIT=$(config_get "$section" elimit)
|
||||
export ITARGET=$(config_get "$section" itarget)
|
||||
export ETARGET=$(config_get "$section" etarget)
|
||||
export IECN=$(config_get "$section" ingress_ecn)
|
||||
export EECN=$(config_get "$section" egress_ecn)
|
||||
export IQDISC_OPTS=$(config_get "$section" iqdisc_opts)
|
||||
export EQDISC_OPTS=$(config_get "$section" eqdisc_opts)
|
||||
export TARGET=$(config_get "$section" target)
|
||||
export SQUASH_DSCP=$(config_get "$section" squash_dscp)
|
||||
export SQUASH_INGRESS=$(config_get "$section" squash_ingress)
|
||||
|
||||
export QDISC=$(config_get "$section" qdisc)
|
||||
export SCRIPT=/usr/lib/sqm/$(config_get "$section" script)
|
||||
|
||||
# # there should be nothing left to stop, so just avoid calling the script
|
||||
if [ "$STOP" == "stop" -o "$SECTION_STOP" == "stop" ];
|
||||
then
|
||||
# /usr/lib/sqm/stop.sh
|
||||
# [ -f ${ACTIVE_STATE_FILE_FQN} ] && rm ${ACTIVE_STATE_FILE_FQN} # conditional to avoid errors ACTIVE_STATE_FILE_FQN does not exist anymore
|
||||
# $(config_set "$section" enabled 0) # this does not save to the config file only to the loaded memory representation
|
||||
logger -t SQM -s "${0} SQM qdiscs on ${IFACE} removed"
|
||||
return 0
|
||||
fi
|
||||
# in case of spurious hotplug events, try double check whether the interface is really up
|
||||
if [ ! -d /sys/class/net/${IFACE} ] ;
|
||||
then
|
||||
echo "${IFACE} does currently not exist, not even trying to start SQM on nothing." > /dev/kmsg
|
||||
logger -t SQM -s "${IFACE} does currently not exist, not even trying to start SQM on nothing."
|
||||
return 0
|
||||
fi
|
||||
|
||||
logger -t SQM -s "${0} Queue Setup Script: ${SCRIPT}"
|
||||
[ -x "$SCRIPT" ] && { $SCRIPT ; touch ${ACTIVE_STATE_FILE_FQN}; }
|
||||
}
|
||||
|
||||
config_foreach run_simple_qos
|
218
net/sqm-scripts/files/usr/lib/sqm/simple.qos
Executable file
218
net/sqm-scripts/files/usr/lib/sqm/simple.qos
Executable file
|
@ -0,0 +1,218 @@
|
|||
#!/bin/sh
|
||||
# Cero3 Shaper
|
||||
# A 3 bin tc_codel and ipv6 enabled shaping script for
|
||||
# ethernet gateways
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
# Compared to the complexity that debloat had become
|
||||
# this cleanly shows a means of going from diffserv marking
|
||||
# to prioritization using the current tools (ip(6)tables
|
||||
# and tc. I note that the complexity of debloat exists for
|
||||
# a reason, and it is expected that script is run first
|
||||
# to setup various other parameters such as BQL and ethtool.
|
||||
# (And that the debloat script has setup the other interfaces)
|
||||
|
||||
# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
|
||||
|
||||
. /usr/lib/sqm/functions.sh
|
||||
|
||||
ipt_setup() {
|
||||
|
||||
ipt -t mangle -N QOS_MARK_${IFACE}
|
||||
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -j MARK --set-mark 0x2${IPT_MASK_STRING}
|
||||
# You can go further with classification but...
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS1 -j MARK --set-mark 0x3${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS6 -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class EF -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class AF42 -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m tos --tos Minimize-Delay -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
|
||||
# and it might be a good idea to do it for udp tunnels too
|
||||
|
||||
# Turn it on. Preserve classification if already performed
|
||||
|
||||
#sm: is it correct to do this in $IFACE? Should ingress not be on $DEV? since HTB acts on $DEV?
|
||||
# SQUASH also does not work on $DEV (that is the IFB will still see the incoming ToS bits whether we squash or not)
|
||||
# SQUASH is still useful to protect internal machines...
|
||||
if [ "$SQUASH_DSCP" = "1" ]
|
||||
then
|
||||
sqm_logger "Squashing differentiated services code points (DSCP) from ingress."
|
||||
ipt -t mangle -I PREROUTING -i $IFACE -m dscp ! --dscp 0 -j DSCP --set-dscp-class be
|
||||
else
|
||||
sqm_logger "Keeping differentiated services code points (DSCP) from ingress."
|
||||
ipt -t mangle -A PREROUTING -i $IFACE -m mark --mark 0x00${IPT_MASK_STRING} -g QOS_MARK_${IFACE}
|
||||
fi
|
||||
|
||||
ipt -t mangle -A POSTROUTING -o $IFACE -m mark --mark 0x00${IPT_MASK_STRING} -g QOS_MARK_${IFACE}
|
||||
|
||||
# The Syn optimization was nice but fq_codel does it for us
|
||||
# ipt -t mangle -A PREROUTING -i s+ -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x01
|
||||
# Not sure if this will work. Encapsulation is a problem period
|
||||
|
||||
ipt -t mangle -I PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2${IPT_MASK_STRING} # tcp tunnels need ordering
|
||||
|
||||
# Emanating from router, do a little more optimization
|
||||
# but don't bother with it too much.
|
||||
|
||||
ipt -t mangle -A OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
|
||||
|
||||
#Not clear if the second line is needed
|
||||
#ipt -t mangle -A OUTPUT -o $IFACE -g QOS_MARK_${IFACE}
|
||||
|
||||
}
|
||||
|
||||
|
||||
# TC rules
|
||||
|
||||
egress() {
|
||||
|
||||
CEIL=${UPLINK}
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_mtu $IFACE $CEIL`"
|
||||
|
||||
$TC qdisc del dev $IFACE root 2> /dev/null
|
||||
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:11 htb $LQ rate 128kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
|
||||
|
||||
$TC qdisc add dev $IFACE parent 1:11 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${PRIO_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:12 handle 120: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BE_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:13 handle 130: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
|
||||
|
||||
|
||||
# Need a catchall rule
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# FIXME should probably change the filter here to do pre-nat
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 2 handle 2 fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 3 handle 3 fw classid 1:13
|
||||
|
||||
# ipv6 support. Note that the handle indicates the fw mark bucket that is looked for
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 4 handle 1 fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 5 handle 2 fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 6 handle 3 fw classid 1:13
|
||||
|
||||
# Arp traffic
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol arp prio 7 handle 1 fw classid 1:11
|
||||
|
||||
# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
|
||||
# better instead
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 8 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 9 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
|
||||
#diffserv $IFACE
|
||||
|
||||
}
|
||||
|
||||
ingress() {
|
||||
|
||||
CEIL=$DOWNLINK
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_mtu $IFACE $CEIL`"
|
||||
|
||||
$TC qdisc del dev $IFACE handle ffff: ingress 2> /dev/null
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
$TC qdisc del dev $DEV root 2> /dev/null
|
||||
|
||||
if [ "$SQUASH_INGRESS" = "1" ]
|
||||
then
|
||||
sqm_logger "Do not perform DSCP based filtering on ingress. (1-tier classification)"
|
||||
# Revert to no dscp based filtering
|
||||
$TC qdisc del dev $DEV root 2>/dev/null
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
|
||||
|
||||
else
|
||||
sqm_logger "Perform DSCP based filtering on ingress. (3-tier classification)"
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:11 htb $LQ rate 32kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
|
||||
|
||||
# I'd prefer to use a pre-nat filter but that causes permutation...
|
||||
|
||||
$TC qdisc add dev $DEV parent 1:11 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 500` `get_flows ${PRIO_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:12 handle 120: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 1500` `get_flows ${BE_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:13 handle 130: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
|
||||
|
||||
diffserv $DEV
|
||||
|
||||
fi
|
||||
|
||||
ifconfig $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
do_modules
|
||||
ipt_setup
|
||||
|
||||
if [ "$UPLINK" -ne 0 ];
|
||||
then
|
||||
egress
|
||||
sqm_logger "egress shaping activated"
|
||||
else
|
||||
sqm_logger "egress shaping deactivated"
|
||||
tc qdisc del dev $IFACE root 2> /dev/null
|
||||
fi
|
||||
if [ "$DOWNLINK" -ne 0 ];
|
||||
then
|
||||
ingress
|
||||
sqm_logger "ingress shaping activated"
|
||||
else
|
||||
sqm_logger "ingress shaping deactivated"
|
||||
tc qdisc del dev $DEV root 2> /dev/null
|
||||
tc qdisc del dev $IFACE ingress 2> /dev/null
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
|
||||
# Comments
|
||||
# This does the right thing with ipv6 traffic.
|
||||
# It also tries to leverage diffserv to some sane extent. In particular,
|
||||
# the 'priority' queue is limited to 33% of the total, so EF, and IMM traffic
|
||||
# cannot starve other types. The rfc suggested 30%. 30% is probably
|
||||
# a lot in today's world.
|
||||
|
||||
# Flaws
|
||||
# Many!
|
1
net/sqm-scripts/files/usr/lib/sqm/simple.qos.help
Normal file
1
net/sqm-scripts/files/usr/lib/sqm/simple.qos.help
Normal file
|
@ -0,0 +1 @@
|
|||
BW-limited three-tier prioritisation scheme with fq_codel on each queue. (default)
|
398
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos
Normal file
398
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos
Normal file
|
@ -0,0 +1,398 @@
|
|||
#!/bin/sh
|
||||
# Cero3 Shaper
|
||||
# A 3 bin tc_codel and ipv6 enabled shaping script for
|
||||
# ethernet gateways
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
# Compared to the complexity that debloat had become
|
||||
# this cleanly shows a means of going from diffserv marking
|
||||
# to prioritization using the current tools (ip(6)tables
|
||||
# and tc. I note that the complexity of debloat exists for
|
||||
# a reason, and it is expected that script is run first
|
||||
# to setup various other parameters such as BQL and ethtool.
|
||||
# (And that the debloat script has setup the other interfaces)
|
||||
|
||||
# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
|
||||
|
||||
#sm: Goal to create a set of tc filters that also apply on pppoe encapsulated packets
|
||||
# but having multiple filters run in succession is slow, so look at tc filter hashing
|
||||
# (this should help cut down the number of OPs per packet considerably)
|
||||
|
||||
|
||||
. /usr/lib/sqm/functions.sh
|
||||
#sqm_logger IPT_MASK: ${IPT_MASK_STRING}
|
||||
ipt_setup() {
|
||||
|
||||
ipt -t mangle -N QOS_MARK_${IFACE}
|
||||
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -j MARK --set-mark 0x2${IPT_MASK_STRING}
|
||||
# You can go further with classification but...
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS1 -j MARK --set-mark 0x3${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS6 -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class EF -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class AF42 -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m tos --tos Minimize-Delay -j MARK --set-mark 0x1${IPT_MASK_STRING}
|
||||
|
||||
# and it might be a good idea to do it for udp tunnels too
|
||||
|
||||
# Turn it on. Preserve classification if already performed
|
||||
|
||||
if [ "$SQUASH_DSCP" = "1" ]
|
||||
then
|
||||
sqm_logger "Squashing differentiated services code points (DSCP) from ingress."
|
||||
ipt -t mangle -I PREROUTING -i $IFACE -m dscp ! --dscp 0 -j DSCP --set-dscp-class be
|
||||
else
|
||||
sqm_logger "Keeping differentiad services code points (DSCP) from ingress."
|
||||
ipt -t mangle -A PREROUTING -i $IFACE -m mark --mark 0x00${IPT_MASK_STRING} -g QOS_MARK_${IFACE}
|
||||
fi
|
||||
|
||||
ipt -t mangle -A POSTROUTING -o $IFACE -m mark --mark 0x00${IPT_MASK_STRING} -g QOS_MARK_${IFACE}
|
||||
|
||||
# The Syn optimization was nice but fq_codel does it for us
|
||||
# ipt -t mangle -A PREROUTING -i s+ -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x01
|
||||
# Not sure if this will work. Encapsulation is a problem period
|
||||
|
||||
ipt -t mangle -I PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2${IPT_MASK_STRING} # tcp tunnels need ordering
|
||||
|
||||
# Emanating from router, do a little more optimization
|
||||
# but don't bother with it too much.
|
||||
|
||||
ipt -t mangle -A OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
|
||||
|
||||
#Not clear if the second line is needed
|
||||
#ipt -t mangle -A OUTPUT -o $IFACE -g QOS_MARK_${IFACE}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MYBURST=1600 #sm: make burst and cburst as well as quantum configurable for ingress and egress in the GUI
|
||||
# TC rules
|
||||
|
||||
egress() {
|
||||
|
||||
CEIL=${UPLINK}
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for priority
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_mtu $IFACE $CEIL`"
|
||||
HTB_BURSTS="burst ${MYBURST} cburst ${MYBURST}"
|
||||
|
||||
$TC qdisc del dev $IFACE root 2> /dev/null
|
||||
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ ${HTB_BURSTS} rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ ${HTB_BURSTS} rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:11 htb $LQ ${HTB_BURSTS} rate 128kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:12 htb $LQ ${HTB_BURSTS} rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:13 htb $LQ ${HTB_BURSTS} rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
|
||||
|
||||
$TC qdisc add dev $IFACE parent 1:11 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${PRIO_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:12 handle 120: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BE_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:13 handle 130: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
|
||||
|
||||
|
||||
#sm: for testing we need a band to collect PPPOEd packets
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:14 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $IFACE parent 1:14 handle 140: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
|
||||
|
||||
|
||||
# Need a catchall rule (should also match VLANs and PPPoE packets)
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# FIXME should probably change the filter here to do pre-nat
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 2 handle 2 fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 3 handle 3 fw classid 1:13
|
||||
|
||||
# ipv6 support. Note that the handle indicates the fw mark bucket that is looked for
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 4 handle 1 fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 5 handle 2 fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 6 handle 3 fw classid 1:13
|
||||
|
||||
# Arp traffic
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol arp prio 7 handle 1 fw classid 1:11
|
||||
|
||||
# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
|
||||
# better instead
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 8 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 9 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
|
||||
|
||||
|
||||
|
||||
# PPPoE encapsulated packets traversing the router (e.g.: the router does PPPoE termination but we shape
|
||||
# on the underlaying ethernet interface instead of the pppoe device)
|
||||
|
||||
PPPOE_SESSION_ETHERTYPE="0x8864"
|
||||
PPPOE_DISCOVERY_ETHERTYPE="0x8863"
|
||||
PPP_PROTO_IP4="0x0021"
|
||||
PPP_PROTO_IP6="0x0057"
|
||||
ARP_PROTO_IP4="0x0806"
|
||||
|
||||
# NOTE it seems prio can not be reused?
|
||||
#$TC filter add dev $IFACE protocol 0x8863 parent 1:0 prio 1 u32 flowid 1:14
|
||||
# PPPoE can be selected for by ether_type, the encapsulated IP version from the PPP (0x0021 IPv4, 0x0057 IPv6)
|
||||
#U32_PREFIX="$TC filter add dev $IFACE" parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE}"
|
||||
|
||||
#BE: 1:12 is the default anyway, but this will catch all non marked packets
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 400 u32 \
|
||||
# match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
# match u8 0x00 0xfb at 9 \
|
||||
# flowid 1:12
|
||||
|
||||
#AF42
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 401 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0x90 0xfc at 9 \
|
||||
flowid 1:11
|
||||
#EF
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 402 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0xb8 0xfc at 9 \
|
||||
flowid 1:11
|
||||
#CS1
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 403 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0x20 0xf0 at 9 \
|
||||
flowid 1:13
|
||||
#IMM
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 404 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0x10 0xf0 at 9 \
|
||||
flowid 1:11
|
||||
#CS3
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 405 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0xc0 0xf0 at 9 \
|
||||
flowid 1:11
|
||||
#CS6
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 406 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0xe0 0xf0 at 9 \
|
||||
flowid 1:11
|
||||
|
||||
|
||||
## Arp traffic
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 409 u32 \
|
||||
# match u16 ${ARP_PROTO_IP4} 0xffff at 6 \
|
||||
# flowid 1:14
|
||||
|
||||
# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
|
||||
# better instead; sm: really only deprio echo requestst and echo replies instead?
|
||||
# ECHO request, the rest stays in best effort
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 410 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0x01 0xff at 17 \
|
||||
match u8 0x08 0xff at 28 \
|
||||
flowid 1:13
|
||||
# ECHO reply
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 410 u32 \
|
||||
match u16 ${PPP_PROTO_IP4} 0xffff at 6 \
|
||||
match u8 0x01 0xff at 17 \
|
||||
match u8 0x00 0xff at 28 \
|
||||
flowid 1:13
|
||||
|
||||
## ICMPv6 133-137 (NDP) is equivalent to IPv4 ARP, so only push echo request and reply into the bulk class
|
||||
## 133
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u8 0x85 0xff at 48 \
|
||||
# match u8 0x3a 0xff at 14 \
|
||||
# flowid 1:14
|
||||
## 134
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u8 0x86 0xff at 48 \
|
||||
# match u8 0x3a 0xff at 14 \
|
||||
# flowid 1:14
|
||||
## 135
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u8 0x87 0xff at 48 \
|
||||
# match u8 0x3a 0xff at 14 \
|
||||
# flowid 1:14
|
||||
## 136
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u8 0x88 0xff at 48 \
|
||||
# match u8 0x3a 0xff at 14 \
|
||||
# flowid 1:14
|
||||
## 137
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u8 0x89 0xff at 48 \
|
||||
# match u8 0x3a 0xff at 14 \
|
||||
# flowid 1:14
|
||||
|
||||
# ICMPv6 echo request
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u8 0x3a 0xff at 14 \
|
||||
match u8 0x80 0xff at 48 \
|
||||
flowid 1:13
|
||||
# ICMPv6 echo reply
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 610 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u8 0x3a 0xff at 14 \
|
||||
match u8 0x81 0xff at 48 \
|
||||
flowid 1:13
|
||||
|
||||
|
||||
|
||||
|
||||
#IPV6
|
||||
#BE: careful, will override ICMP
|
||||
#$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 600 u32 \
|
||||
# match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
# match u16 0x0000 0x0fb0 at 8 \
|
||||
# flowid 1:12
|
||||
#AF42
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 601 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0900 0x0fc0 at 8 \
|
||||
flowid 1:11
|
||||
#EF
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 602 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0b80 0x0fc0 at 8 \
|
||||
flowid 1:11
|
||||
#CS1
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 603 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0200 0x0fc0 at 8 \
|
||||
flowid 1:13
|
||||
#IMM
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 604 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0100 0x0fc0 at 8 \
|
||||
flowid 1:11
|
||||
#CS3
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 605 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0c00 0x0fc0 at 8 \
|
||||
flowid 1:11
|
||||
#CS6
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ${PPPOE_SESSION_ETHERTYPE} prio 606 u32 \
|
||||
match u16 ${PPP_PROTO_IP6} 0xffff at 6 \
|
||||
match u16 0x0e00 0x0fc0 at 8 \
|
||||
flowid 1:11
|
||||
|
||||
|
||||
|
||||
|
||||
#diffserv $IFACE
|
||||
|
||||
}
|
||||
|
||||
ingress() {
|
||||
|
||||
CEIL=$DOWNLINK
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_mtu $IFACE $CEIL`"
|
||||
HTB_BURSTS="burst ${MYBURST} cburst ${MYBURST}"
|
||||
|
||||
$TC qdisc del dev $IFACE handle ffff: ingress 2> /dev/null
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
$TC qdisc del dev $DEV root 2> /dev/null
|
||||
|
||||
if [ "$SQUASH_INGRESS" = "1" ]
|
||||
then
|
||||
sqm_logger "Do not perform DSCP based filtering on ingress. (1-tier classification)"
|
||||
# Revert to no dscp based filtering
|
||||
$TC qdisc del dev $DEV root 2>/dev/null
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ ${HTB_BURSTS} rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ ${HTB_BURSTS} rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
|
||||
|
||||
else
|
||||
sqm_logger "Perform DSCP based filtering on ingress. (3-tier classification)"
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ ${HTB_BURSTS} rate ${CEIL}kbit ceil ${CEIL}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ ${HTB_BURSTS} rate ${CEIL}kbit ceil ${CEIL}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:11 htb $LQ ${HTB_BURSTS} rate 32kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:12 htb $LQ ${HTB_BURSTS} rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:13 htb $LQ ${HTB_BURSTS} rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
|
||||
|
||||
# I'd prefer to use a pre-nat filter but that causes permutation...
|
||||
|
||||
$TC qdisc add dev $DEV parent 1:11 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 500` `get_flows ${PRIO_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:12 handle 120: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 1500` `get_flows ${BE_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:13 handle 130: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
|
||||
|
||||
#sm: for PPPoE packet testing
|
||||
$TC class add dev $DEV parent 1:1 classid 1:14 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit prio 3 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $DEV parent 1:14 handle 140: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
|
||||
|
||||
|
||||
|
||||
#diffserv $DEV
|
||||
diffserv_pppoe $DEV
|
||||
|
||||
fi
|
||||
|
||||
ifconfig $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
do_modules
|
||||
ipt_setup
|
||||
|
||||
if [ "$UPLINK" -ne 0 ];
|
||||
then
|
||||
egress
|
||||
sqm_logger "egress shaping activated"
|
||||
else
|
||||
sqm_logger "egress shaping deactivated"
|
||||
tc qdisc del dev $IFACE root 2> /dev/null
|
||||
fi
|
||||
if [ "$DOWNLINK" -ne 0 ];
|
||||
then
|
||||
ingress
|
||||
sqm_logger "ingress shaping activated"
|
||||
else
|
||||
sqm_logger "ingress shaping deactivated"
|
||||
tc qdisc del dev $DEV root 2> /dev/null
|
||||
tc qdisc del dev $IFACE ingress 2> /dev/null
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
|
||||
# Comments
|
||||
# This does the right thing with ipv6 traffic.
|
||||
# It also tries to leverage diffserv to some sane extent. In particular,
|
||||
# the 'priority' queue is limited to 33% of the total, so EF, and IMM traffic
|
||||
# cannot starve other types. The rfc suggested 30%. 30% is probably
|
||||
# a lot in today's world.
|
||||
|
||||
# Flaws
|
||||
# Many!
|
2
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos.help
Normal file
2
net/sqm-scripts/files/usr/lib/sqm/simple_pppoe.qos.help
Normal file
|
@ -0,0 +1,2 @@
|
|||
BW-limited three-tier prioritisation scheme with fq_codel on each queue. Temporary version to implement shaping
|
||||
of pass through PPPOE encapsulated packets.
|
84
net/sqm-scripts/files/usr/lib/sqm/simplest.qos
Normal file
84
net/sqm-scripts/files/usr/lib/sqm/simplest.qos
Normal file
|
@ -0,0 +1,84 @@
|
|||
#!/bin/sh
|
||||
# Cero3 Simple Shaper
|
||||
# A 1 bin tc_codel and ipv6 enabled shaping script for
|
||||
# ethernet gateways. This is nearly the simplest possible
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
. /usr/lib/sqm/functions.sh
|
||||
sqm_logger "Starting simplest.qos"
|
||||
|
||||
egress() {
|
||||
|
||||
LQ="quantum `get_mtu $IFACE ${UPLINK}`"
|
||||
|
||||
$TC qdisc del dev $IFACE root 2>/dev/null
|
||||
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit prio 0 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $IFACE parent 1:10 handle 110: $QDISC `get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_flows ${UPLINK}` ${EQDISC_OPTS}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ingress() {
|
||||
sqm_logger "ingress"
|
||||
$TC qdisc del dev $IFACE handle ffff: ingress 2>/dev/null
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
LQ="quantum `get_mtu $IFACE ${DOWNLINK}`"
|
||||
|
||||
$TC qdisc del dev $DEV root 2>/dev/null
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit prio 0 `get_htb_adsll_string`
|
||||
|
||||
# FIXME: I'd prefer to use a pre-nat filter but we need to detect if nat is on this interface
|
||||
# AND we need to permute by a random number which we can't do from userspace filters
|
||||
|
||||
# Most high rate flows are REALLY close. This stomps on those harder, but hurts on high rate long distance
|
||||
#$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC limit $LIMIT $ECN interval 20ms target 3ms `get_flows ${DOWNLINK}`
|
||||
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC `get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
|
||||
|
||||
ifconfig $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
do_modules
|
||||
|
||||
if [ "$UPLINK" -ne 0 ];
|
||||
then
|
||||
egress
|
||||
sqm_logger "egress shaping activated"
|
||||
else
|
||||
sqm_logger "egress shaping deactivated"
|
||||
tc qdisc del dev $IFACE root 2> /dev/null
|
||||
fi
|
||||
if [ "$DOWNLINK" -ne 0 ];
|
||||
then
|
||||
ingress
|
||||
sqm_logger "ingress shaping activated"
|
||||
else
|
||||
sqm_logger "ingress shaping deactivated"
|
||||
tc qdisc del dev $DEV root 2> /dev/null
|
||||
tc qdisc del dev $IFACE ingress 2> /dev/null
|
||||
fi
|
||||
|
||||
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
|
||||
# Comments
|
||||
# This does the right thing with ipv6 traffic.
|
||||
# Flaws
|
||||
# Many!
|
1
net/sqm-scripts/files/usr/lib/sqm/simplest.qos.help
Normal file
1
net/sqm-scripts/files/usr/lib/sqm/simplest.qos.help
Normal file
|
@ -0,0 +1 @@
|
|||
Simplest possible configuration: HTB rate limiter with your qdisc attached.
|
42
net/sqm-scripts/files/usr/lib/sqm/stop.sh
Normal file
42
net/sqm-scripts/files/usr/lib/sqm/stop.sh
Normal file
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
# allow passing in the IFACE as first command line argument
|
||||
[ ! -z ${1} ] && IFACE=${1}
|
||||
# now IFACE is defined so we can source functions.sh without creating a spurious ifb4ge00
|
||||
. /usr/lib/sqm/functions.sh
|
||||
# sqm_logger is defined in functions.sh...
|
||||
sqm_logger "${0}: Stopping ${IFACE}"
|
||||
|
||||
# make sure to only delete the ifb associated with the current interface
|
||||
CUR_IFB=$( get_ifb_associated_with_if ${IFACE} )
|
||||
|
||||
sqm_stop() {
|
||||
tc qdisc del dev $IFACE ingress 2> /dev/null
|
||||
tc qdisc del dev $IFACE root 2> /dev/null
|
||||
[ ! -z "$CUR_IFB" ] && tc qdisc del dev $CUR_IFB root 2> /dev/null
|
||||
[ ! -z "$CUR_IFB" ] && sqm_logger "${0}: ${CUR_IFB} shaper deleted"
|
||||
}
|
||||
|
||||
ipt_stop() {
|
||||
[ ! -z "$CUR_IFB" ] && ipt -t mangle -D POSTROUTING -o $CUR_IFB -m mark --mark 0x00 -g QOS_MARK_${IFACE}
|
||||
ipt -t mangle -D POSTROUTING -o $IFACE -m mark --mark 0x00 -g QOS_MARK_${IFACE}
|
||||
ipt -t mangle -D PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2
|
||||
ipt -t mangle -D OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
|
||||
ipt -t mangle -F QOS_MARK_${IFACE}
|
||||
ipt -t mangle -X QOS_MARK_${IFACE}
|
||||
}
|
||||
|
||||
|
||||
sqm_stop
|
||||
ipt_stop
|
||||
[ ! -z "$CUR_IFB" ] && ifconfig ${CUR_IFB} down
|
||||
[ ! -z "$CUR_IFB" ] && ip link delete ${CUR_IFB} type ifb
|
||||
[ ! -z "$CUR_IFB" ] && sqm_logger "${0}: ${CUR_IFB} interface deleted"
|
||||
|
||||
exit 0
|
Loading…
Reference in a new issue