X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libs%2Fcore%2Fluasrc%2Fmodel%2Fnetwork.lua;h=39145748f79352db51a87240ec2c157c4bc46141;hb=5bcf9d07fdb29b03f191f63a98f76e44e348868f;hp=0267bb437cd93d6fa5b139959b8f9cbef073f775;hpb=c7a95b6683078c1800087446a1c1ca660bb1dec0;p=oweals%2Fluci.git diff --git a/libs/core/luasrc/model/network.lua b/libs/core/luasrc/model/network.lua index 0267bb437..39145748f 100644 --- a/libs/core/luasrc/model/network.lua +++ b/libs/core/luasrc/model/network.lua @@ -17,12 +17,15 @@ limitations under the License. ]]-- -local type, next, pairs, ipairs, loadfile, table, tonumber, math, i18n - = type, next, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n +local type, next, pairs, ipairs, loadfile, table + = type, next, pairs, ipairs, loadfile, table + +local tonumber, tostring, math, i18n + = tonumber, tostring, math, luci.i18n -local error = error local require = require +local bus = require "ubus" local nxo = require "nixio" local nfs = require "nixio.fs" local ipc = require "luci.ip" @@ -44,6 +47,7 @@ protocol = utl.class() local _protocols = { } local _interfaces, _bridge, _switch, _tunnel +local _ubus, _ubusnetcache, _ubusdevcache local _uci_real, _uci_state function _filter(c, s, o, r) @@ -197,6 +201,10 @@ function init(cursor) _switch = { } _tunnel = { } + _ubus = bus.connect() + _ubusnetcache = { } + _ubusdevcache = { } + -- read interface information local n, i for n, i in ipairs(nxo.getifaddrs()) do @@ -598,22 +606,15 @@ function protocol._get(self, opt) return v or "" end -function protocol._ip(self, opt, family, list) - local ip = _uci_state:get("network", self.sid, opt) - local fc = (family == 6) and ipc.IPv6 or ipc.IPv4 - if ip or list then - if list then - local l = { } - for ip in utl.imatch(ip) do - ip = fc(ip) - if ip then l[#l+1] = ip:string() end - end - return l - else - ip = fc(ip) - return ip and ip:string() - end +function protocol._ubus(self, field) + if not _ubusnetcache[self.sid] then + _ubusnetcache[self.sid] = _ubus:call("network.interface.%s" % self.sid, + "status", { }) + end + if _ubusnetcache[self.sid] and field then + return _ubusnetcache[self.sid][field] end + return _ubusnetcache[self.sid] end function protocol.get(self, opt) @@ -625,36 +626,28 @@ function protocol.set(self, opt, val) end function protocol.ifname(self) - local p = self:proto() - if self:is_bridge() then - return "br-" .. self.sid - elseif self:is_virtual() then - return p .. "-" .. self.sid + local ifname + if self:is_floating() then + ifname = self:_ubus("l3_device") else + ifname = self:_ubus("device") + end + if not ifname then local num = { } - local dev = _uci_real:get("network", self.sid, "ifname") or - _uci_state:get("network", self.sid, "ifname") - - dev = (type(dev) == "table") and dev[1] or dev - dev = (dev ~= nil) and dev:match("%S+") - - if not dev then - _uci_real:foreach("wireless", "wifi-iface", - function(s) - if s.device then - num[s.device] = num[s.device] - and num[s.device] + 1 or 1 + _uci_real:foreach("wireless", "wifi-iface", + function(s) + if s.device then + num[s.device] = num[s.device] + and num[s.device] + 1 or 1 - if s.network == self.sid then - dev = "%s.network%d" %{ s.device, num[s.device] } - return false - end + if s.network == self.sid then + ifname = "%s.network%d" %{ s.device, num[s.device] } + return false end - end) - end - - return dev + end + end) end + return ifname end function protocol.proto(self) @@ -683,12 +676,7 @@ function protocol.name(self) end function protocol.uptime(self) - local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time")) - if cnt ~= nil then - return nxo.sysinfo().uptime - cnt - else - return 0 - end + return self:_ubus("uptime") or 0 end function protocol.expires(self) @@ -706,51 +694,60 @@ function protocol.metric(self) end function protocol.ipaddr(self) - return self:_ip("ipaddr", 4) + local addrs = self:_ubus("ipv4-address") + return addrs and #addrs > 0 and addrs[1].address end function protocol.netmask(self) - return self:_ip("netmask", 4) + local addrs = self:_ubus("ipv4-address") + return addrs and #addrs > 0 and + ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string() end function protocol.gwaddr(self) - return self:_ip("gateway", 4) + local _, route + for _, route in ipairs(self:_ubus("route") or { }) do + if route.target == "0.0.0.0" and route.mask == 0 then + return route.nexthop + end + end end function protocol.dnsaddrs(self) - return self:_ip("dns", 4, true) + local dns = { } + local _, addr + for _, addr in ipairs(self:_ubus("dns-server") or { }) do + if not addr:match(":") then + dns[#dns+1] = addr + end + end + return dns end function protocol.ip6addr(self) - local ip6 = self:_ip("ip6addr", 6) - if not ip6 then - local ifc = _interfaces[self:ifname()] - if ifc and ifc.ip6addrs then - local a - for _, a in ipairs(ifc.ip6addrs) do - if not a:is6linklocal() then - ip6 = a:string() - break - end - end - end - end - return ip6 + local addrs = self:_ubus("ipv6-address") + return addrs and #addrs > 0 + and "%s/%d" %{ addrs[1].address, addrs[1].mask } end function protocol.gw6addr(self) - local ip6 = self:_ip("ip6gw", 6) - if not ip6 then - local dr6 = sys.net.defaultroute6() - if dr6 and dr6.device == self:ifname() then - return dr6.nexthop:string() + local _, route + for _, route in ipairs(self:_ubus("route") or { }) do + if route.target == "::" and route.mask == 0 then + return ipc.IPv6(route.nexthop):string() end end - return ip6 end function protocol.dns6addrs(self) - return self:_ip("dns", 6, true) + local dns = { } + local _, addr + for _, addr in ipairs(self:_ubus("dns-server") or { }) do + if addr:match(":") then + dns[#dns+1] = addr + end + end + return dns end function protocol.is_bridge(self) @@ -774,7 +771,7 @@ function protocol.is_floating(self) end function protocol.is_empty(self) - if self:is_virtual() then + if self:is_floating() then return false else local rv = true @@ -838,17 +835,17 @@ function protocol.get_interface(self) else local ifn = nil local num = { } - for ifn in utl.imatch(_uci_state:get("network", self.sid, "ifname")) do + for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do ifn = ifn:match("^[^:/]+") return ifn and interface(ifn, self) end ifn = nil - _uci_state:foreach("wireless", "wifi-iface", + _uci_real:foreach("wireless", "wifi-iface", function(s) if s.device then num[s.device] = num[s.device] and num[s.device] + 1 or 1 if s.network == self.sid then - ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] } + ifn = "%s.network%d" %{ s.device, num[s.device] } return false end end @@ -928,19 +925,33 @@ interface = utl.class() function interface.__init__(self, ifname, network) local wif = _wifi_lookup(ifname) - if wif then self.wif = wifinet(wif) end + if wif then + self.wif = wifinet(wif) + self.ifname = _uci_state:get("wireless", wif, "ifname") + end self.ifname = self.ifname or ifname self.dev = _interfaces[self.ifname] self.network = network end +function interface._ubus(self, field) + if not _ubusdevcache[self.ifname] then + _ubusdevcache[self.ifname] = _ubus:call("network.device", "status", + { name = self.ifname }) + end + if _ubusdevcache[self.ifname] and field then + return _ubusdevcache[self.ifname][field] + end + return _ubusdevcache[self.ifname] +end + function interface.name(self) return self.wif and self.wif:ifname() or self.ifname end function interface.mac(self) - return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper() + return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper() end function interface.ipaddrs(self) @@ -1014,11 +1025,12 @@ function interface.adminlink(self) end function interface.ports(self) - if self.br then - local iface + local members = self:_ubus("bridge-members") + if members then + local _, iface local ifaces = { } - for _, iface in ipairs(self.br.ifnames) do - ifaces[#ifaces+1] = interface(iface.name) + for _, iface in ipairs(members) do + ifaces[#ifaces+1] = interface(iface) end return ifaces end @@ -1044,7 +1056,7 @@ function interface.is_up(self) if self.wif then return self.wif:is_up() else - return self.dev and self.dev.flags and self.dev.flags.up or false + return self:_ubus("up") or false end end @@ -1056,24 +1068,31 @@ function interface.is_bridgeport(self) return self.dev and self.dev.bridge and true or false end +local function uint(x) + if x then + return (x < 0) and ((2^32) + x) or x + end + return 0 +end + function interface.tx_bytes(self) - return self.dev and self.dev.stats - and self.dev.stats.tx_bytes or 0 + local stat = self:_ubus("statistics") + return stat and uint(stat.tx_bytes) or 0 end function interface.rx_bytes(self) - return self.dev and self.dev.stats - and self.dev.stats.rx_bytes or 0 + local stat = self:_ubus("statistics") + return stat and uint(stat.rx_bytes) or 0 end function interface.tx_packets(self) - return self.dev and self.dev.stats - and self.dev.stats.tx_packets or 0 + local stat = self:_ubus("statistics") + return stat and uint(stat.tx_packets) or 0 end function interface.rx_packets(self) - return self.dev and self.dev.stats - and self.dev.stats.rx_packets or 0 + local stat = self:_ubus("statistics") + return stat and uint(stat.rx_packets) or 0 end function interface.get_network(self) @@ -1358,7 +1377,12 @@ function wifinet.country(self) end function wifinet.txpower(self) - return self.iwinfo.txpower or 0 + local pwr = (self.iwinfo.txpower or 0) + return pwr + self:txpower_offset() +end + +function wifinet.txpower_offset(self) + return self.iwinfo.txpower_offset or 0 end function wifinet.signal_level(self, s, n) @@ -1409,8 +1433,9 @@ function wifinet.adminlink(self) end function wifinet.get_network(self) - if _uci_real:get("network", self.iwdata.network) == "interface" then - return network(self.iwdata.network) + local net = tostring(self.iwdata.network) + if net and _uci_real:get("network", net) == "interface" then + return network(net) end end