sqm-scripts: Bump to v1.0.3.

Backported changes from master.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
This commit is contained in:
Toke Høiland-Jørgensen 2015-09-03 15:37:11 +02:00
parent a77f6728a4
commit c36d2e8735
17 changed files with 50 additions and 1772 deletions

View File

@ -1,67 +0,0 @@
#
# 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:=4
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))

View File

@ -1,238 +0,0 @@
--[[
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 this SQM instance."))
e.rmempty = false
-- sm: following jow's advise, be helpful to the user and enable
-- sqm's init script if even a single sm instance/interface
-- is enabled; this is unexpected in that the init script gets
-- enabled as soon as at least one sqm instance is enabled
-- and that state is saved, so it does not require "Save & Apply"
-- to effect the init scripts.
-- the implementation was inpired/lifted from
-- https://github.com/openwrt/luci/blob/master/applications/luci-app-minidlna/luasrc/model/cbi/minidlna.lua
function e.write(self, section, value)
if value == "1" then
luci.sys.init.enable("sqm")
m.message = translate("The SQM GUI has just enabled the sqm initscript on your behalf. Remember to disable the sqm initscript manually under System Startup menu in case this change was not wished for.")
-- luci.sys.call("/etc/init.d/sqm start >/dev/null")
-- else
-- luci.sys.call("/etc/init.d/sqm stop >/dev/null")
-- luci.sys.init.disable("sqm")
end
return Flag.write(self, section, value)
end
-- TODO: inform the user what we just did...
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) set to 0 to selectively disable ingress shaping:"))
dl.datatype = "and(uinteger,min(0))"
dl.rmempty = false
ul = s:taboption("tab_basic", Value, "upload", translate("Upload speed (kbit/s) (egress) set to 0 to selectively disable egress shaping:"))
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 and Use Advanced Configuration. Advanced options will only be used as long as this box is checked."))
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 and Use Dangerous Configuration. Dangerous options will only be used as long as this box is checked."))
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 automatic selection, put in the word default for the qdisc's default."))
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 automatic selection, put in the word default for the qdisc's default."))
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). Advanced options will only be used as long as this box is checked."))
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

View File

@ -1,26 +0,0 @@
--[[
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

View File

@ -1,12 +0,0 @@
#!/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

View File

@ -8,11 +8,16 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=sqm-scripts
PKG_VERSION:=8
PKG_RELEASE:=4
PKG_SOURCE_VERSION:=39005a11405ca68bb80d42855ff7ea641a9769b9
PKG_VERSION:=1.0.3
PKG_RELEASE:=1
PKG_LICENSE:=GPLv2
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE).tar.xz
PKG_SOURCE_URL:=git://github.com/tohojo/sqm-scripts.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE)
include $(INCLUDE_DIR)/package.mk
@ -32,28 +37,51 @@ endef
define Package/sqm-scripts/conffiles
/etc/config/sqm
endef
define Build/Prepare
endef
define Build/Configure
endef
define Build/Compile
/etc/sqm/sqm.conf
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/
make -C $(PKG_BUILD_DIR) DESTDIR=$(1) PLATFORM=openwrt install
endef
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 Package/luci-app-sqm/install
make -C $(PKG_BUILD_DIR) DESTDIR=$(1) PLATFORM=openwrt install-luci
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,sqm-scripts))
$(eval $(call BuildPackage,luci-app-sqm))

View File

@ -1,16 +0,0 @@
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'

View File

@ -1,3 +0,0 @@
#!/bin/sh
[ "$ACTION" = ifup ] && /etc/init.d/sqm enabled && /usr/lib/sqm/run.sh start ${DEVICE}

View File

@ -1,23 +0,0 @@
#!/bin/sh /etc/rc.common
START=50
reload()
{
/usr/lib/sqm/run.sh start
}
restart()
{
reload
}
start()
{
reload
}
stop()
{
/usr/lib/sqm/run.sh stop
}

View File

@ -1,486 +0,0 @@
# 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
# empty field in GUI or undefined GUI variable now defaults to auto
if [ -z "${CUR_TARGET_VALUE}" -a -z "${CUR_TARGET_UNIT}" ];
then
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"
sqm_logger "get_target defaulting to auto."
else
sqm_logger "required link bandwidth in kbps not passed to get_target()."
fi
fi
# but still allow explicit use of the keyword auto for backward compatibility
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
case ${CUR_TARGET_UNIT} in
default|Default|DEFAULT)
if [ ! -z "${CUR_LINK_KBPS}" ];
then
CUR_TARGET_STRING="" # return nothing so the default target is not over-ridden...
AUTO_TARGET="1"
#sqm_logger "get_target using qdisc default, no explicit target string passed."
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 one of the strings auto or default."
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))
}

View File

@ -1,133 +0,0 @@
#!/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}
START_ON_IF=$2 # only process this interface
# TODO if $2 is empty select all interfaces with running sqm instance
if [ -z ${START_ON_IF} ] ;
then
# find all interfaces with active sqm instance
logger -t SQM -s "Trying to start/stop SQM on all interfaces."
PROTO_STATE_FILE_LIST=$( ls ${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}* 2> /dev/null )
else
# only try to restart the just hotplugged interface, so reduce the list of interfaces to stop to the specified one
logger -t SQM -s "Trying to start/stop SQM on interface ${START_ON_IF}"
PROTO_STATE_FILE_LIST=${ACTIVE_STATE_FILE_DIR}/${ACTIVE_STATE_PREFIX}${START_ON_IF}
fi
case ${1} in
start)
# just run through, same as passing no argument
;;
stop)
logger -t SQM -s "run.sh stop"
STOP=$1
;;
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

View File

@ -1,218 +0,0 @@
#!/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!

View File

@ -1 +0,0 @@
BW-limited three-tier prioritisation scheme with fq_codel on each queue. (default)

View File

@ -1,398 +0,0 @@
#!/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!

View File

@ -1,2 +0,0 @@
BW-limited three-tier prioritisation scheme with fq_codel on each queue. Temporary version to implement shaping
of pass through PPPOE encapsulated packets.

View File

@ -1,84 +0,0 @@
#!/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!

View File

@ -1 +0,0 @@
Simplest possible configuration: HTB rate limiter with your qdisc attached.

View File

@ -1,42 +0,0 @@
#!/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