Merge pull request #1855 from rosysong/nqos
luci-app-nft-qos: add new application
This commit is contained in:
commit
14ad794925
8 changed files with 966 additions and 0 deletions
14
applications/luci-app-nft-qos/Makefile
Normal file
14
applications/luci-app-nft-qos/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Qos over Nftables
|
||||
LUCI_DEPENDS:=+nft-qos
|
||||
|
||||
include ../../luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
51
applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua
Normal file
51
applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua
Normal file
|
@ -0,0 +1,51 @@
|
|||
-- Copyright 2018 Rosy Song <rosysong@rosinson.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.nft-qos", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/nft-qos") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "status", "realtime", "rate"},
|
||||
template("nft-qos/rate"), _("Rate"), 5).leaf = true
|
||||
entry({"admin", "status", "realtime", "rate_status"},
|
||||
call("action_rate")).leaf = true
|
||||
entry({"admin", "services", "nft-qos"}, cbi("nft-qos/nft-qos"),
|
||||
_("Qos over Nftables"), 60)
|
||||
end
|
||||
|
||||
function _action_rate(rv, n)
|
||||
local c = io.popen("nft list chain inet nft-qos-monitor " .. n .. " 2>/dev/null")
|
||||
if c then
|
||||
for l in c:lines() do
|
||||
local _, i, p, b = l:match('^%s+ip ([^%s]+) ([^%s]+) counter packets (%d+) bytes (%d+)')
|
||||
if i and p and b then
|
||||
-- handle expression
|
||||
local r = {
|
||||
rule = {
|
||||
family = "inet",
|
||||
table = "nft-qos-monitor",
|
||||
chain = n,
|
||||
handle = 0,
|
||||
expr = {
|
||||
{ match = { right = i } },
|
||||
{ counter = { packets = p, bytes = b } }
|
||||
}
|
||||
}
|
||||
}
|
||||
rv[#rv + 1] = r
|
||||
end
|
||||
end
|
||||
c:close()
|
||||
end
|
||||
end
|
||||
|
||||
function action_rate()
|
||||
luci.http.prepare_content("application/json")
|
||||
local data = { nftables = {} }
|
||||
_action_rate(data.nftables, "upload")
|
||||
_action_rate(data.nftables, "download")
|
||||
luci.http.write_json(data)
|
||||
end
|
|
@ -0,0 +1,229 @@
|
|||
-- Copyright 2018 Rosy Song <rosysong@rosinson.com>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local wa = require("luci.tools.webadmin")
|
||||
local fs = require("nixio.fs")
|
||||
local ipc = require("luci.ip")
|
||||
|
||||
local def_rate_dl = uci:get("nft-qos", "default", "static_rate_dl")
|
||||
local def_rate_ul = uci:get("nft-qos", "default", "static_rate_ul")
|
||||
local def_unit_dl = uci:get("nft-qos", "default", "static_unit_dl")
|
||||
local def_unit_ul = uci:get("nft-qos", "default", "static_unit_ul")
|
||||
|
||||
local def_up = uci:get("nft-qos", "default", "dynamic_bw_up")
|
||||
local def_down = uci:get("nft-qos", "default", "dynamic_bw_down")
|
||||
|
||||
local limit_enable = uci:get("nft-qos", "default", "limit_enable")
|
||||
local limit_type = uci:get("nft-qos", "default", "limit_type")
|
||||
local enable_priority = uci:get("nft-qos", "default", "priority_enable")
|
||||
|
||||
local has_ipv6 = fs.access("/proc/net/ipv6_route")
|
||||
|
||||
m = Map("nft-qos", translate("Qos over Nftables"))
|
||||
|
||||
--
|
||||
-- Taboptions
|
||||
--
|
||||
s = m:section(TypedSection, "default", translate("NFT-QoS Settings"))
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
|
||||
s:tab("limit", "Limit Rate")
|
||||
s:tab("priority", "Traffic Priority")
|
||||
|
||||
--
|
||||
-- Static
|
||||
--
|
||||
o = s:taboption("limit", Flag, "limit_enable", translate("Limit Enable"), translate("Enable Limit Rate Feature"))
|
||||
o.default = limit_enable or o.enabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("limit", ListValue, "limit_type", translate("Limit Type"), translate("Type of Limit Rate"))
|
||||
o.default = limit_static or "static"
|
||||
o:depends("limit_enable","1")
|
||||
o:value("static", "Static")
|
||||
o:value("dynamic", "Dynamic")
|
||||
|
||||
o = s:taboption("limit", Value, "static_rate_dl", translate("Default Download Rate"), translate("Default value for download rate"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = def_rate_dl or '50'
|
||||
o:depends("limit_type","static")
|
||||
|
||||
o = s:taboption("limit", ListValue, "static_unit_dl", translate("Default Download Unit"), translate("Default unit for download rate"))
|
||||
o.default = def_unit_dl or "kbytes"
|
||||
o:depends("limit_type","static")
|
||||
o:value("bytes", "Bytes/s")
|
||||
o:value("kbytes", "KBytes/s")
|
||||
o:value("mbytes", "MBytes/s")
|
||||
|
||||
o = s:taboption("limit", Value, "static_rate_ul", translate("Default Upload Rate"), translate("Default value for upload rate"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = def_rate_ul or '50'
|
||||
o:depends("limit_type","static")
|
||||
|
||||
o = s:taboption("limit", ListValue, "static_unit_ul", translate("Default Upload Unit"), translate("Default unit for upload rate"))
|
||||
o.default = def_unit_ul or "kbytes"
|
||||
o:depends("limit_type","static")
|
||||
o:value("bytes", "Bytes/s")
|
||||
o:value("kbytes", "KBytes/s")
|
||||
o:value("mbytes", "MBytes/s")
|
||||
|
||||
--
|
||||
-- Dynamic
|
||||
--
|
||||
o = s:taboption("limit", Value, "dynamic_bw_down", translate("Download Bandwidth (Mbps)"), translate("Default value for download bandwidth"))
|
||||
o.default = def_up or '100'
|
||||
o.datatype = "uinteger"
|
||||
o:depends("limit_type","dynamic")
|
||||
|
||||
o = s:taboption("limit", Value, "dynamic_bw_up", translate("Upload Bandwidth (Mbps)"), translate("Default value for upload bandwidth"))
|
||||
o.default = def_down or '100'
|
||||
o.datatype = "uinteger"
|
||||
o:depends("limit_type","dynamic")
|
||||
|
||||
o = s:taboption("limit", Value, "dynamic_cidr", translate("Target Network (IPv4/MASK)"), translate("Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc"))
|
||||
o.datatype = "cidr4"
|
||||
ipc.routes({ family = 4, type = 1 }, function(rt) o.default = rt.dest end)
|
||||
o:depends("limit_type","dynamic")
|
||||
|
||||
if has_ipv6 then
|
||||
o = s:taboption("limit", Value, "dynamic_cidr6", translate("Target Network6 (IPv6/MASK)"), translate("Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc"))
|
||||
o.datatype = "cidr6"
|
||||
o:depends("limit_type","dynamic")
|
||||
end
|
||||
|
||||
o = s:taboption("limit", DynamicList, "limit_whitelist", translate("White List for Limit Rate"))
|
||||
o.datatype = "ipaddr"
|
||||
o:depends("limit_enable","1")
|
||||
|
||||
--
|
||||
-- Priority
|
||||
--
|
||||
o = s:taboption("priority", Flag, "priority_enable", translate("Enable Traffic Priority"), translate("Enable this feature"))
|
||||
o.default = enable_priority or o.enabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("priority", ListValue, "priority_netdev", translate("Default Network Interface"), translate("Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc"))
|
||||
o:depends("priority_enable", "1")
|
||||
wa.cbi_add_networks(o)
|
||||
|
||||
--
|
||||
-- Static Limit Rate - Download Rate
|
||||
--
|
||||
if limit_enable == "1" and limit_type == "static" then
|
||||
|
||||
x = m:section(TypedSection, "download", translate("Static QoS-Download Rate"))
|
||||
x.anonymous = true
|
||||
x.addremove = true
|
||||
x.template = "cbi/tblsection"
|
||||
|
||||
o = x:option(Value, "hostname", translate("Hostname"))
|
||||
o.datatype = "hostname"
|
||||
o.default = 'undefined'
|
||||
|
||||
if has_ipv6 then
|
||||
o = x:option(Value, "ipaddr", translate("IP Address(V4 / V6)"))
|
||||
else
|
||||
o = x:option(Value, "ipaddr", translate("IP Address(V4 Only)"))
|
||||
end
|
||||
o.datatype = "ipaddr"
|
||||
if nixio.fs.access("/tmp/dhcp.leases") or nixio.fs.access("/var/dhcp6.leases") then
|
||||
o.titleref = luci.dispatcher.build_url("admin", "status", "overview")
|
||||
end
|
||||
|
||||
o = x:option(Value, "macaddr", translate("MAC (optional)"))
|
||||
o.rmempty = true
|
||||
o.datatype = "macaddr"
|
||||
|
||||
o = x:option(Value, "rate", translate("Rate"))
|
||||
o.default = def_rate_dl or '50'
|
||||
o.size = 4
|
||||
o.datatype = "uinteger"
|
||||
|
||||
o = x:option(ListValue, "unit", translate("Unit"))
|
||||
o.default = def_unit_dl or "kbytes"
|
||||
o:value("bytes", "Bytes/s")
|
||||
o:value("kbytes", "KBytes/s")
|
||||
o:value("mbytes", "MBytes/s")
|
||||
|
||||
--
|
||||
-- Static Limit Rate - Upload Rate
|
||||
--
|
||||
y = m:section(TypedSection, "upload", translate("Static QoS-Upload Rate"))
|
||||
y.anonymous = true
|
||||
y.addremove = true
|
||||
y.template = "cbi/tblsection"
|
||||
|
||||
o = y:option(Value, "hostname", translate("Hostname"))
|
||||
o.datatype = "hostname"
|
||||
o.default = 'undefined'
|
||||
|
||||
if has_ipv6 then
|
||||
o = y:option(Value, "ipaddr", translate("IP Address(V4 / V6)"))
|
||||
else
|
||||
o = y:option(Value, "ipaddr", translate("IP Address(V4 Only)"))
|
||||
end
|
||||
o.datatype = "ipaddr"
|
||||
if nixio.fs.access("/tmp/dhcp.leases") or nixio.fs.access("/var/dhcp6.leases") then
|
||||
o.titleref = luci.dispatcher.build_url("admin", "status", "overview")
|
||||
end
|
||||
|
||||
o = y:option(Value, "macaddr", translate("MAC (optional)"))
|
||||
o.rmempty = true
|
||||
o.datatype = "macaddr"
|
||||
|
||||
o = y:option(Value, "rate", translate("Rate"))
|
||||
o.default = def_rate_ul or '50'
|
||||
o.size = 4
|
||||
o.datatype = "uinteger"
|
||||
|
||||
o = y:option(ListValue, "unit", translate("Unit"))
|
||||
o.default = def_unit_ul or "kbytes"
|
||||
o:value("bytes", "Bytes/s")
|
||||
o:value("kbytes", "KBytes/s")
|
||||
o:value("mbytes", "MBytes/s")
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Traffic Priority Settings
|
||||
--
|
||||
if enable_priority == "1" then
|
||||
|
||||
s = m:section(TypedSection, "priority", translate("Traffic Priority Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
o = s:option(ListValue, "protocol", translate("Protocol"))
|
||||
o.default = "tcp"
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("udplite", "UDP-Lite")
|
||||
o:value("sctp", "SCTP")
|
||||
o:value("dccp", "DCCP")
|
||||
|
||||
o = s:option(ListValue, "priority", translate("Priority"))
|
||||
o.default = "1"
|
||||
o:value("-400", "1")
|
||||
o:value("-300", "2")
|
||||
o:value("-225", "3")
|
||||
o:value("-200", "4")
|
||||
o:value("-150", "5")
|
||||
o:value("-100", "6")
|
||||
o:value("0", "7")
|
||||
o:value("50", "8")
|
||||
o:value("100", "9")
|
||||
o:value("225", "10")
|
||||
o:value("300", "11")
|
||||
|
||||
o = s:option(Value, "service", translate("Service"), translate("e.g. https, 23, (separator is comma)"))
|
||||
o.default = '?'
|
||||
|
||||
o = s:option(Value, "comment", translate("Comment"))
|
||||
o.default = '?'
|
||||
|
||||
end
|
||||
|
||||
return m
|
167
applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm
Normal file
167
applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm
Normal file
|
@ -0,0 +1,167 @@
|
|||
<%#
|
||||
Copyright 2018 Rosy Song <rosysong@rosinson.com>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var RC = { };
|
||||
var em = 0;
|
||||
var ec = 1;
|
||||
|
||||
var rate_table_dl;
|
||||
var rate_table_ul;
|
||||
|
||||
function init_bytes(rl, ra) {
|
||||
var bytes_pre;
|
||||
var obj = { };
|
||||
obj.chain = rl.chain;
|
||||
obj.ipaddr = rl.expr[em].match.right;
|
||||
obj.bytes = rl.expr[ec].counter.bytes;
|
||||
obj.packets = rl.expr[ec].counter.packets;
|
||||
obj.rate = 0;
|
||||
|
||||
if (RC[obj.chain] && RC[obj.chain][obj.ipaddr])
|
||||
bytes_pre = RC[obj.chain][obj.ipaddr];
|
||||
else
|
||||
bytes_pre = 0;
|
||||
|
||||
obj.rate = (bytes_pre > 0) ? (obj.bytes - bytes_pre) / 3: 0;
|
||||
|
||||
if (!RC[obj.chain])
|
||||
RC[obj.chain] = { };
|
||||
RC[obj.chain][obj.ipaddr] = obj.bytes;
|
||||
|
||||
if (!ra[obj.chain])
|
||||
ra[obj.chain] = [ ];
|
||||
ra[obj.chain].push(obj);
|
||||
} /* function init_bytes(rl, ra) */
|
||||
|
||||
function bytes_label(bytes) {
|
||||
var uby = '<%:kB%>';
|
||||
var kby = (bytes / 1024);
|
||||
|
||||
if (kby > 1024) {
|
||||
uby = '<%:MB%>';
|
||||
kby = (kby / 1024);
|
||||
}
|
||||
|
||||
return String.format("%f %s", kby.toFixed(2), uby);
|
||||
}
|
||||
|
||||
function print_table(tbl, rs, ra) {
|
||||
ra.sort(function(a, b) { return b.rate - a.rate });
|
||||
for (var i = 0; i < ra.length; i++) {
|
||||
rs.push([
|
||||
ra[i].ipaddr,
|
||||
bytes_label(ra[i].rate) + '/s',
|
||||
bytes_label(ra[i].bytes),
|
||||
'%s Pkts.'.format(ra[i].packets),
|
||||
]);
|
||||
}
|
||||
cbi_update_table(tbl, rs, '<em><%:No information available%></em>');
|
||||
} /* function print_table(tbl, ra) */
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
if (!RC)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
rate_table_dl = document.getElementById('rate_table_dl');
|
||||
rate_table_ul = document.getElementById('rate_table_ul');
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/rate_status")%>', null,
|
||||
function(x, json)
|
||||
{
|
||||
var RA = {};
|
||||
var rows_dl = [];
|
||||
var rows_ul = [];
|
||||
|
||||
var rules = json.nftables;
|
||||
for (var i = 0; i < rules.length; i++)
|
||||
{
|
||||
if (!rules[i].rule)
|
||||
continue;
|
||||
if (rules[i].rule.table != 'nft-qos-monitor')
|
||||
continue;
|
||||
|
||||
var rl = rules[i].rule;
|
||||
switch (rl.chain)
|
||||
{
|
||||
case 'download':
|
||||
case 'upload': init_bytes(rl, RA); break;
|
||||
}
|
||||
} /* for (var i = 0; i < rules.length; i++) */
|
||||
|
||||
/* display the result */
|
||||
if (RA.download) {
|
||||
while (rate_table_dl.firstElementChild !== rate_table_dl.lastElementChild)
|
||||
rate_table_dl.removeChild(rate_table_dl.lastElementChild);
|
||||
print_table(rate_table_dl, rows_dl, RA.download);
|
||||
}
|
||||
if (RA.upload) {
|
||||
while (rate_table_ul.firstElementChild !== rate_table_ul.lastElementChild)
|
||||
rate_table_ul.removeChild(rate_table_ul.lastElementChild);
|
||||
print_table(rate_table_ul, rows_ul, RA.upload);
|
||||
}
|
||||
|
||||
} /* function(x, json) */
|
||||
); /* XHR.poll() */
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Rate%></h2>
|
||||
|
||||
<div class="cbi-map-descr"><%:This page gives an overview over currently download/upload rate.%></div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend><%:Realtime Download Rate%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table" id="rate_table_dl">
|
||||
<div class="tr table-titles">
|
||||
<div class="th col-2 hide-xs"><%:IP Address%></div>
|
||||
<div class="th col-2"><%:Download Rate%></div>
|
||||
<div class="th col-7"><%:Bytes Total%></div>
|
||||
<div class="th col-7"><%:Packets Total%></div>
|
||||
</div>
|
||||
<div class="tr placeholder">
|
||||
<div class="td">
|
||||
<em><%:Collecting data...%></em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend><%:Realtime Upload Rate%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table" id="rate_table_ul">
|
||||
<div class="tr table-titles">
|
||||
<div class="th col-2 hide-xs"><%:IP Address%></div>
|
||||
<div class="th col-2"><%:Upload Rate%></div>
|
||||
<div class="th col-7"><%:Bytes Total%></div>
|
||||
<div class="th col-7"><%:Packets Total%></div>
|
||||
</div>
|
||||
<div class="tr placeholder">
|
||||
<div class="td">
|
||||
<em><%:Collecting data...%></em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
161
applications/luci-app-nft-qos/po/templates/nft-qos.pot
Normal file
161
applications/luci-app-nft-qos/po/templates/nft-qos.pot
Normal file
|
@ -0,0 +1,161 @@
|
|||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Bytes Total"
|
||||
msgstr ""
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default Download Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default Download Unit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default Network Interface"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default Upload Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default Upload Unit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default unit for download rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default unit for upload rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default value for download bandwidth"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default value for download rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default value for upload bandwidth"
|
||||
msgstr ""
|
||||
|
||||
msgid "Default value for upload rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download Bandwidth (Mbps)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Download Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dynamic Rate Limit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable Limit Rate Feature"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable Traffic Priority"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable this feature"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hostname"
|
||||
msgstr ""
|
||||
|
||||
msgid "IP Address"
|
||||
msgstr ""
|
||||
|
||||
msgid "Limit Enable"
|
||||
msgstr ""
|
||||
|
||||
msgid "Limit Type"
|
||||
msgstr ""
|
||||
|
||||
msgid "MAC (optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "MB"
|
||||
msgstr ""
|
||||
|
||||
msgid "NFT-QoS Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc"
|
||||
msgstr ""
|
||||
|
||||
msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc"
|
||||
msgstr ""
|
||||
|
||||
msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc"
|
||||
msgstr ""
|
||||
|
||||
msgid "No information available"
|
||||
msgstr ""
|
||||
|
||||
msgid "Packets Total"
|
||||
msgstr ""
|
||||
|
||||
msgid "Priority"
|
||||
msgstr ""
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr ""
|
||||
|
||||
msgid "Qos over Nftables"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rate Limit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Realtime Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Service"
|
||||
msgstr ""
|
||||
|
||||
msgid "Static QoS-Download Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Static QoS-Upload Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Target Network (IPv4/MASK)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Target Network6 (IPv6/MASK)"
|
||||
msgstr ""
|
||||
|
||||
msgid "This page gives an overview over currently download/upload rate."
|
||||
msgstr ""
|
||||
|
||||
msgid "Traffic Priority"
|
||||
msgstr ""
|
||||
|
||||
msgid "Traffic Priority Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type of Limit Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload Bandwidth (Mbps)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "White List for Limit Rate"
|
||||
msgstr ""
|
||||
|
||||
msgid "e.g. https, 23, (separator is comma)"
|
||||
msgstr ""
|
||||
|
||||
msgid "kB"
|
||||
msgstr ""
|
BIN
applications/luci-app-nft-qos/po/templates/zh_CN.mo
Normal file
BIN
applications/luci-app-nft-qos/po/templates/zh_CN.mo
Normal file
Binary file not shown.
172
applications/luci-app-nft-qos/po/templates/zh_CN.po
Normal file
172
applications/luci-app-nft-qos/po/templates/zh_CN.po
Normal file
|
@ -0,0 +1,172 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.7\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"Language: zh_CN\n"
|
||||
|
||||
msgid "Bytes Total"
|
||||
msgstr "字节总数"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据"
|
||||
|
||||
msgid "Comment"
|
||||
msgstr "注释"
|
||||
|
||||
msgid "Default Download Rate"
|
||||
msgstr "默认下载速率"
|
||||
|
||||
msgid "Default Download Unit"
|
||||
msgstr "默认下载速率单位"
|
||||
|
||||
msgid "Default Network Interface"
|
||||
msgstr "默认网络接口"
|
||||
|
||||
msgid "Default Upload Rate"
|
||||
msgstr "默认上传速率"
|
||||
|
||||
msgid "Default Upload Unit"
|
||||
msgstr "默认上传速率单位"
|
||||
|
||||
msgid "Default unit for download rate"
|
||||
msgstr "默认的下载速率单位"
|
||||
|
||||
msgid "Default unit for upload rate"
|
||||
msgstr "默认的上传速率单位"
|
||||
|
||||
msgid "Default value for download bandwidth"
|
||||
msgstr "下载带宽的默认值"
|
||||
|
||||
msgid "Default value for download rate"
|
||||
msgstr "下载速率的默认值"
|
||||
|
||||
msgid "Default value for upload bandwidth"
|
||||
msgstr "上传带宽的默认值"
|
||||
|
||||
msgid "Default value for upload rate"
|
||||
msgstr "上传速率的默认值"
|
||||
|
||||
msgid "Download Bandwidth (Mbps)"
|
||||
msgstr "下载带宽 (Mbps)"
|
||||
|
||||
msgid "Download Rate"
|
||||
msgstr "下载速率"
|
||||
|
||||
msgid "Dynamic Rate Limit"
|
||||
msgstr "动态QoS"
|
||||
|
||||
msgid "Enable Limit Rate Feature"
|
||||
msgstr "开启速率限制功能"
|
||||
|
||||
msgid "Enable Traffic Priority"
|
||||
msgstr "开启流量优先级"
|
||||
|
||||
msgid "Enable this feature"
|
||||
msgstr "开启这个功能"
|
||||
|
||||
msgid "Hostname"
|
||||
msgstr "主机名"
|
||||
|
||||
msgid "IP Address"
|
||||
msgstr "IP地址"
|
||||
|
||||
msgid "Limit Enable"
|
||||
msgstr "限速开启"
|
||||
|
||||
msgid "Limit Type"
|
||||
msgstr "限速类型"
|
||||
|
||||
msgid "MAC (optional)"
|
||||
msgstr "物理地址(可选)"
|
||||
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
msgid "NFT-QoS Settings"
|
||||
msgstr "NFT-QoS 设置"
|
||||
|
||||
msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc"
|
||||
msgstr "流量整形的目标网络接口, 例如, br-lan, eth0.1, eth0, etc"
|
||||
|
||||
msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc"
|
||||
msgstr "将要应用规则的网络, 例如, 192.168.1.0/24, 10.2.0.0/16, 等等"
|
||||
|
||||
msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc"
|
||||
msgstr "将要应用规则的网络, 例如, AAAA::BBBB/64, CCCC::1/128, 等等"
|
||||
|
||||
msgid "No information available"
|
||||
msgstr "没有更多的信息"
|
||||
|
||||
msgid "Packets Total"
|
||||
msgstr "数据包总数"
|
||||
|
||||
msgid "Priority"
|
||||
msgstr "优先级"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "协议"
|
||||
|
||||
msgid "Qos over Nftables"
|
||||
msgstr "QoS Nftables版"
|
||||
|
||||
msgid "Rate"
|
||||
msgstr "速率"
|
||||
|
||||
msgid "Rate Limit"
|
||||
msgstr "速率限制"
|
||||
|
||||
msgid "Realtime Rate"
|
||||
msgstr "实时速率显示"
|
||||
|
||||
msgid "Service"
|
||||
msgstr "服务/端口"
|
||||
|
||||
msgid "Static QoS-Download Rate"
|
||||
msgstr "静态QoS-下载速率"
|
||||
|
||||
msgid "Static QoS-Upload Rate"
|
||||
msgstr "静态QoS-上传速率"
|
||||
|
||||
msgid "Target Network (IPv4/MASK)"
|
||||
msgstr "目标网络(IPv4地址/掩码)"
|
||||
|
||||
msgid "Target Network6 (IPv6/MASK)"
|
||||
msgstr "目标网络v6(IPv6地址/掩码)"
|
||||
|
||||
msgid "This page gives an overview over currently download/upload rate."
|
||||
msgstr "该页面提供了当前上传和下载速率的一个总览"
|
||||
|
||||
msgid "Traffic Priority"
|
||||
msgstr "流量优先级"
|
||||
|
||||
msgid "Traffic Priority Settings"
|
||||
msgstr "流量优先级设置"
|
||||
|
||||
msgid "Type of Limit Rate"
|
||||
msgstr "限速的类型"
|
||||
|
||||
msgid "Unit"
|
||||
msgstr "单位"
|
||||
|
||||
msgid "Upload Bandwidth (Mbps)"
|
||||
msgstr "上传带宽 (Mbps)"
|
||||
|
||||
msgid "Upload Rate"
|
||||
msgstr "上传速率"
|
||||
|
||||
msgid "White List for Limit Rate"
|
||||
msgstr "限速白名单"
|
||||
|
||||
msgid "e.g. https, 23, (separator is comma)"
|
||||
msgstr "例如, https, 23 (用逗号分隔)"
|
||||
|
||||
msgid "kB"
|
||||
msgstr "kB"
|
172
applications/luci-app-nft-qos/po/zh-cn/nft-qos.po
Normal file
172
applications/luci-app-nft-qos/po/zh-cn/nft-qos.po
Normal file
|
@ -0,0 +1,172 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.3\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"Language: zh_CN\n"
|
||||
|
||||
msgid "Bytes Total"
|
||||
msgstr "字节总数"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据"
|
||||
|
||||
msgid "Comment"
|
||||
msgstr "注释"
|
||||
|
||||
msgid "Default Download Rate"
|
||||
msgstr "默认下载速率"
|
||||
|
||||
msgid "Default Download Unit"
|
||||
msgstr "默认下载速率单位"
|
||||
|
||||
msgid "Default Network Interface"
|
||||
msgstr "默认网络接口"
|
||||
|
||||
msgid "Default Upload Rate"
|
||||
msgstr "默认上传速率"
|
||||
|
||||
msgid "Default Upload Unit"
|
||||
msgstr "默认上传速率单位"
|
||||
|
||||
msgid "Default unit for download rate"
|
||||
msgstr "默认的下载速率单位"
|
||||
|
||||
msgid "Default unit for upload rate"
|
||||
msgstr "默认的上传速率单位"
|
||||
|
||||
msgid "Default value for download bandwidth"
|
||||
msgstr "下载带宽的默认值"
|
||||
|
||||
msgid "Default value for download rate"
|
||||
msgstr "下载速率的默认值"
|
||||
|
||||
msgid "Default value for upload bandwidth"
|
||||
msgstr "上传带宽的默认值"
|
||||
|
||||
msgid "Default value for upload rate"
|
||||
msgstr "上传速率的默认值"
|
||||
|
||||
msgid "Download Bandwidth (Mbps)"
|
||||
msgstr "下载带宽 (Mbps)"
|
||||
|
||||
msgid "Download Rate"
|
||||
msgstr "下载速率"
|
||||
|
||||
msgid "Dynamic Rate Limit"
|
||||
msgstr "动态QoS"
|
||||
|
||||
msgid "Enable Limit Rate Feature"
|
||||
msgstr "开启速率限制功能"
|
||||
|
||||
msgid "Enable Traffic Priority"
|
||||
msgstr "开启流量优先级"
|
||||
|
||||
msgid "Enable this feature"
|
||||
msgstr "开启这个功能"
|
||||
|
||||
msgid "Hostname"
|
||||
msgstr "主机名"
|
||||
|
||||
msgid "IP Address"
|
||||
msgstr "IP地址"
|
||||
|
||||
msgid "Limit Enable"
|
||||
msgstr "限速开启"
|
||||
|
||||
msgid "Limit Type"
|
||||
msgstr "限速类型"
|
||||
|
||||
msgid "MAC (optional)"
|
||||
msgstr "物理地址(可选)"
|
||||
|
||||
msgid "MB"
|
||||
msgstr "MB"
|
||||
|
||||
msgid "NFT-QoS Settings"
|
||||
msgstr "NFT-QoS 设置"
|
||||
|
||||
msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc"
|
||||
msgstr "流量整形的目标网络接口, 例如, br-lan, eth0.1, eth0, etc"
|
||||
|
||||
msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc"
|
||||
msgstr "将要应用规则的网络, 例如, 192.168.1.0/24, 10.2.0.0/16, 等等"
|
||||
|
||||
msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc"
|
||||
msgstr "将要应用规则的网络, 例如, AAAA::BBBB/64, CCCC::1/128, 等等"
|
||||
|
||||
msgid "No information available"
|
||||
msgstr "没有更多的信息"
|
||||
|
||||
msgid "Packets Total"
|
||||
msgstr "数据包总数"
|
||||
|
||||
msgid "Priority"
|
||||
msgstr "优先级"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "协议"
|
||||
|
||||
msgid "Qos over Nftables"
|
||||
msgstr "QoS Nftables版"
|
||||
|
||||
msgid "Rate"
|
||||
msgstr "速率"
|
||||
|
||||
msgid "Rate Limit"
|
||||
msgstr "速率限制"
|
||||
|
||||
msgid "Realtime Rate"
|
||||
msgstr "实时速率显示"
|
||||
|
||||
msgid "Service"
|
||||
msgstr "服务/端口"
|
||||
|
||||
msgid "Static QoS-Download Rate"
|
||||
msgstr "静态QoS-下载速率"
|
||||
|
||||
msgid "Static QoS-Upload Rate"
|
||||
msgstr "静态QoS-上传速率"
|
||||
|
||||
msgid "Target Network (IPv4/MASK)"
|
||||
msgstr "目标网络(IPv4地址/掩码)"
|
||||
|
||||
msgid "Target Network6 (IPv6/MASK)"
|
||||
msgstr "目标网络v6(IPv6地址/掩码)"
|
||||
|
||||
msgid "This page gives an overview over currently download/upload rate."
|
||||
msgstr "该页面提供了当前上传和下载速率的一个总览"
|
||||
|
||||
msgid "Traffic Priority"
|
||||
msgstr "流量优先级"
|
||||
|
||||
msgid "Traffic Priority Settings"
|
||||
msgstr "流量优先级设置"
|
||||
|
||||
msgid "Type of Limit Rate"
|
||||
msgstr "限速的类型"
|
||||
|
||||
msgid "Unit"
|
||||
msgstr "单位"
|
||||
|
||||
msgid "Upload Bandwidth (Mbps)"
|
||||
msgstr "上传带宽 (Mbps)"
|
||||
|
||||
msgid "Upload Rate"
|
||||
msgstr "上传速率"
|
||||
|
||||
msgid "White List for Limit Rate"
|
||||
msgstr "限速白名单"
|
||||
|
||||
msgid "e.g. https, 23, (separator is comma)"
|
||||
msgstr "例如, https, 23 (用逗号分隔)"
|
||||
|
||||
msgid "kB"
|
||||
msgstr "kB"
|
Loading…
Reference in a new issue