You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
9.3 KiB

  1. --[[
  2. LuCI - Lua Configuration Interface
  3. Copyright 2014 Steven Barth <steven@midlink.org>
  4. Copyright 2014 Dave Taht <dave.taht@bufferbloat.net>
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. $Id$
  10. ]]--
  11. local wa = require "luci.tools.webadmin"
  12. local fs = require "nixio.fs"
  13. local net = require "luci.model.network".init()
  14. local sys = require "luci.sys"
  15. --local ifaces = net:get_interfaces()
  16. local ifaces = sys.net:devices()
  17. local path = "/usr/lib/sqm"
  18. m = Map("sqm", translate("Smart Queue Management"),
  19. translate("With <abbr title=\"Smart Queue Management\">SQM</abbr> you " ..
  20. "can enable traffic shaping, better mixing (Fair Queueing)," ..
  21. " active queue length management (AQM) " ..
  22. " and prioritisation on one " ..
  23. "network interface."))
  24. s = m:section(TypedSection, "queue", translate("Queues"))
  25. s:tab("tab_basic", translate("Basic Settings"))
  26. s:tab("tab_qdisc", translate("Queue Discipline"))
  27. s:tab("tab_linklayer", translate("Link Layer Adaptation"))
  28. s.addremove = true -- set to true to allow adding SQM instances in the GUI
  29. s.anonymous = true
  30. -- BASIC
  31. e = s:taboption("tab_basic", Flag, "enabled", translate("Enable this SQM instance."))
  32. e.rmempty = false
  33. -- sm: following jow's advise, be helpful to the user and enable
  34. -- sqm's init script if even a single sm instance/interface
  35. -- is enabled; this is unexpected in that the init script gets
  36. -- enabled as soon as at least one sqm instance is enabled
  37. -- and that state is saved, so it does not require "Save & Apply"
  38. -- to effect the init scripts.
  39. -- the implementation was inpired/lifted from
  40. -- https://github.com/openwrt/luci/blob/master/applications/luci-app-minidlna/luasrc/model/cbi/minidlna.lua
  41. function e.write(self, section, value)
  42. if value == "1" then
  43. luci.sys.init.enable("sqm")
  44. 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.")
  45. -- luci.sys.call("/etc/init.d/sqm start >/dev/null")
  46. -- else
  47. -- luci.sys.call("/etc/init.d/sqm stop >/dev/null")
  48. -- luci.sys.init.disable("sqm")
  49. end
  50. return Flag.write(self, section, value)
  51. end
  52. -- TODO: inform the user what we just did...
  53. n = s:taboption("tab_basic", ListValue, "interface", translate("Interface name"))
  54. -- sm lifted from luci-app-wol, the original implementation failed to show pppoe-ge00 type interface names
  55. for _, iface in ipairs(ifaces) do
  56. -- if iface:is_up() then
  57. -- n:value(iface:name())
  58. -- end
  59. if iface ~= "lo" then
  60. n:value(iface)
  61. end
  62. end
  63. n.rmempty = false
  64. dl = s:taboption("tab_basic", Value, "download", translate("Download speed (kbit/s) (ingress) set to 0 to selectively disable ingress shaping:"))
  65. dl.datatype = "and(uinteger,min(0))"
  66. dl.rmempty = false
  67. ul = s:taboption("tab_basic", Value, "upload", translate("Upload speed (kbit/s) (egress) set to 0 to selectively disable egress shaping:"))
  68. ul.datatype = "and(uinteger,min(0))"
  69. ul.rmempty = false
  70. -- QDISC
  71. c = s:taboption("tab_qdisc", ListValue, "qdisc", translate("Queueing discipline"))
  72. c:value("fq_codel", "fq_codel ("..translate("default")..")")
  73. c:value("efq_codel")
  74. c:value("nfq_codel")
  75. c:value("sfq")
  76. c:value("codel")
  77. c:value("ns2_codel")
  78. c:value("pie")
  79. c:value("sfq")
  80. c:value("cake")
  81. c.default = "fq_codel"
  82. c.rmempty = false
  83. local qos_desc = ""
  84. sc = s:taboption("tab_qdisc", ListValue, "script", translate("Queue setup script"))
  85. for file in fs.dir(path) do
  86. if string.find(file, ".qos$") then
  87. sc:value(file)
  88. end
  89. if string.find(file, ".qos.help$") then
  90. fh = io.open(path .. "/" .. file, "r")
  91. qos_desc = qos_desc .. "<p><b>" .. file:gsub(".help$", "") .. ":</b><br />" .. fh:read("*a") .. "</p>"
  92. end
  93. end
  94. sc.default = "simple.qos"
  95. sc.rmempty = false
  96. sc.description = qos_desc
  97. 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."))
  98. ad.default = false
  99. ad.rmempty = true
  100. squash_dscp = s:taboption("tab_qdisc", ListValue, "squash_dscp", translate("Squash DSCP on inbound packets (ingress):"))
  101. squash_dscp:value("1", "SQUASH")
  102. squash_dscp:value("0", "DO NOT SQUASH")
  103. squash_dscp.default = "1"
  104. squash_dscp.rmempty = true
  105. squash_dscp:depends("qdisc_advanced", "1")
  106. squash_ingress = s:taboption("tab_qdisc", ListValue, "squash_ingress", translate("Ignore DSCP on ingress:"))
  107. squash_ingress:value("1", "Ignore")
  108. squash_ingress:value("0", "Allow")
  109. squash_ingress.default = "1"
  110. squash_ingress.rmempty = true
  111. squash_ingress:depends("qdisc_advanced", "1")
  112. iecn = s:taboption("tab_qdisc", ListValue, "ingress_ecn", translate("Explicit congestion notification (ECN) status on inbound packets (ingress):"))
  113. iecn:value("ECN", "ECN ("..translate("default")..")")
  114. iecn:value("NOECN")
  115. iecn.default = "ECN"
  116. iecn.rmempty = true
  117. iecn:depends("qdisc_advanced", "1")
  118. eecn = s:taboption("tab_qdisc", ListValue, "egress_ecn", translate("Explicit congestion notification (ECN) status on outbound packets (egress)."))
  119. eecn:value("NOECN", "NOECN ("..translate("default")..")")
  120. eecn:value("ECN")
  121. eecn.default = "NOECN"
  122. eecn.rmempty = true
  123. eecn:depends("qdisc_advanced", "1")
  124. 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."))
  125. ad2.default = false
  126. ad2.rmempty = true
  127. ad2:depends("qdisc_advanced", "1")
  128. ilim = s:taboption("tab_qdisc", Value, "ilimit", translate("Hard limit on ingress queues; leave empty for default."))
  129. -- ilim.default = 1000
  130. ilim.isnumber = true
  131. ilim.datatype = "and(uinteger,min(0))"
  132. ilim.rmempty = true
  133. ilim:depends("qdisc_really_really_advanced", "1")
  134. elim = s:taboption("tab_qdisc", Value, "elimit", translate("Hard limit on egress queues; leave empty for default."))
  135. -- elim.default = 1000
  136. elim.datatype = "and(uinteger,min(0))"
  137. elim.rmempty = true
  138. elim:depends("qdisc_really_really_advanced", "1")
  139. 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."))
  140. itarg.datatype = "string"
  141. itarg.rmempty = true
  142. itarg:depends("qdisc_really_really_advanced", "1")
  143. 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."))
  144. etarg.datatype = "string"
  145. etarg.rmempty = true
  146. etarg:depends("qdisc_really_really_advanced", "1")
  147. 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."))
  148. iqdisc_opts.rmempty = true
  149. iqdisc_opts:depends("qdisc_really_really_advanced", "1")
  150. 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."))
  151. eqdisc_opts.rmempty = true
  152. eqdisc_opts:depends("qdisc_really_really_advanced", "1")
  153. -- LINKLAYER
  154. ll = s:taboption("tab_linklayer", ListValue, "linklayer", translate("Which link layer to account for:"))
  155. ll:value("none", "none ("..translate("default")..")")
  156. ll:value("ethernet", "Ethernet with overhead: select for e.g. VDSL2.")
  157. ll:value("atm", "ATM: select for e.g. ADSL1, ADSL2, ADSL2+.")
  158. -- ll:value("adsl") -- reduce the options
  159. ll.default = "none"
  160. po = s:taboption("tab_linklayer", Value, "overhead", translate("Per Packet Overhead (byte):"))
  161. po.datatype = "and(integer,min(-1500))"
  162. po.default = 0
  163. po.isnumber = true
  164. po.rmempty = true
  165. po:depends("linklayer", "ethernet")
  166. -- po:depends("linklayer", "adsl")
  167. po:depends("linklayer", "atm")
  168. 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."))
  169. adll.rmempty = true
  170. adll:depends("linklayer", "ethernet")
  171. -- adll:depends("linklayer", "adsl")
  172. adll:depends("linklayer", "atm")
  173. smtu = s:taboption("tab_linklayer", Value, "tcMTU", translate("Maximal Size for size and rate calculations, tcMTU (byte); needs to be >= interface MTU + overhead:"))
  174. smtu.datatype = "and(uinteger,min(0))"
  175. smtu.default = 2047
  176. smtu.isnumber = true
  177. smtu.rmempty = true
  178. smtu:depends("linklayer_advanced", "1")
  179. stsize = s:taboption("tab_linklayer", Value, "tcTSIZE", translate("Number of entries in size/rate tables, TSIZE; for ATM choose TSIZE = (tcMTU + 1) / 16:"))
  180. stsize.datatype = "and(uinteger,min(0))"
  181. stsize.default = 128
  182. stsize.isnumber = true
  183. stsize.rmempty = true
  184. stsize:depends("linklayer_advanced", "1")
  185. smpu = s:taboption("tab_linklayer", Value, "tcMPU", translate("Minimal packet size, MPU (byte); needs to be > 0 for ethernet size tables:"))
  186. smpu.datatype = "and(uinteger,min(0))"
  187. smpu.default = 0
  188. smpu.isnumber = true
  189. smpu.rmempty = true
  190. smpu:depends("linklayer_advanced", "1")
  191. lla = s:taboption("tab_linklayer", ListValue, "linklayer_adaptation_mechanism", translate("Which linklayer adaptation mechanism to use; for testing only"))
  192. lla:value("cake")
  193. lla:value("htb_private")
  194. lla:value("tc_stab", "tc_stab ("..translate("default")..")")
  195. lla.default = "tc_stab"
  196. lla.rmempty = true
  197. lla:depends("linklayer_advanced", "1")
  198. -- PRORITIES?
  199. return m