4 Copyright 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
20 local type, next, pairs, ipairs, loadfile, table, tonumber, math, i18n
21 = type, next, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n
23 local nxo = require "nixio"
24 local ipc = require "luci.ip"
25 local sys = require "luci.sys"
26 local utl = require "luci.util"
27 local dsp = require "luci.dispatcher"
28 local uci = require "luci.model.uci"
30 module "luci.model.network"
33 local ifs, brs, sws, tns, uci_r, uci_s
35 function _list_del(c, s, o, r)
36 local val = uci_r:get(c, s, o)
39 if type(val) == "string" then
40 for val in val:gmatch("%S+") do
46 uci_r:set(c, s, o, table.concat(l, " "))
50 elseif type(val) == "table" then
51 for _, val in ipairs(val) do
65 function _list_add(c, s, o, a)
66 local val = uci_r:get(c, s, o) or ""
67 if type(val) == "string" then
69 for val in val:gmatch("%S+") do
75 uci_r:set(c, s, o, table.concat(l, " "))
76 elseif type(val) == "table" then
78 for _, val in ipairs(val) do
88 function _stror(s1, s2)
89 if not s1 or #s1 == 0 then
90 return s2 and #s2 > 0 and s2
96 function _get(c, s, o)
97 return uci_r:get(c, s, o)
100 function _set(c, s, o, v)
102 if type(v) == "boolean" then v = v and "1" or "0" end
103 return uci_r:set(c, s, o, v)
105 return uci_r:delete(c, s, o)
109 function _wifi_iface(x)
111 x:match("^wlan%d") or x:match("^wl%d") or x:match("^ath%d") or
112 x:match("^%w+%.network%d")
116 function _wifi_lookup(ifn)
117 -- got a radio#.network# pseudo iface, locate the corresponding section
118 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
119 if radio and ifnidx then
123 ifnidx = tonumber(ifnidx)
124 uci_r:foreach("wireless", "wifi-iface",
126 if s.device == radio then
128 if num == ifnidx then
137 -- looks like wifi, try to locate the section via state vars
138 elseif _wifi_iface(ifn) then
141 uci_s:foreach("wireless", "wifi-iface",
143 if s.ifname == ifn then
153 function _iface_virtual(x)
155 x:match("^6in4-%w") or x:match("^6to4-%w") or x:match("^3g-%w") or
156 x:match("^ppp-%w") or x:match("^pppoe-%w") or x:match("^pppoa-%w") or
161 function _iface_ignore(x)
163 x:match("^wmaster%d") or x:match("^wifi%d") or x:match("^hwsim%d") or
164 x:match("^imq%d") or x:match("^mon.wlan%d") or
165 x == "sit0" or x == "lo" or _iface_virtual(x)
170 function init(cursor)
171 uci_r = cursor or uci_r or uci.cursor()
172 uci_s = uci_r:substate()
179 -- read interface information
181 for n, i in ipairs(nxo.getifaddrs()) do
182 local name = i.name:match("[^:]+")
183 local prnt = name:match("^([^%.]+)%.")
185 if _iface_virtual(name) then
189 if tns[name] or not _iface_ignore(name) then
190 ifs[name] = ifs[name] or {
191 idx = i.ifindex or n,
204 if i.family == "packet" then
205 ifs[name].flags = i.flags
206 ifs[name].stats = i.data
207 ifs[name].macaddr = i.addr
208 elseif i.family == "inet" then
209 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
210 elseif i.family == "inet6" then
211 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
216 -- read bridge informaton
218 for l in utl.execi("brctl show") do
219 if not l:match("STP") then
220 local r = utl.split(l, "%s+", nil, true)
226 ifnames = { ifs[r[4]] }
229 b.ifnames[1].bridge = b
233 b.ifnames[#b.ifnames+1] = ifs[r[2]]
234 b.ifnames[#b.ifnames].bridge = b
242 function save(self, ...)
247 function commit(self, ...)
252 function has_ipv6(self)
253 return nfs.access("/proc/net/ipv6_route")
256 function add_network(self, n, options)
257 local oldnet = self:get_network(n)
258 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
259 if uci_r:section("network", "interface", n, options) then
262 elseif oldnet and oldnet:is_empty() then
265 for k, v in pairs(options) do
273 function get_network(self, n)
274 if n and uci_r:get("network", n) == "interface" then
279 function get_networks(self)
283 uci_r:foreach("network", "interface",
285 nls[s['.name']] = network(s['.name'])
289 for n in utl.kspairs(nls) do
290 nets[#nets+1] = nls[n]
296 function del_network(self, n)
297 local r = uci_r:delete("network", n)
299 uci_r:delete_all("network", "alias",
300 function(s) return (s.interface == n) end)
302 uci_r:delete_all("network", "route",
303 function(s) return (s.interface == n) end)
305 uci_r:delete_all("network", "route6",
306 function(s) return (s.interface == n) end)
308 uci_r:foreach("wireless", "wifi-iface",
310 if s.network == n then
311 uci_r:delete("wireless", s['.name'], "network")
318 function rename_network(self, old, new)
320 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
321 r = uci_r:section("network", "interface", new, uci_r:get_all("network", old))
324 uci_r:foreach("network", "alias",
326 if s.interface == old then
327 uci_r:set("network", s['.name'], "interface", new)
331 uci_r:foreach("network", "route",
333 if s.interface == old then
334 uci_r:set("network", s['.name'], "interface", new)
338 uci_r:foreach("network", "route6",
340 if s.interface == old then
341 uci_r:set("network", s['.name'], "interface", new)
345 uci_r:foreach("wireless", "wifi-iface",
347 if s.network == old then
348 uci_r:set("wireless", s['.name'], "network", new)
352 uci_r:delete("network", old)
358 function get_interface(self, i)
359 if ifs[i] or _wifi_iface(i) then
364 uci_r:foreach("wireless", "wifi-iface",
367 num[s.device] = num[s.device] and num[s.device] + 1 or 1
368 if s['.name'] == i then
370 "%s.network%d" %{s.device, num[s.device] })
379 function get_interfaces(self)
385 -- find normal interfaces
386 uci_r:foreach("network", "interface",
388 for iface in utl.imatch(s.ifname) do
389 if not _iface_ignore(iface) and not _wifi_iface(iface) then
391 nfs[iface] = interface(iface)
396 for iface in utl.kspairs(ifs) do
397 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
398 nfs[iface] = interface(iface)
402 -- find vlan interfaces
403 uci_r:foreach("network", "switch_vlan",
405 local base = s.device or "-"
406 if not base:match("^eth%d") then
410 local vid = tonumber(s.vid or s.vlan)
411 if vid ~= nil and vid >= 0 and vid <= 4095 then
412 local iface = "%s.%d" %{ base, vid }
413 if not seen[iface] then
415 nfs[iface] = interface(iface)
420 for iface in utl.kspairs(nfs) do
421 ifaces[#ifaces+1] = nfs[iface]
424 -- find wifi interfaces
427 uci_r:foreach("wireless", "wifi-iface",
430 num[s.device] = num[s.device] and num[s.device] + 1 or 1
431 local i = "%s.network%d" %{ s.device, num[s.device] }
432 wfs[i] = interface(i)
436 for iface in utl.kspairs(wfs) do
437 ifaces[#ifaces+1] = wfs[iface]
443 function ignore_interface(self, x)
444 return _iface_ignore(x)
447 function get_wifidev(self, dev)
448 if uci_r:get("wireless", dev) == "wifi-device" then
453 function get_wifidevs(self)
457 uci_r:foreach("wireless", "wifi-device",
458 function(s) wfd[#wfd+1] = s['.name'] end)
461 for _, dev in utl.vspairs(wfd) do
462 devs[#devs+1] = wifidev(dev)
468 function get_wifinet(self, net)
469 local wnet = _wifi_lookup(net)
475 function add_wifinet(self, net, options)
476 if type(options) == "table" and options.device and
477 uci_r:get("wireless", options.device) == "wifi-device"
479 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
484 function del_wifinet(self, net)
485 local wnet = _wifi_lookup(net)
487 uci_r:delete("wireless", wnet)
494 network = utl.class()
496 function network.__init__(self, name)
500 function network._get(self, opt)
501 local v = uci_r:get("network", self.sid, opt)
502 if type(v) == "table" then
503 return table.concat(v, " ")
508 function network._ip(self, opt, family, list)
509 local ip = uci_s:get("network", self.sid, opt)
510 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
514 for ip in utl.imatch(ip) do
516 if ip then l[#l+1] = ip:string() end
521 return ip and ip:string()
526 function network.get(self, opt)
527 return _get("network", self.sid, opt)
530 function network.set(self, opt, val)
531 return _set("network", self.sid, opt, val)
534 function network.ifname(self)
535 local p = self:proto()
536 if self:is_bridge() then
537 return "br-" .. self.sid
538 elseif self:proto() == "relay" then
539 return uci_s:get("network", self.sid, "up") == "1" and "lo" or nil
540 elseif self:is_virtual() then
541 return p .. "-" .. self.sid
544 local dev = uci_r:get("network", self.sid, "ifname") or
545 uci_s:get("network", self.sid, "ifname")
547 dev = (type(dev) == "table") and dev[1] or dev
548 dev = (dev ~= nil) and dev:match("%S+")
551 uci_r:foreach("wireless", "wifi-iface",
554 num[s.device] = num[s.device]
555 and num[s.device] + 1 or 1
557 if s.network == self.sid then
558 dev = "%s.network%d" %{ s.device, num[s.device] }
569 function network.device(self)
570 local dev = uci_r:get("network", self.sid, "device") or
571 uci_s:get("network", self.sid, "device")
573 dev = (type(dev) == "table") and dev[1] or dev
575 if not dev or dev:match("[^%w%-%.%s]") then
576 dev = uci_r:get("network", self.sid, "ifname") or
577 uci_s:get("network", self.sid, "ifname")
579 dev = (type(dev) == "table") and dev[1] or dev
582 for dev in utl.imatch(dev) do
587 function network.proto(self)
588 return self:_get("proto") or "none"
591 function network.type(self)
592 return self:_get("type")
595 function network.name(self)
599 function network.uptime(self)
600 local cnt = tonumber(uci_s:get("network", self.sid, "connect_time"))
602 return nxo.sysinfo().uptime - cnt
608 function network.expires(self)
609 local a = tonumber(uci_s:get("network", self.sid, "lease_acquired"))
610 local l = tonumber(uci_s:get("network", self.sid, "lease_lifetime"))
612 l = l - (nxo.sysinfo().uptime - a)
613 return l > 0 and l or 0
618 function network.metric(self)
619 return tonumber(uci_s:get("network", self.sid, "metric")) or 0
622 function network.ipaddr(self)
623 return self:_ip("ipaddr", 4)
626 function network.netmask(self)
627 return self:_ip("netmask", 4)
630 function network.gwaddr(self)
631 return self:_ip("gateway", 4)
634 function network.dnsaddrs(self)
635 return self:_ip("dns", 4, true)
638 function network.ip6addr(self)
639 local ip6 = self:_ip("ip6addr", 6)
641 local ifc = ifs[self:ifname()]
642 if ifc and ifc.ip6addrs then
644 for _, a in ipairs(ifc.ip6addrs) do
645 if not a:is6linklocal() then
655 function network.gw6addr(self)
656 local ip6 = self:_ip("ip6gw", 6)
658 local dr6 = sys.net.defaultroute6()
659 if dr6 and dr6.device == self:ifname() then
660 return dr6.nexthop:string()
666 function network.dns6addrs(self)
667 return self:_ip("dns", 6, true)
670 function network.is_bridge(self)
671 return (self:type() == "bridge")
674 function network.is_virtual(self)
675 local p = self:proto()
677 p == "3g" or p == "6in4" or p == "6to4" or p == "ppp" or
678 p == "pppoe" or p == "pppoa" or p == "relay"
682 function network.is_floating(self)
683 return (self:is_virtual() and self:proto() ~= "pppoe")
686 function network.is_empty(self)
687 if self:is_virtual() then
692 if (self:_get("ifname") or ""):match("%S+") then
696 uci_r:foreach("wireless", "wifi-iface",
698 if s.network == self.sid then
708 function network.add_interface(self, ifname)
709 if not self:is_floating() then
710 if type(ifname) ~= "string" then
711 ifname = ifname:name()
713 ifname = ifname:match("[^%s:]+")
716 -- remove the interface from all ifaces
717 uci_r:foreach("network", "interface",
719 _list_del("network", s['.name'], "ifname", ifname)
722 -- if its a wifi interface, change its network option
723 local wif = _wifi_lookup(ifname)
725 uci_r:set("wireless", wif, "network", self.sid)
727 -- add iface to our iface list
729 _list_add("network", self.sid, "ifname", ifname)
734 function network.del_interface(self, ifname)
735 if not self:is_floating() then
736 if utl.instanceof(ifname, interface) then
737 ifname = ifname:name()
739 ifname = ifname:match("[^%s:]+")
742 -- if its a wireless interface, clear its network option
743 local wif = _wifi_lookup(ifname)
744 if wif then uci_r:delete("wireless", wif, "network") end
746 -- remove the interface
747 _list_del("network", self.sid, "ifname", ifname)
751 function network.get_interface(self)
752 if self:is_virtual() then
753 tns[self:proto() .. "-" .. self.sid] = true
754 return interface(self:proto() .. "-" .. self.sid, self)
755 elseif self:is_bridge() then
756 brs["br-" .. self.sid] = true
757 return interface("br-" .. self.sid, self)
761 for ifn in utl.imatch(uci_s:get("network", self.sid, "ifname")) do
762 ifn = ifn:match("^[^:/]+")
763 return ifn and interface(ifn, self)
766 uci_s:foreach("wireless", "wifi-iface",
769 num[s.device] = num[s.device] and num[s.device] + 1 or 1
770 if s.network == self.sid then
771 ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] }
776 return ifn and interface(ifn, self)
780 function network.get_interfaces(self)
785 for ifn in utl.imatch(self:get("ifname")) do
786 ifn = ifn:match("^[^:/]+")
787 nfs[ifn] = interface(ifn, self)
790 for ifn in utl.kspairs(nfs) do
791 ifaces[#ifaces+1] = nfs[ifn]
796 uci_r:foreach("wireless", "wifi-iface",
799 num[s.device] = num[s.device] and num[s.device] + 1 or 1
800 if s.network == self.sid then
801 ifn = "%s.network%d" %{ s.device, num[s.device] }
802 wfs[ifn] = interface(ifn, self)
807 for ifn in utl.kspairs(wfs) do
808 ifaces[#ifaces+1] = wfs[ifn]
810 -- only bridges may cover more than one interface
811 --if not self:is_bridge() then
819 function network.contains_interface(self, ifname)
820 if type(ifname) ~= "string" then
821 ifname = ifname:name()
823 ifname = ifname:match("[^%s:]+")
826 if self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
828 elseif self:is_bridge() and "br-" .. self.sid == ifname then
832 for ifn in utl.imatch(self:get("ifname")) do
833 ifn = ifn:match("[^:]+")
834 if ifn == ifname then
839 local wif = _wifi_lookup(ifname)
841 return (uci_r:get("wireless", wif, "network") == self.sid)
848 function network.adminlink(self)
849 return dsp.build_url("admin", "network", "network", self.sid)
853 interface = utl.class()
854 function interface.__init__(self, ifname, network)
855 local wif = _wifi_lookup(ifname)
856 if wif then self.wif = wifinet(wif) end
858 self.ifname = self.ifname or ifname
859 self.dev = ifs[self.ifname]
860 self.network = network
863 function interface.name(self)
864 return self.wif and self.wif:ifname() or self.ifname
867 function interface.mac(self)
868 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
871 function interface.ipaddrs(self)
872 return self.dev and self.dev.ipaddrs or { }
875 function interface.ip6addrs(self)
876 return self.dev and self.dev.ip6addrs or { }
879 function interface.type(self)
880 if self.wif or _wifi_iface(self.ifname) then
882 elseif brs[self.ifname] then
884 elseif tns[self.ifname] then
886 elseif self.ifname:match("%.") then
888 elseif sws[self.ifname] then
895 function interface.shortname(self)
898 self.wif:active_mode(),
899 self.wif:active_ssid() or self.wif:active_bssid()
906 function interface.get_i18n(self)
908 return "%s: %s %q" %{
909 i18n.translate("Wireless Network"),
910 self.wif:active_mode(),
911 self.wif:active_ssid() or self.wif:active_bssid()
914 return "%s: %q" %{ self:get_type_i18n(), self:name() }
918 function interface.get_type_i18n(self)
919 local x = self:type()
921 return i18n.translate("Wireless Adapter")
922 elseif x == "bridge" then
923 return i18n.translate("Bridge")
924 elseif x == "switch" then
925 return i18n.translate("Ethernet Switch")
926 elseif x == "vlan" then
927 return i18n.translate("VLAN Interface")
928 elseif x == "tunnel" then
929 return i18n.translate("Tunnel Interface")
931 return i18n.translate("Ethernet Adapter")
935 function interface.adminlink(self)
937 return self.wif:adminlink()
941 function interface.ports(self)
945 for _, iface in ipairs(self.br.ifnames) do
946 ifaces[#ifaces+1] = interface(iface.name)
952 function interface.bridge_id(self)
960 function interface.bridge_stp(self)
968 function interface.is_up(self)
970 return self.wif:is_up()
972 return self.dev and self.dev.flags and self.dev.flags.up or false
976 function interface.is_bridge(self)
977 return (self:type() == "bridge")
980 function interface.is_bridgeport(self)
981 return self.dev and self.dev.bridge and true or false
984 function interface.tx_bytes(self)
985 return self.dev and self.dev.stats
986 and self.dev.stats.tx_bytes or 0
989 function interface.rx_bytes(self)
990 return self.dev and self.dev.stats
991 and self.dev.stats.rx_bytes or 0
994 function interface.tx_packets(self)
995 return self.dev and self.dev.stats
996 and self.dev.stats.tx_packets or 0
999 function interface.rx_packets(self)
1000 return self.dev and self.dev.stats
1001 and self.dev.stats.rx_packets or 0
1004 function interface.get_network(self)
1005 if not self.network then
1006 if self.dev and self.dev.network then
1007 self.network = _M:get_network(self.dev.network)
1011 if not self.network then
1013 for _, net in ipairs(_M:get_networks()) do
1014 if net:contains_interface(self.ifname) or
1015 net:ifname() == self.ifname
1026 function interface.get_wifinet(self)
1031 wifidev = utl.class()
1032 function wifidev.__init__(self, dev)
1034 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1037 function wifidev.get(self, opt)
1038 return _get("wireless", self.sid, opt)
1041 function wifidev.set(self, opt, val)
1042 return _set("wireless", self.sid, opt, val)
1045 function wifidev.name(self)
1049 function wifidev.hwmodes(self)
1050 local l = self.iwinfo.hwmodelist
1051 if l and next(l) then
1054 return { b = true, g = true }
1058 function wifidev.get_i18n(self)
1060 if self.iwinfo.type == "wl" then
1062 elseif self.iwinfo.type == "madwifi" then
1067 local l = self:hwmodes()
1068 if l.a then m = m .. "a" end
1069 if l.b then m = m .. "b" end
1070 if l.g then m = m .. "g" end
1071 if l.n then m = m .. "n" end
1073 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1076 function wifidev.is_up(self)
1079 uci_s:foreach("wireless", "wifi-iface",
1081 if s.device == self.sid then
1092 function wifidev.get_wifinet(self, net)
1093 if uci_r:get("wireless", net) == "wifi-iface" then
1096 local wnet = _wifi_lookup(net)
1098 return wifinet(wnet)
1103 function wifidev.get_wifinets(self)
1106 uci_r:foreach("wireless", "wifi-iface",
1108 if s.device == self.sid then
1109 nets[#nets+1] = wifinet(s['.name'])
1116 function wifidev.add_wifinet(self, options)
1117 options = options or { }
1118 options.device = self.sid
1120 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
1122 return wifinet(wnet, options)
1126 function wifidev.del_wifinet(self, net)
1127 if utl.instanceof(net, wifinet) then
1129 elseif uci_r:get("wireless", net) ~= "wifi-iface" then
1130 net = _wifi_lookup(net)
1133 if net and uci_r:get("wireless", net, "device") == self.sid then
1134 uci_r:delete("wireless", net)
1142 wifinet = utl.class()
1143 function wifinet.__init__(self, net, data)
1148 uci_r:foreach("wireless", "wifi-iface",
1151 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1152 if s['.name'] == self.sid then
1153 netid = "%s.network%d" %{ s.device, num[s.device] }
1159 local dev = uci_s:get("wireless", self.sid, "ifname") or netid
1163 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1164 self.iwdata = data or uci_s:get_all("wireless", self.sid) or
1165 uci_r:get_all("wireless", self.sid) or { }
1168 function wifinet.get(self, opt)
1169 return _get("wireless", self.sid, opt)
1172 function wifinet.set(self, opt, val)
1173 return _set("wireless", self.sid, opt, val)
1176 function wifinet.mode(self)
1177 return uci_s:get("wireless", self.sid, "mode") or "ap"
1180 function wifinet.ssid(self)
1181 return uci_s:get("wireless", self.sid, "ssid")
1184 function wifinet.bssid(self)
1185 return uci_s:get("wireless", self.sid, "bssid")
1188 function wifinet.network(self)
1189 return uci_s:get("wifinet", self.sid, "network")
1192 function wifinet.id(self)
1196 function wifinet.name(self)
1200 function wifinet.ifname(self)
1201 local ifname = self.iwinfo.ifname
1202 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1208 function wifinet.get_device(self)
1209 if self.iwdata.device then
1210 return wifidev(self.iwdata.device)
1214 function wifinet.is_up(self)
1215 return (self.iwdata.up == "1")
1218 function wifinet.active_mode(self)
1219 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1221 if m == "ap" then m = "Master"
1222 elseif m == "sta" then m = "Client"
1223 elseif m == "adhoc" then m = "Ad-Hoc"
1224 elseif m == "mesh" then m = "Mesh"
1225 elseif m == "monitor" then m = "Monitor"
1231 function wifinet.active_mode_i18n(self)
1232 return i18n.translate(self:active_mode())
1235 function wifinet.active_ssid(self)
1236 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1239 function wifinet.active_bssid(self)
1240 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1243 function wifinet.active_encryption(self)
1244 local enc = self.iwinfo and self.iwinfo.encryption
1245 return enc and enc.description or "-"
1248 function wifinet.assoclist(self)
1249 return self.iwinfo.assoclist or { }
1252 function wifinet.frequency(self)
1253 local freq = self.iwinfo.frequency
1254 if freq and freq > 0 then
1255 return "%.03f" % (freq / 1000)
1259 function wifinet.bitrate(self)
1260 local rate = self.iwinfo.bitrate
1261 if rate and rate > 0 then
1262 return (rate / 1000)
1266 function wifinet.channel(self)
1267 return self.iwinfo.channel or
1268 tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1271 function wifinet.signal(self)
1272 return self.iwinfo.signal or 0
1275 function wifinet.noise(self)
1276 return self.iwinfo.noise or 0
1279 function wifinet.country(self)
1280 return self.iwinfo.country or "00"
1283 function wifinet.txpower(self)
1284 return self.iwinfo.txpower or 0
1287 function wifinet.signal_level(self, s, n)
1288 if self:active_bssid() ~= "00:00:00:00:00:00" then
1289 local signal = s or self:signal()
1290 local noise = n or self:noise()
1292 if signal < 0 and noise < 0 then
1293 local snr = -1 * (noise - signal)
1294 return math.floor(snr / 5)
1303 function wifinet.signal_percent(self)
1304 local qc = self.iwinfo.quality or 0
1305 local qm = self.iwinfo.quality_max or 0
1307 if qc > 0 and qm > 0 then
1308 return math.floor((100 / qm) * qc)
1314 function wifinet.shortname(self)
1316 i18n.translate(self:active_mode()),
1317 self:active_ssid() or self:active_bssid()
1321 function wifinet.get_i18n(self)
1322 return "%s: %s %q (%s)" %{
1323 i18n.translate("Wireless Network"),
1324 i18n.translate(self:active_mode()),
1325 self:active_ssid() or self:active_bssid(),
1330 function wifinet.adminlink(self)
1331 return dsp.build_url("admin", "network", "wireless", self.netid)
1334 function wifinet.get_network(self)
1335 if uci_r:get("network", self.iwdata.network) == "interface" then
1336 return network(self.iwdata.network)
1340 function wifinet.get_interface(self)
1341 return interface(self:ifname())