luci-app-mwan3: fix legacy uci api usage
[project/luci.git] / applications / luci-app-mwan3 / luasrc / model / cbi / mwan / interface.lua
1 -- Copyright 2014 Aedan Renner <chipdankly@gmail.com
2 -- Copyright 2018 Florian Eckert <fe@dev.tdt.de>
3 -- Licensed to the public under the GNU General Public License v2.
4
5 dsp = require "luci.dispatcher"
6 uci = require "uci"
7
8
9 function interfaceWarnings(overview, count, iface_max)
10 local warnings = ""
11 if count <= iface_max then
12 warnings = string.format("<strong>%s</strong><br />",
13 translatef("There are currently %d of %d supported interfaces configured", count, iface_max)
14 )
15 else
16 warnings = string.format("<strong>%s</strong><br />",
17 translatef("WARNING: %d interfaces are configured exceeding the maximum of %d!", count, iface_max)
18 )
19 end
20
21 for i, k in pairs(overview) do
22 if overview[i]["network"] == false then
23 warnings = warnings .. string.format("<strong>%s</strong><br />",
24 translatef("WARNING: Interface %s are not found in /etc/config/network", i)
25 )
26 end
27
28 if overview[i]["default_route"] == false then
29 warnings = warnings .. string.format("<strong>%s</strong><br />",
30 translatef("WARNING: Interface %s has no default route in the main routing table", i)
31 )
32 end
33
34 if overview[i]["reliability"] == false then
35 warnings = warnings .. string.format("<strong>%s</strong><br />",
36 translatef("WARNING: Interface %s has a higher reliability " ..
37 "requirement than tracking hosts (%d)", i, overview[i]["tracking"])
38 )
39 end
40
41 if overview[i]["duplicate_metric"] == true then
42 warnings = warnings .. string.format("<strong>%s</strong><br />",
43 translatef("WARNING: Interface %s has a duplicate metric %s configured", i, overview[i]["metric"])
44 )
45 end
46 end
47
48 return warnings
49 end
50
51 function configCheck()
52 local overview = {}
53 local count = 0
54 local duplicate_metric = {}
55 uci.cursor():foreach("mwan3", "interface",
56 function (section)
57 local uci = uci.cursor(nil, "/var/state")
58 local iface = section[".name"]
59 overview[iface] = {}
60 count = count + 1
61 local network = uci:get("network", iface)
62 overview[iface]["network"] = false
63 if network ~= nil then
64 overview[iface]["network"] = true
65
66 local device = uci:get("network", iface, "ifname")
67 if device ~= nil then
68 overview[iface]["device"] = device
69 end
70
71 local metric = uci:get("network", iface, "metric")
72 if metric ~= nil then
73 overview[iface]["metric"] = metric
74 overview[iface]["duplicate_metric"] = false
75 for _, m in ipairs(duplicate_metric) do
76 if m == metric then
77 overview[iface]["duplicate_metric"] = true
78 end
79 end
80 table.insert(duplicate_metric, metric)
81 end
82
83 local dump = require("luci.util").ubus("network.interface.%s" % iface, "status", {})
84 overview[iface]["default_route"] = false
85 if dump and dump.route then
86 local _, route
87 for _, route in ipairs(dump.route) do
88 if dump.route[_].target == "0.0.0.0" then
89 overview[iface]["default_route"] = true
90 end
91 end
92 end
93 end
94
95 local trackingNumber = uci:get("mwan3", iface, "track_ip")
96 overview[iface]["tracking"] = 0
97 if trackingNumber and #trackingNumber > 0 then
98 overview[iface]["tracking"] = #trackingNumber
99 overview[iface]["reliability"] = false
100 local reliabilityNumber = tonumber(uci:get("mwan3", iface, "reliability"))
101 if reliabilityNumber and reliabilityNumber <= #trackingNumber then
102 overview[iface]["reliability"] = true
103 end
104 end
105 end
106 )
107
108 -- calculate iface_max usage from firewall mmx_mask
109 function bit(p)
110 return 2 ^ (p - 1)
111 end
112 function hasbit(x, p)
113 return x % (p + p) >= p
114 end
115 function setbit(x, p)
116 return hasbit(x, p) and x or x + p
117 end
118
119 local uci = require("uci").cursor(nil, "/var/state")
120 local mmx_mask = uci:get("mwan3", "globals", "mmx_mask") or "0x3F00"
121 local number = tonumber(mmx_mask, 16)
122 local bits = 0
123 local iface_max = 0
124 for i=1,16 do
125 if hasbit(number, bit(i)) then
126 bits = bits + 1
127 iface_max = setbit( iface_max, bit(bits))
128 end
129 end
130
131 -- subtract blackhole, unreachable and default table from iface_max
132 iface_max = iface_max - 3
133
134 return overview, count, iface_max
135 end
136
137 m5 = Map("mwan3", translate("MWAN - Interfaces"),
138 interfaceWarnings(configCheck()))
139
140 mwan_interface = m5:section(TypedSection, "interface", nil,
141 translate("MWAN supports up to 250 physical and/or logical interfaces<br />" ..
142 "MWAN requires that all interfaces have a unique metric configured in /etc/config/network<br />" ..
143 "Names must match the interface name found in /etc/config/network (see advanced tab)<br />" ..
144 "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
145 "Interfaces may not share the same name as configured members, policies or rules"))
146 mwan_interface.addremove = true
147 mwan_interface.dynamic = false
148 mwan_interface.sectionhead = translate("Interface")
149 mwan_interface.sortable = false
150 mwan_interface.template = "cbi/tblsection"
151 mwan_interface.extedit = dsp.build_url("admin", "network", "mwan", "interface", "%s")
152 function mwan_interface.create(self, section)
153 TypedSection.create(self, section)
154 m5.uci:save("mwan3")
155 luci.http.redirect(dsp.build_url("admin", "network", "mwan", "interface", section))
156 end
157
158 enabled = mwan_interface:option(DummyValue, "enabled", translate("Enabled"))
159 enabled.rawhtml = true
160 function enabled.cfgvalue(self, s)
161 if self.map:get(s, "enabled") == "1" then
162 return translate("Yes")
163 else
164 return translate("No")
165 end
166 end
167
168 track_method = mwan_interface:option(DummyValue, "track_method", translate("Tracking method"))
169 track_method.rawhtml = true
170 function track_method.cfgvalue(self, s)
171 local tracked = self.map:get(s, "track_ip")
172 if tracked then
173 return self.map:get(s, "track_method") or "&#8212;"
174 else
175 return "&#8212;"
176 end
177 end
178
179 reliability = mwan_interface:option(DummyValue, "reliability", translate("Tracking reliability"))
180 reliability.rawhtml = true
181 function reliability.cfgvalue(self, s)
182 local tracked = self.map:get(s, "track_ip")
183 if tracked then
184 return self.map:get(s, "reliability") or "&#8212;"
185 else
186 return "&#8212;"
187 end
188 end
189
190 interval = mwan_interface:option(DummyValue, "interval", translate("Ping interval"))
191 interval.rawhtml = true
192 function interval.cfgvalue(self, s)
193 local tracked = self.map:get(s, "track_ip")
194 if tracked then
195 local intervalValue = self.map:get(s, "interval")
196 if intervalValue then
197 return intervalValue .. "s"
198 else
199 return "&#8212;"
200 end
201 else
202 return "&#8212;"
203 end
204 end
205
206 down = mwan_interface:option(DummyValue, "down", translate("Interface down"))
207 down.rawhtml = true
208 function down.cfgvalue(self, s)
209 local tracked = self.map:get(s, "track_ip")
210 if tracked then
211 return self.map:get(s, "down") or "&#8212;"
212 else
213 return "&#8212;"
214 end
215 end
216
217 up = mwan_interface:option(DummyValue, "up", translate("Interface up"))
218 up.rawhtml = true
219 function up.cfgvalue(self, s)
220 local tracked = self.map:get(s, "track_ip")
221 if tracked then
222 return self.map:get(s, "up") or "&#8212;"
223 else
224 return "&#8212;"
225 end
226 end
227
228 metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
229 metric.rawhtml = true
230 function metric.cfgvalue(self, s)
231 local uci = uci.cursor(nil, "/var/state")
232 local metric = uci:get("network", s, "metric")
233 if metric then
234 return metric
235 else
236 return "&#8212;"
237 end
238 end
239
240 return m5