luci-app-qos-gargoyle: import from core
This is only available for this branch. Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
parent
8704d4af19
commit
7ad4177396
22
package/ctcgfw/luci-app-qos-gargoyle/Makefile
Normal file
22
package/ctcgfw/luci-app-qos-gargoyle/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-qos-gargoyle
|
||||
PKG_VERSION:=1.3.6
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=Xingwang Liao <kuoruan@gmail.com>
|
||||
|
||||
LUCI_TITLE:=LuCI Support for Gargoyle QoS
|
||||
LUCI_DEPENDS:=+qos-gargoyle
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
@ -0,0 +1,100 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.qos_gargoyle", package.seeall)
|
||||
|
||||
local util = require "luci.util"
|
||||
local http = require "luci.http"
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/qos_gargoyle") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle"},
|
||||
firstchild(), _("Gargoyle QoS"), 60)
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "global"},
|
||||
cbi("qos_gargoyle/global"), _("Global Settings"), 10)
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "upload"},
|
||||
cbi("qos_gargoyle/upload"), _("Upload Settings"), 20)
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "upload", "class"},
|
||||
cbi("qos_gargoyle/upload_class")).leaf = true
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "upload", "rule"},
|
||||
cbi("qos_gargoyle/upload_rule")).leaf = true
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "download"},
|
||||
cbi("qos_gargoyle/download"), _("Download Settings"), 30)
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "download", "class"},
|
||||
cbi("qos_gargoyle/download_class")).leaf = true
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "download", "rule"},
|
||||
cbi("qos_gargoyle/download_rule")).leaf = true
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "troubleshooting"},
|
||||
template("qos_gargoyle/troubleshooting"), _("Troubleshooting"), 40)
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "troubleshooting", "data"},
|
||||
call("action_troubleshooting_data"))
|
||||
|
||||
entry({"admin", "network", "qos_gargoyle", "load_data"},
|
||||
call("action_load_data")).leaf = true
|
||||
end
|
||||
|
||||
function action_troubleshooting_data()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local i18n = require "luci.i18n"
|
||||
|
||||
local data = {}
|
||||
|
||||
local monenabled = uci:get("qos_gargoyle", "download", "qos_monenabled") or "false"
|
||||
|
||||
local show_data = util.trim(util.exec("/etc/init.d/qos_gargoyle show 2>/dev/null"))
|
||||
if show_data == "" then
|
||||
show_data = i18n.translate("No data found")
|
||||
end
|
||||
|
||||
data.show = show_data
|
||||
|
||||
local mon_data
|
||||
if monenabled == "true" then
|
||||
mon_data = util.trim(util.exec("cat /tmp/qosmon.status 2>/dev/null"))
|
||||
|
||||
if mon_data == "" then
|
||||
mon_data = i18n.translate("No data found")
|
||||
end
|
||||
else
|
||||
mon_data = i18n.translate("\"Active Congestion Control\" not enabled")
|
||||
end
|
||||
|
||||
data.mon = mon_data
|
||||
|
||||
http.prepare_content("application/json")
|
||||
http.write_json(data)
|
||||
end
|
||||
|
||||
function action_load_data(type)
|
||||
local device
|
||||
if type == "download" then
|
||||
device = "imq0"
|
||||
elseif type == "upload" then
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
local wan = qos.get_wan()
|
||||
device = wan and wan:ifname() or ""
|
||||
end
|
||||
|
||||
if device then
|
||||
local data
|
||||
if device ~= "" then
|
||||
data = util.exec("tc -s class show dev %s 2>/dev/null" % device)
|
||||
end
|
||||
http.prepare_content("text/plain")
|
||||
http.write(data or "")
|
||||
else
|
||||
http.status(500, "Bad address")
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,166 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local http = require "luci.http"
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
|
||||
local m, class_s, rule_s, o
|
||||
local download_classes = {}
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
uci:foreach(qos_gargoyle, "download_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(qos_gargoyle, translate("Download Settings"))
|
||||
m.template = "qos_gargoyle/list_view"
|
||||
|
||||
class_s = m:section(TypedSection, "download_class", translate("Service Classes"),
|
||||
translate("Each service class is specified by four parameters: percent bandwidth at capacity, "
|
||||
.. "realtime bandwidth and maximum bandwidth and the minimimze round trip time flag."))
|
||||
class_s.anonymous = true
|
||||
class_s.addremove = true
|
||||
class_s.template = "cbi/tblsection"
|
||||
class_s.extedit = dsp.build_url("admin/network/qos_gargoyle/download/class/%s")
|
||||
class_s.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
m.uci:save(qos_gargoyle)
|
||||
http.redirect(class_s.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "name", translate("Class Name"))
|
||||
o.cfgvalue = function(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "percent_bandwidth", translate("Percent Bandwidth At Capacity"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return "%d %%" % v
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "min_bandwidth", "%s (kbps)" % translate("Minimum Bandwidth"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
return v or translate("Zero")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "max_bandwidth", "%s (kbps)" % translate("Maximum Bandwidth"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
return v or translate("Unlimited")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "minRTT", translate("Minimize RTT"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and translate(v) or translate("No")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "_ld", "%s (kbps)" % translate("Load"))
|
||||
o.rawhtml = true
|
||||
o.value = "<em class=\"ld-download\">*</em>"
|
||||
|
||||
rule_s = m:section(TypedSection, "download_rule", translate("Classification Rules"),
|
||||
translate("Packets are tested against the rules in the order specified -- rules toward the top "
|
||||
.. "have priority. As soon as a packet matches a rule it is classified, and the rest of the rules "
|
||||
.. "are ignored. The order of the rules can be altered using the arrow controls.")
|
||||
)
|
||||
rule_s.addremove = true
|
||||
rule_s.sortable = true
|
||||
rule_s.anonymous = true
|
||||
rule_s.template = "cbi/tblsection"
|
||||
rule_s.extedit = dsp.build_url("admin/network/qos_gargoyle/download/rule/%s")
|
||||
rule_s.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
m.uci:save(qos_gargoyle)
|
||||
http.redirect(rule_s.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = rule_s:option(ListValue, "class", translate("Service Class"))
|
||||
for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = rule_s:option(Value, "proto", translate("Transport Protocol"))
|
||||
o:value("", translate("All"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("icmp", "ICMP")
|
||||
o:value("gre", "GRE")
|
||||
o.size = "10"
|
||||
o.cfgvalue = function(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
Value.write(self, section, value:lower())
|
||||
end
|
||||
|
||||
o = rule_s:option(Value, "source", translate("Source IP(s)"))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = rule_s:option(Value, "srcport", translate("Source Port(s)"))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = rule_s:option(Value, "destination", translate("Destination IP(s)"))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = rule_s:option(Value, "dstport", translate("Destination Port(s)"))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = rule_s:option(DummyValue, "min_pkt_size", translate("Minimum Packet Length"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = rule_s:option(DummyValue, "max_pkt_size", translate("Maximum Packet Length"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = rule_s:option(DummyValue, "connbytes_kb", translate("Connection Bytes Reach"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v * 1024)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
if qos.has_ndpi() then
|
||||
o = rule_s:option(DummyValue, "ndpi", translate("DPI Protocol"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or translate("All")
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,61 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local m, s, o
|
||||
local sid = arg[1]
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
m = Map(qos_gargoyle, translate("Edit Download Service Class"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/download")
|
||||
|
||||
if m.uci:get(qos_gargoyle, sid) ~= "download_class" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, sid, "download_class")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Value, "name", translate("Service Class Name"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "percent_bandwidth", translate("Percent Bandwidth At Capacity"),
|
||||
translate("The percentage of the total available bandwidth that should be allocated to this class "
|
||||
.. "when all available bandwidth is being used. If unused bandwidth is available, more can (and "
|
||||
.. "will) be allocated. The percentages can be configured to equal more (or less) than 100, but "
|
||||
.. "when the settings are applied the percentages will be adjusted proportionally so that they "
|
||||
.. "add to 100. This setting only comes into effect when the WAN link is saturated."))
|
||||
o.datatype = "range(1, 100)"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "min_bandwidth", translate("Minimum Bandwidth"),
|
||||
translate("The minimum service this class will be allocated when the link is at capacity. Classes "
|
||||
.. "which specify minimum service are known as realtime classes by the active congestion "
|
||||
.. "controller. Streaming video, VoIP and interactive online gaming are all examples of "
|
||||
.. "applications that must have a minimum bandwith to function. To determine what to enter use "
|
||||
.. "the application on an unloaded LAN and observe how much bandwidth it uses. Then enter a "
|
||||
.. "number only slightly higher than this into this field. QoS will satisfiy the minimum service "
|
||||
.. "of all classes first before allocating to other waiting classes so be careful to use minimum "
|
||||
.. "bandwidths sparingly."))
|
||||
o:value("0", translate("Zero"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "max_bandwidth", translate("Maximum Bandwidth"),
|
||||
translate("The maximum amount of bandwidth this class will be allocated in kbit/s. Even if unused "
|
||||
.. "bandwidth is available, this service class will never be permitted to use more than this "
|
||||
.. "amount of bandwidth."))
|
||||
o:value("", translate("Unlimited"))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
o = s:option(Flag, "minRTT", translate("Minimize RTT"),
|
||||
translate("Indicates to the active congestion controller that you wish to minimize round trip "
|
||||
.. "times (RTT) when this class is active. Use this setting for online gaming or VoIP "
|
||||
.. "applications that need low round trip times (ping times). Minimizing RTT comes at the expense "
|
||||
.. "of efficient WAN throughput so while these class are active your WAN throughput will decline "
|
||||
.. "(usually around 20%)."))
|
||||
o.enabled = "Yes"
|
||||
o.disabled = "No"
|
||||
|
||||
return m
|
||||
@ -0,0 +1,87 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
|
||||
local m, s, o
|
||||
local sid = arg[1]
|
||||
local download_classes = {}
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
uci:foreach(qos_gargoyle, "download_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(qos_gargoyle, translate("Edit Download Classification Rule"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/download")
|
||||
|
||||
if m.uci:get(qos_gargoyle, sid) ~= "download_rule" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, sid, "download_rule")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(ListValue, "class", translate("Service Class"))
|
||||
for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = s:option(Value, "proto", translate("Transport Protocol"))
|
||||
o:value("", translate("All"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("icmp", "ICMP")
|
||||
o:value("gre", "GRE")
|
||||
o.write = function(self, section, value)
|
||||
Value.write(self, section, value:lower())
|
||||
end
|
||||
|
||||
o = s:option(Value, "source", translate("Source IP(s)"),
|
||||
translate("Packet's source ip, can optionally have /[mask] after it (see -s option in iptables "
|
||||
.. "man page)."))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = s:option(Value, "srcport", translate("Source Port(s)"),
|
||||
translate("Packet's source port, can be a range (eg. 80-90)."))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = s:option(Value, "destination", translate("Destination IP(s)"),
|
||||
translate("Packet's destination ip, can optionally have /[mask] after it (see -d option in "
|
||||
.. "iptables man page)."))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = s:option(Value, "dstport", translate("Destination Port(s)"),
|
||||
translate("Packet's destination port, can be a range (eg. 80-90)."))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = s:option(Value, "min_pkt_size", translate("Minimum Packet Length"),
|
||||
translate("Packet's minimum size (in bytes)."))
|
||||
o.datatype = "range(1, 1500)"
|
||||
|
||||
o = s:option(Value, "max_pkt_size", translate("Maximum Packet Length"),
|
||||
translate("Packet's maximum size (in bytes)."))
|
||||
o.datatype = "range(1, 1500)"
|
||||
|
||||
o = s:option(Value, "connbytes_kb", translate("Connection Bytes Reach"),
|
||||
translate("The total size of data transmitted since the establishment of the link (in kBytes)."))
|
||||
o.datatype = "range(0, 4194303)"
|
||||
|
||||
if qos.has_ndpi() then
|
||||
o = s:option(ListValue, "ndpi", translate("DPI Protocol"))
|
||||
o:value("", translate("All"))
|
||||
qos.cbi_add_dpi_protocols(o)
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,123 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local net = require "luci.model.network".init()
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
|
||||
local m, s, o
|
||||
local upload_classes = {}
|
||||
local download_classes = {}
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
local function qos_enabled()
|
||||
return sys.init.enabled(qos_gargoyle)
|
||||
end
|
||||
|
||||
uci:foreach(qos_gargoyle, "upload_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
uci:foreach(qos_gargoyle, "download_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
download_classes[#download_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(qos_gargoyle, translate("Gargoyle QoS"),
|
||||
translate("Quality of Service (QoS) provides a way to control how available bandwidth is "
|
||||
.. "allocated."))
|
||||
|
||||
s = m:section(SimpleSection, translate("Global Settings"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Button, "_switch", nil, translate("QoS Switch"))
|
||||
o.render = function(self, section, scope)
|
||||
if qos_enabled() then
|
||||
self.title = translate("Disable QoS")
|
||||
self.inputstyle = "reset"
|
||||
else
|
||||
self.title = translate("Enable QoS")
|
||||
self.inputstyle = "apply"
|
||||
end
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
o.write = function(...)
|
||||
if qos_enabled() then
|
||||
sys.init.stop(qos_gargoyle)
|
||||
sys.init.disable(qos_gargoyle)
|
||||
else
|
||||
sys.init.enable(qos_gargoyle)
|
||||
sys.init.start(qos_gargoyle)
|
||||
end
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, "upload", "upload", translate("Upload Settings"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "default_class", translate("Default Service Class"),
|
||||
translate("Specifie how packets that do not match any rule should be classified."))
|
||||
for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = s:option(Value, "total_bandwidth", translate("Total Upload Bandwidth"),
|
||||
translate("Should be set to around 98% of your available upload bandwidth. Entering a number "
|
||||
.. "which is too high will result in QoS not meeting its class requirements. Entering a number "
|
||||
.. "which is too low will needlessly penalize your upload speed. You should use a speed test "
|
||||
.. "program (with QoS off) to determine available upload bandwidth. Note that bandwidth is "
|
||||
.. "specified in kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte."))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
s = m:section(NamedSection, "download", "download", translate("Download Settings"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(ListValue, "default_class", translate("Default Service Class"),
|
||||
translate("Specifie how packets that do not match any rule should be classified."))
|
||||
for _, s in ipairs(download_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = s:option(Value, "total_bandwidth", translate("Total Download Bandwidth"),
|
||||
translate("Specifying correctly is crucial to making QoS work. Note that bandwidth is specified "
|
||||
.. "in kbps, leave blank to disable download QoS. There are 8 kilobits per kilobyte."))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
o = s:option(Flag, "qos_monenabled", translate("Enable Active Congestion Control"),
|
||||
translate("<p>The active congestion control (ACC) observes your download activity and "
|
||||
.. "automatically adjusts your download link limit to maintain proper QoS performance. ACC "
|
||||
.. "automatically compensates for changes in your ISP's download speed and the demand from your "
|
||||
.. "network adjusting the link speed to the highest speed possible which will maintain proper QoS "
|
||||
.. "function. The effective range of this control is between 15% and 100% of the total download "
|
||||
.. "bandwidth you entered above.</p>") ..
|
||||
translate("<p>While ACC does not adjust your upload link speed you must enable and properly "
|
||||
.. "configure your upload QoS for it to function properly.</p>")
|
||||
)
|
||||
o.enabled = "true"
|
||||
o.disabled = "false"
|
||||
|
||||
o = s:option(Value, "ptarget_ip", translate("Use Non-standard Ping Target"),
|
||||
translate("The segment of network between your router and the ping target is where congestion is "
|
||||
.. "controlled. By monitoring the round trip ping times to the target congestion is detected. By "
|
||||
.. "default ACC uses your WAN gateway as the ping target. If you know that congestion on your "
|
||||
.. "link will occur in a different segment then you can enter an alternate ping target. Leave "
|
||||
.. "empty to use the default settings."))
|
||||
o:depends("qos_monenabled", "true")
|
||||
local wan = qos.get_wan()
|
||||
if wan then o:value(wan:gwaddr()) end
|
||||
o.datatype = "ipaddr"
|
||||
|
||||
o = s:option(Value, "pinglimit", translate("Manual Ping Limit"),
|
||||
translate("Round trip ping times are compared against the ping limits. ACC controls the link "
|
||||
.. "limit to maintain ping times under the appropriate limit. By default ACC attempts to "
|
||||
.. "automatically select appropriate target ping limits for you based on the link speeds you "
|
||||
.. "entered and the performance of your link it measures during initialization. You cannot change "
|
||||
.. "the target ping time for the minRTT mode but by entering a manual time you can control the "
|
||||
.. "target ping time of the active mode. The time you enter becomes the increase in the target "
|
||||
.. "ping time between minRTT and active mode. Leave empty to use the default settings."))
|
||||
o:depends("qos_monenabled", "true")
|
||||
o:value("Auto", translate("Auto"))
|
||||
o.datatype = "or('Auto', range(10, 250))"
|
||||
|
||||
return m
|
||||
@ -0,0 +1,160 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local http = require "luci.http"
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
|
||||
local m, class_s, rule_s, o
|
||||
local upload_classes = {}
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
uci:foreach(qos_gargoyle, "upload_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(qos_gargoyle, translate("Upload Settings"))
|
||||
m.template = "qos_gargoyle/list_view"
|
||||
|
||||
class_s = m:section(TypedSection, "upload_class", translate("Service Classes"),
|
||||
translate("Each upload service class is specified by three parameters: percent bandwidth at "
|
||||
.. "capacity, minimum bandwidth and maximum bandwidth."))
|
||||
class_s.anonymous = true
|
||||
class_s.addremove = true
|
||||
class_s.template = "cbi/tblsection"
|
||||
class_s.extedit = dsp.build_url("admin/network/qos_gargoyle/upload/class/%s")
|
||||
class_s.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
m.uci:save(qos_gargoyle)
|
||||
http.redirect(class_s.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "name", translate("Class Name"))
|
||||
o.cfgvalue = function(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "percent_bandwidth", translate("Percent Bandwidth At Capacity"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return "%d %%" % v
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "min_bandwidth", "%s (kbps)" % translate("Minimum Bandwidth"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
return v or translate("Zero")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "max_bandwidth", "%s (kbps)" % translate("Maximum Bandwidth"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
return v or translate("Unlimited")
|
||||
end
|
||||
|
||||
o = class_s:option(DummyValue, "_ld", "%s (kbps)" % translate("Load"))
|
||||
o.rawhtml = true
|
||||
o.value = "<em class=\"ld-upload\">*</em>"
|
||||
|
||||
rule_s = m:section(TypedSection, "upload_rule",translate("Classification Rules"),
|
||||
translate("Packets are tested against the rules in the order specified -- rules toward the top "
|
||||
.. "have priority. As soon as a packet matches a rule it is classified, and the rest of the rules "
|
||||
.. "are ignored. The order of the rules can be altered using the arrow controls.")
|
||||
)
|
||||
rule_s.addremove = true
|
||||
rule_s.sortable = true
|
||||
rule_s.anonymous = true
|
||||
rule_s.template = "cbi/tblsection"
|
||||
rule_s.extedit = dsp.build_url("admin/network/qos_gargoyle/upload/rule/%s")
|
||||
rule_s.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
m.uci:save(qos_gargoyle)
|
||||
http.redirect(rule_s.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = rule_s:option(ListValue, "class", translate("Service Class"))
|
||||
for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = rule_s:option(Value, "proto", translate("Transport Protocol"))
|
||||
o:value("", translate("All"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("icmp", "ICMP")
|
||||
o:value("gre", "GRE")
|
||||
o.size = "10"
|
||||
o.cfgvalue = function(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or ""
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
Value.write(self, section, value:lower())
|
||||
end
|
||||
|
||||
o = rule_s:option(Value, "source", translate("Source IP(s)"))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = rule_s:option(Value, "srcport", translate("Source Port(s)"))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = rule_s:option(Value, "destination", translate("Destination IP(s)"))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = rule_s:option(Value, "dstport", translate("Destination Port(s)"))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = rule_s:option(DummyValue, "min_pkt_size", translate("Minimum Packet Length"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = rule_s:option(DummyValue, "max_pkt_size", translate("Maximum Packet Length"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
o = rule_s:option(DummyValue, "connbytes_kb", translate("Connection Bytes Reach"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = tonumber(Value.cfgvalue(...))
|
||||
if v and v > 0 then
|
||||
return wa.byte_format(v * 1024)
|
||||
end
|
||||
return translate("Not set")
|
||||
end
|
||||
|
||||
if qos.has_ndpi() then
|
||||
o = rule_s:option(DummyValue, "ndpi", translate("DPI Protocol"))
|
||||
o.cfgvalue = function(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or translate("All")
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,52 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local m, s, o
|
||||
local sid = arg[1]
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
m = Map(qos_gargoyle, translate("Edit Upload Service Class"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/upload")
|
||||
|
||||
if m.uci:get(qos_gargoyle, sid) ~= "upload_class" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, sid, "upload_class")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Value, "name", translate("Service Class Name"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "percent_bandwidth", translate("Percent Bandwidth At Capacity"),
|
||||
translate("The percentage of the total available bandwidth that should be allocated to this class "
|
||||
.. "when all available bandwidth is being used. If unused bandwidth is available, more can (and "
|
||||
.. "will) be allocated. The percentages can be configured to equal more (or less) than 100, but "
|
||||
.. "when the settings are applied the percentages will be adjusted proportionally so that they "
|
||||
.. "add to 100. This setting only comes into effect when the WAN link is saturated."))
|
||||
o.datatype = "range(1, 100)"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "min_bandwidth", translate("Minimum Bandwidth"),
|
||||
translate("The minimum service this class will be allocated when the link is at capacity. Classes "
|
||||
.. "which specify minimum service are known as realtime classes by the active congestion "
|
||||
.. "controller. Streaming video, VoIP and interactive online gaming are all examples of "
|
||||
.. "applications that must have a minimum bandwith to function. To determine what to enter use "
|
||||
.. "the application on an unloaded LAN and observe how much bandwidth it uses. Then enter a "
|
||||
.. "number only slightly higher than this into this field. QoS will satisfiy the minimum service "
|
||||
.. "of all classes first before allocating to other waiting classes so be careful to use minimum "
|
||||
.. "bandwidths sparingly."))
|
||||
o:value("0", translate("Zero"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "max_bandwidth", translate("Maximum Bandwidth"),
|
||||
translate("The maximum amount of bandwidth this class will be allocated in kbit/s. Even if unused "
|
||||
.. "bandwidth is available, this service class will never be permitted to use more than this "
|
||||
.. "amount of bandwidth."))
|
||||
o:value("", translate("Unlimited"))
|
||||
o.datatype = "uinteger"
|
||||
|
||||
return m
|
||||
@ -0,0 +1,87 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local qos = require "luci.model.qos_gargoyle"
|
||||
|
||||
local m, s, o
|
||||
local sid = arg[1]
|
||||
local upload_classes = {}
|
||||
local qos_gargoyle = "qos_gargoyle"
|
||||
|
||||
uci:foreach(qos_gargoyle, "upload_class", function(s)
|
||||
local class_alias = s.name
|
||||
if class_alias then
|
||||
upload_classes[#upload_classes + 1] = {name = s[".name"], alias = class_alias}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(qos_gargoyle, translate("Edit Upload Classification Rule"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/network/qos_gargoyle/upload")
|
||||
|
||||
if m.uci:get(qos_gargoyle, sid) ~= "upload_rule" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, sid, "upload_rule")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(ListValue, "class", translate("Service Class"))
|
||||
for _, s in ipairs(upload_classes) do o:value(s.name, s.alias) end
|
||||
|
||||
o = s:option(Value, "proto", translate("Transport Protocol"))
|
||||
o:value("", translate("All"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("icmp", "ICMP")
|
||||
o:value("gre", "GRE")
|
||||
o.write = function(self, section, value)
|
||||
Value.write(self, section, value:lower())
|
||||
end
|
||||
|
||||
o = s:option(Value, "source", translate("Source IP(s)"),
|
||||
translate("Packet's source ip, can optionally have /[mask] after it (see -s option in iptables "
|
||||
.. "man page)."))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = s:option(Value, "srcport", translate("Source Port(s)"),
|
||||
translate("Packet's source port, can be a range (eg. 80-90)."))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = s:option(Value, "destination", translate("Destination IP(s)"),
|
||||
translate("Packet's destination ip, can optionally have /[mask] after it (see -d option in "
|
||||
.. "iptables man page)."))
|
||||
o:value("", translate("All"))
|
||||
wa.cbi_add_knownips(o)
|
||||
o.datatype = "ipmask4"
|
||||
|
||||
o = s:option(Value, "dstport", translate("Destination Port(s)"),
|
||||
translate("Packet's destination port, can be a range (eg. 80-90)."))
|
||||
o:value("", translate("All"))
|
||||
o.datatype = "or(port, portrange)"
|
||||
|
||||
o = s:option(Value, "min_pkt_size", translate("Minimum Packet Length"),
|
||||
translate("Packet's minimum size (in bytes)."))
|
||||
o.datatype = "range(1, 1500)"
|
||||
|
||||
o = s:option(Value, "max_pkt_size", translate("Maximum Packet Length"),
|
||||
translate("Packet's maximum size (in bytes)."))
|
||||
o.datatype = "range(1, 1500)"
|
||||
|
||||
o = s:option(Value, "connbytes_kb", translate("Connection Bytes Reach"),
|
||||
translate("The total size of data transmitted since the establishment of the link (in kBytes)."))
|
||||
o.datatype = "range(0, 4194303)"
|
||||
|
||||
if qos.has_ndpi() then
|
||||
o = s:option(ListValue, "ndpi", translate("DPI Protocol"))
|
||||
o:value("", translate("All"))
|
||||
qos.cbi_add_dpi_protocols(o)
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,31 @@
|
||||
-- Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.model.qos_gargoyle", package.seeall)
|
||||
|
||||
function has_ndpi()
|
||||
return luci.sys.call("lsmod | cut -d ' ' -f1 | grep -q 'xt_ndpi'") == 0
|
||||
end
|
||||
|
||||
function cbi_add_dpi_protocols(field)
|
||||
local util = require "luci.util"
|
||||
|
||||
local dpi_protocols = {}
|
||||
|
||||
for line in util.execi("iptables -m ndpi --help 2>/dev/null | grep '^--'") do
|
||||
local _, _, protocol, name = line:find("%-%-([^%s]+) Match for ([^%s]+)")
|
||||
|
||||
if protocol and name then
|
||||
dpi_protocols[protocol] = name
|
||||
end
|
||||
end
|
||||
|
||||
for p, n in util.kspairs(dpi_protocols) do
|
||||
field:value(p, n)
|
||||
end
|
||||
end
|
||||
|
||||
function get_wan()
|
||||
local net = require "luci.model.network".init()
|
||||
return net:get_wannet()
|
||||
end
|
||||
@ -0,0 +1,97 @@
|
||||
<%#
|
||||
Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local dsp = require "luci.dispatcher"
|
||||
local request = dsp.context.path
|
||||
local leaf = request[#request]
|
||||
-%>
|
||||
|
||||
<style title="text/css">
|
||||
/* container for entire page. fixes bootstrap theme's ridiculously small page width */
|
||||
.container {
|
||||
max-width: none;
|
||||
margin: 0 30px;
|
||||
width: auto;
|
||||
}
|
||||
/* column for configuration section name */
|
||||
table th {
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* cells showing the configuration values */
|
||||
table td {
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* sort buttons column */
|
||||
table.cbi-section-table td.cbi-section-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<%+cbi/map%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function bpsToKbpsString(bps) {
|
||||
var kbps = '*';
|
||||
var bpsn = parseInt(bps) / 1000;
|
||||
if (isNaN(bpsn)) {
|
||||
kbps = '*';
|
||||
} else if (bpsn < 1) {
|
||||
kbps = bpsn.toFixed(1) + '';
|
||||
} else {
|
||||
kbps = bpsn.toFixed(0) + '';
|
||||
}
|
||||
return kbps;
|
||||
}
|
||||
(function(doc){
|
||||
var tbs = doc.getElementsByClassName('ld-<%=leaf%>');
|
||||
var lastTime = 0;
|
||||
var dataTable = [];
|
||||
var updateInProgress = false;
|
||||
|
||||
XHR.poll(3, '<%=dsp.build_url("admin", "network", "qos_gargoyle", "load_data", leaf)%>',
|
||||
null, function(res) {
|
||||
if (res.readyState == 4 && tbs) {
|
||||
var timestamp = new Date().getTime();
|
||||
var timeDiff = timestamp - lastTime;
|
||||
lastTime = timestamp;
|
||||
|
||||
if (updateInProgress) return;
|
||||
|
||||
updateInProgress = true;
|
||||
var lines = res.responseText.match(/hfsc\s1:[0-9]{1,2}\s.+leaf.+\n.+Sent\s[0-9]+/g);
|
||||
|
||||
if (lines) {
|
||||
for (var i = 0, len = lines.length; i < len; i++) {
|
||||
var line = lines[i];
|
||||
var idx = parseInt(line.match(/hfsc\s1:([0-9]+)/)[1]) - 2;
|
||||
var lastBytes;
|
||||
if (idx < tbs.length) {
|
||||
lastBytes = dataTable[idx];
|
||||
var newBytes = line.match(/Sent\s([0-9]+)/)[1];
|
||||
dataTable[idx] = newBytes;
|
||||
var bps = NaN;
|
||||
if (lastBytes) {
|
||||
var diffBytes = parseInt(newBytes) - parseInt(lastBytes);
|
||||
if (diffBytes <= 0) {
|
||||
bps = 0;
|
||||
} else {
|
||||
bps = diffBytes * 8000 / timeDiff;
|
||||
}
|
||||
}
|
||||
tbs[idx].innerText = bpsToKbpsString(bps);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}(document));
|
||||
//]]></script>
|
||||
@ -0,0 +1,52 @@
|
||||
<%#
|
||||
Copyright 2017 Xingwang Liao <kuoruan@gmail.com>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<% css = [[
|
||||
|
||||
#troubleshoot_text {
|
||||
padding: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
#troubleshoot_text pre {
|
||||
word-break: break-all;
|
||||
margin: 0;
|
||||
}
|
||||
.description {
|
||||
background-color: #33CCFF;
|
||||
}
|
||||
|
||||
]]
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(15, '<%=url("admin/network/qos_gargoyle/troubleshooting/data")%>', null,
|
||||
function(x, data) {
|
||||
var tshoot = document.getElementById('troubleshoot_text');
|
||||
if (data.hasOwnProperty("show")) {
|
||||
tshoot.innerHTML = String.format(
|
||||
'<pre>%s%s%s%s</pre>',
|
||||
'<span class="description">Output of "/etc/init.d/qos_gargoyle show" : </span><br /><br />',
|
||||
data.show,
|
||||
'<br /><br /><span class="description">Output of "cat /tmp/qosmon.status" : </span><br /><br />',
|
||||
data.mon
|
||||
);
|
||||
} else {
|
||||
tshoot.innerHTML = '<strong><%:Error collecting troubleshooting information%></strong>';
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<div id="troubleshoot">
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Troubleshooting Data%></legend>
|
||||
<div id="troubleshoot_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /><%:Collecting data...%></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
||||
334
package/ctcgfw/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po
Normal file
334
package/ctcgfw/luci-app-qos-gargoyle/po/zh-cn/qos-gargoyle.po
Normal file
@ -0,0 +1,334 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "\"Active Congestion Control\" not enabled"
|
||||
msgstr "“主动拥塞控制”未启用"
|
||||
|
||||
msgid ""
|
||||
"<p>The active congestion control (ACC) observes your download activity and "
|
||||
"automatically adjusts your download link limit to maintain proper QoS "
|
||||
"performance. ACC automatically compensates for changes in your ISP's "
|
||||
"download speed and the demand from your network adjusting the link speed to "
|
||||
"the highest speed possible which will maintain proper QoS function. The "
|
||||
"effective range of this control is between 15% and 100% of the total "
|
||||
"download bandwidth you entered above.</p>"
|
||||
msgstr ""
|
||||
"<p>主动拥塞控制系统(ACC)观察你的下载活动并自动调整你的下载链接限制以保持适"
|
||||
"当的 QoS 性能。ACC 自动调整 QoS 功能以补偿来自你 ISP 的下载速度变化及来自你网"
|
||||
"络链接速度的调整需求,使速度最大化。这个控制的有效范围在你上面输入的下载总带"
|
||||
"宽的 15% 至 100% 之间。</p>"
|
||||
|
||||
msgid ""
|
||||
"<p>While ACC does not adjust your upload link speed you must enable and "
|
||||
"properly configure your upload QoS for it to function properly.</p>"
|
||||
msgstr ""
|
||||
"<p>虽然 ACC 不调整你的上传链路速度,但你必须启用并正确配置你的上传 QoS 带宽以"
|
||||
"使该功能正常工作。</p>"
|
||||
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
msgid "Auto"
|
||||
msgstr "自动"
|
||||
|
||||
msgid "Class Name"
|
||||
msgstr "类型名称"
|
||||
|
||||
msgid "Classification Rules"
|
||||
msgstr "分类规则"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据..."
|
||||
|
||||
msgid "Connection Bytes Reach"
|
||||
msgstr "连接流量达到"
|
||||
|
||||
msgid "DPI Protocol"
|
||||
msgstr "DPI 协议"
|
||||
|
||||
msgid "Default Service Class"
|
||||
msgstr "默认服务类型"
|
||||
|
||||
msgid "Destination IP(s)"
|
||||
msgstr "目标 IP"
|
||||
|
||||
msgid "Destination Port(s)"
|
||||
msgstr "目标端口"
|
||||
|
||||
msgid "Disable QoS"
|
||||
msgstr "禁用 QoS"
|
||||
|
||||
msgid "Download Settings"
|
||||
msgstr "下载设置"
|
||||
|
||||
msgid ""
|
||||
"Each service class is specified by four parameters: percent bandwidth at "
|
||||
"capacity, realtime bandwidth and maximum bandwidth and the minimimze round "
|
||||
"trip time flag."
|
||||
msgstr ""
|
||||
"每个下载服务类型由四个参数指定:带宽占用百分比、最小保证带宽、最大带宽和最小"
|
||||
"往返延时标志。"
|
||||
|
||||
msgid ""
|
||||
"Each upload service class is specified by three parameters: percent "
|
||||
"bandwidth at capacity, minimum bandwidth and maximum bandwidth."
|
||||
msgstr "每个上传服务类型由三个参数指定:带宽占用百分比、最小带宽和最大带宽。"
|
||||
|
||||
msgid "Edit Download Classification Rule"
|
||||
msgstr "编辑下载分类规则"
|
||||
|
||||
msgid "Edit Download Service Class"
|
||||
msgstr "编辑下载服务类型"
|
||||
|
||||
msgid "Edit Upload Classification Rule"
|
||||
msgstr "编辑上传分类规则"
|
||||
|
||||
msgid "Edit Upload Service Class"
|
||||
msgstr "编辑上传服务类型"
|
||||
|
||||
msgid "Enable Active Congestion Control"
|
||||
msgstr "启用主动拥塞控制"
|
||||
|
||||
msgid "Enable QoS"
|
||||
msgstr "启用 QoS"
|
||||
|
||||
msgid "Error collecting troubleshooting information"
|
||||
msgstr "收集故障排查信息失败"
|
||||
|
||||
msgid "Gargoyle QoS"
|
||||
msgstr "石像鬼 QoS"
|
||||
|
||||
msgid "Global Settings"
|
||||
msgstr "全局设置"
|
||||
|
||||
msgid ""
|
||||
"Indicates to the active congestion controller that you wish to minimize "
|
||||
"round trip times (RTT) when this class is active. Use this setting for "
|
||||
"online gaming or VoIP applications that need low round trip times (ping "
|
||||
"times). Minimizing RTT comes at the expense of efficient WAN throughput so "
|
||||
"while these class are active your WAN throughput will decline (usually "
|
||||
"around 20%)."
|
||||
msgstr ""
|
||||
"告诉主动拥塞控制器你希望该服务类型启用时尽量减少往返延时(RTT)。该设置一般用"
|
||||
"在 VoIP 或在线游戏这类需要低延时(Ping 值)的应用上。减小往返延时(RTT)会带"
|
||||
"来WAN有效吞吐量的额外花销,所以当这些服务类型启用时你的 WAN 吞吐量将下降(通"
|
||||
"常在20%左右)"
|
||||
|
||||
msgid "Load"
|
||||
msgstr "负载"
|
||||
|
||||
msgid "Loading"
|
||||
msgstr "正在加载"
|
||||
|
||||
msgid "Manual Ping Limit"
|
||||
msgstr "手动 Ping 限制"
|
||||
|
||||
msgid "Maximum Bandwidth"
|
||||
msgstr "最大带宽"
|
||||
|
||||
msgid "Maximum Packet Length"
|
||||
msgstr "最大数据包长度"
|
||||
|
||||
msgid "Minimize RTT"
|
||||
msgstr "最小往返延时"
|
||||
|
||||
msgid "Minimum Bandwidth"
|
||||
msgstr "最小带宽"
|
||||
|
||||
msgid "Minimum Packet Length"
|
||||
msgstr "最小数据包长度"
|
||||
|
||||
msgid "No"
|
||||
msgstr "否"
|
||||
|
||||
msgid "No data found"
|
||||
msgstr "无数据"
|
||||
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
msgid "Not set"
|
||||
msgstr "未设置"
|
||||
|
||||
msgid ""
|
||||
"Packet's destination ip, can optionally have /[mask] after it (see -d option "
|
||||
"in iptables man page)."
|
||||
msgstr ""
|
||||
"数据包的目标 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -d 参数说"
|
||||
"明)"
|
||||
|
||||
msgid "Packet's destination port, can be a range (eg. 80-90)."
|
||||
msgstr "数据包的目标端口,可以是一个范围(例如:80-90)"
|
||||
|
||||
msgid "Packet's maximum size (in bytes)."
|
||||
msgstr "数据包的最大大小(单位:bytes)"
|
||||
|
||||
msgid "Packet's minimum size (in bytes)."
|
||||
msgstr "数据包的最小大小(单位:bytes)"
|
||||
|
||||
msgid ""
|
||||
"Packet's source ip, can optionally have /[mask] after it (see -s option in "
|
||||
"iptables man page)."
|
||||
msgstr ""
|
||||
"数据包的源 IP,可以在后面加子网掩码(/[mask],请看 iptables 的 -s 参数说明)"
|
||||
|
||||
msgid "Packet's source port, can be a range (eg. 80-90)."
|
||||
msgstr "数据包的源端口,可以是一个范围(例如:80-90)"
|
||||
|
||||
msgid ""
|
||||
"Packets are tested against the rules in the order specified -- rules toward "
|
||||
"the top have priority. As soon as a packet matches a rule it is classified, "
|
||||
"and the rest of the rules are ignored. The order of the rules can be altered "
|
||||
"using the arrow controls."
|
||||
msgstr ""
|
||||
"数据包将按规则中指定的顺序进行匹配 —— 靠上的规则优先进行匹配。一旦数据包匹配"
|
||||
"一条规则那它将被归类,并且其余的规则将被忽略。使用上下箭头可调整规则的顺序。"
|
||||
|
||||
msgid "Percent Bandwidth At Capacity"
|
||||
msgstr "带宽占用百分比"
|
||||
|
||||
msgid "QoS Switch"
|
||||
msgstr "QoS 开关"
|
||||
|
||||
msgid ""
|
||||
"Quality of Service (QoS) provides a way to control how available bandwidth "
|
||||
"is allocated."
|
||||
msgstr "QoS 可以用来分配和控制可用带宽。"
|
||||
|
||||
msgid ""
|
||||
"Round trip ping times are compared against the ping limits. ACC controls the "
|
||||
"link limit to maintain ping times under the appropriate limit. By default "
|
||||
"ACC attempts to automatically select appropriate target ping limits for you "
|
||||
"based on the link speeds you entered and the performance of your link it "
|
||||
"measures during initialization. You cannot change the target ping time for "
|
||||
"the minRTT mode but by entering a manual time you can control the target "
|
||||
"ping time of the active mode. The time you enter becomes the increase in the "
|
||||
"target ping time between minRTT and active mode. Leave empty to use the "
|
||||
"default settings."
|
||||
msgstr ""
|
||||
"Ping 延时会与 Ping 限制进行比较。ACC 控制链路限制以保持 Ping 延时在适当范围。"
|
||||
"默认情况下,ACC 会自动根据你输入的链接适当为你选择适当的 Ping 限制。如果你想"
|
||||
"尝试不同的 Ping 限制,你可以在这里输入一个时间值。输入高的时间值将导致更高的 "
|
||||
"Ping 限制,低的时间值会有更低的限制。留空则将由 ACC 自动控制。"
|
||||
|
||||
msgid "Service Class"
|
||||
msgstr "服务类型"
|
||||
|
||||
msgid "Service Class Name"
|
||||
msgstr "服务类型名称"
|
||||
|
||||
msgid "Service Classes"
|
||||
msgstr "服务类型"
|
||||
|
||||
msgid ""
|
||||
"Should be set to around 98% of your available upload bandwidth. Entering a "
|
||||
"number which is too high will result in QoS not meeting its class "
|
||||
"requirements. Entering a number which is too low will needlessly penalize "
|
||||
"your upload speed. You should use a speed test program (with QoS off) to "
|
||||
"determine available upload bandwidth. Note that bandwidth is specified in "
|
||||
"kbps, leave blank to disable update QoS. There are 8 kilobits per kilobyte."
|
||||
msgstr ""
|
||||
"应被设置为你可用上传带宽的 98% 左右。输入数值太高将导致 QoS 不能匹配服务类型"
|
||||
"的要求。输入数值太低将造成不必要的上传速度限制。你应当在 QoS 关闭的情况下使用"
|
||||
"测速程序以确定可用的上传带宽。带宽以 kbps 为单位,留空以禁用上传 QoS。"
|
||||
"(1KByte/s=8Kbps)"
|
||||
|
||||
msgid "Source IP(s)"
|
||||
msgstr "源 IP"
|
||||
|
||||
msgid "Source Port(s)"
|
||||
msgstr "源端口"
|
||||
|
||||
msgid "Specifie how packets that do not match any rule should be classified."
|
||||
msgstr "指定当数据包不匹配任何规则时将被如何归类。"
|
||||
|
||||
msgid ""
|
||||
"Specifying correctly is crucial to making QoS work. Note that bandwidth is "
|
||||
"specified in kbps, leave blank to disable download QoS. There are 8 kilobits "
|
||||
"per kilobyte."
|
||||
msgstr ""
|
||||
"正确设置对于 QoS 的工作至关重要。带宽以 kbps 为单位,留空以禁用下载 QoS。"
|
||||
"(1KByte/s=8Kbps)"
|
||||
|
||||
msgid ""
|
||||
"The maximum amount of bandwidth this class will be allocated in kbit/s. Even "
|
||||
"if unused bandwidth is available, this service class will never be permitted "
|
||||
"to use more than this amount of bandwidth."
|
||||
msgstr ""
|
||||
"该服务类型可被分配的带宽最大值(以 kbit/s 为单位)。即使存在未使用带宽,该服"
|
||||
"务类型也将永远不被允许使用超过此量的带宽。"
|
||||
|
||||
msgid ""
|
||||
"The minimum service this class will be allocated when the link is at "
|
||||
"capacity. Classes which specify minimum service are known as realtime "
|
||||
"classes by the active congestion controller. Streaming video, VoIP and "
|
||||
"interactive online gaming are all examples of applications that must have a "
|
||||
"minimum bandwith to function. To determine what to enter use the application "
|
||||
"on an unloaded LAN and observe how much bandwidth it uses. Then enter a "
|
||||
"number only slightly higher than this into this field. QoS will satisfiy the "
|
||||
"minimum service of all classes first before allocating to other waiting "
|
||||
"classes so be careful to use minimum bandwidths sparingly."
|
||||
msgstr ""
|
||||
"将被分配用于该服务类型的最低链路带宽容量。指定了最小带宽的服务类型会被主动拥"
|
||||
"塞控制器看作实时类应用。例如视频流、VoIP 和在线互动游戏都应该设置最小带宽。要"
|
||||
"确定需要多少最小带宽,可以在一个没有负载的局域网中使用应用程序并观察它使用了"
|
||||
"多少带宽。然后输入一个略高于这个值的数字到字段中。在分配剩余带宽到其它服务类"
|
||||
"型前,QoS 将优先满足所有服务类型的最小带宽要求,所以要谨慎地使用最小带宽。"
|
||||
|
||||
msgid ""
|
||||
"The percentage of the total available bandwidth that should be allocated to "
|
||||
"this class when all available bandwidth is being used. If unused bandwidth "
|
||||
"is available, more can (and will) be allocated. The percentages can be "
|
||||
"configured to equal more (or less) than 100, but when the settings are "
|
||||
"applied the percentages will be adjusted proportionally so that they add to "
|
||||
"100. This setting only comes into effect when the WAN link is saturated."
|
||||
msgstr ""
|
||||
"当所有可用带宽被占满后该服务类型占据总带宽的百分比。如果带宽未用完,该服务类"
|
||||
"型会被分配更多带宽。该百分比值可被设置为等于、大于或小于 100,但当设置被应用"
|
||||
"时,百分比值将会被按比例调整以便使它们加起来等于 100。该设置只在 WAN 端链路饱"
|
||||
"和时才生效。<em>(PS:WAN 端链路饱和即带宽被占用完)</em>"
|
||||
|
||||
msgid ""
|
||||
"The segment of network between your router and the ping target is where "
|
||||
"congestion is controlled. By monitoring the round trip ping times to the "
|
||||
"target congestion is detected. By default ACC uses your WAN gateway as the "
|
||||
"ping target. If you know that congestion on your link will occur in a "
|
||||
"different segment then you can enter an alternate ping target. Leave empty "
|
||||
"to use the default settings."
|
||||
msgstr ""
|
||||
"在路由器和 Ping 目标之间的网络部分是拥塞控制的地方。拥塞通过监视和目标间的 "
|
||||
"Ping 延时来检测。默认情况下 ACC 使用你的 WAN 网关作为 Ping 的目标。假如你知道"
|
||||
"拥塞会在你链路的不同段发生,你可用输入一个备用的 Ping 目标。留空则将由ACC 自"
|
||||
"动控制。"
|
||||
|
||||
msgid ""
|
||||
"The total size of data transmitted since the establishment of the link (in "
|
||||
"kBytes)."
|
||||
msgstr "自连接建立以来,传输的数据总量(单位:kBytes)"
|
||||
|
||||
msgid "Total Download Bandwidth"
|
||||
msgstr "下载总带宽"
|
||||
|
||||
msgid "Total Upload Bandwidth"
|
||||
msgstr "上传总带宽"
|
||||
|
||||
msgid "Transport Protocol"
|
||||
msgstr "协议"
|
||||
|
||||
msgid "Troubleshooting"
|
||||
msgstr "故障排除"
|
||||
|
||||
msgid "Troubleshooting Data"
|
||||
msgstr "故障排除数据"
|
||||
|
||||
msgid "Unlimited"
|
||||
msgstr "不限制"
|
||||
|
||||
msgid "Upload Settings"
|
||||
msgstr "上传设置"
|
||||
|
||||
msgid "Use Non-standard Ping Target"
|
||||
msgstr "使用自定义 Ping 目标"
|
||||
|
||||
msgid "Zero"
|
||||
msgstr "零"
|
||||
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@qos_gargoyle[-1]
|
||||
add ucitrack qos_gargoyle
|
||||
set ucitrack.@qos_gargoyle[-1].init=qos_gargoyle
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -rf /tmp/luci-modulecache /tmp/luci-indexcache
|
||||
exit 0
|
||||
Loading…
Reference in New Issue
Block a user