luci-base: network.js: overhaul code

- Rework internal state management
 - Implement new utility functions such as getL3Device() or getModemType()
 - Fix bugs in various functions

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2019-08-14 18:17:10 +02:00
parent ed8f1c4c1c
commit 0d0882aea0

View file

@ -90,119 +90,98 @@ var callGetProtoHandlers = rpc.declare({
expect: { '': {} } expect: { '': {} }
}); });
var _cache = {}, var _init = null,
_flush = true,
_state = null, _state = null,
_protocols = {}; _protocols = {},
_protospecs = {};
function getWifiState(flush) { function getWifiState(cache) {
if (_cache.wifi == null || flush) return callNetworkWirelessStatus().then(function(state) {
return callNetworkWirelessStatus().then(function(state) { if (!L.isObject(state))
if (!L.isObject(state)) throw !1;
throw !1; return state;
return (_cache.wifi = state); }).catch(function() {
}).catch(function() { return {};
return (_cache.wifi = {}); });
});
return Promise.resolve(_cache.wifi);
} }
function getInterfaceState(flush) { function getInterfaceState(cache) {
if (_cache.interfacedump == null || flush) return callNetworkInterfaceStatus().then(function(state) {
return callNetworkInterfaceStatus().then(function(state) { if (!Array.isArray(state))
if (!Array.isArray(state)) throw !1;
throw !1; return state;
return (_cache.interfacedump = state); }).catch(function() {
}).catch(function() { return [];
return (_cache.interfacedump = []); });
});
return Promise.resolve(_cache.interfacedump);
} }
function getDeviceState(flush) { function getDeviceState(cache) {
if (_cache.devicedump == null || flush) return callNetworkDeviceStatus().then(function(state) {
return callNetworkDeviceStatus().then(function(state) { if (!L.isObject(state))
if (!L.isObject(state)) throw !1;
throw !1; return state;
return (_cache.devicedump = state); }).catch(function() {
}).catch(function() { return {};
return (_cache.devicedump = {}); });
});
return Promise.resolve(_cache.devicedump);
} }
function getIfaddrState(flush) { function getIfaddrState(cache) {
if (_cache.ifaddrs == null || flush) return callLuciIfaddrs().then(function(addrs) {
return callLuciIfaddrs().then(function(addrs) { if (!Array.isArray(addrs))
if (!Array.isArray(addrs)) throw !1;
throw !1; return addrs;
return (_cache.ifaddrs = addrs); }).catch(function() {
}).catch(function() { return [];
return (_cache.ifaddrs = []); });
});
return Promise.resolve(_cache.ifaddrs);
} }
function getNetdevState(flush) { function getNetdevState(cache) {
if (_cache.devices == null || flush) return callLuciNetdevs().then(function(state) {
return callLuciNetdevs().then(function(state) { if (!L.isObject(state))
if (!L.isObject(state)) throw !1;
throw !1; return state;
return (_cache.devices = state); }).catch(function() {
}).catch(function() { return {};
return (_cache.devices = {}); });
});
return Promise.resolve(_cache.devices);
} }
function getBoardState(flush) { function getBoardState(cache) {
if (_cache.board == null || flush) return callLuciBoardjson().then(function(state) {
return callLuciBoardjson().then(function(state) { if (!L.isObject(state))
if (!L.isObject(state)) throw !1;
throw !1; return state;
return (_cache.board = state); }).catch(function() {
}).catch(function() { return {};
return (_cache.board = {}); });
});
return Promise.resolve(_cache.board);
} }
function getProtocolHandlers(flush) { function getProtocolHandlers(cache) {
if (_cache.protocols == null || flush) return callGetProtoHandlers().then(function(protos) {
return callGetProtoHandlers().then(function(protos) { if (!L.isObject(protos))
if (!L.isObject(protos)) throw !1;
throw !1;
_cache.protocols = protos; Object.assign(_protospecs, protos);
return Promise.all(Object.keys(protos).map(function(p) { return Promise.all(Object.keys(protos).map(function(p) {
return Promise.resolve(L.require('protocol.%s'.format(p))).catch(function(err) { return Promise.resolve(L.require('protocol.%s'.format(p))).catch(function(err) {
if (L.isObject(err) && err.name != 'NetworkError') if (L.isObject(err) && err.name != 'NetworkError')
L.error(err); L.error(err);
});
})).then(function() {
return _cache.protocols;
}); });
}).catch(function() { })).then(function() {
return (_cache.protocols = {}); return protos;
}); });
}).catch(function() {
return Promise.resolve(_cache.protocols); return {};
});
} }
function getWifiStateBySid(sid) { function getWifiStateBySid(sid) {
var s = uci.get('wireless', sid); var s = uci.get('wireless', sid);
if (s != null && s['.type'] == 'wifi-iface') { if (s != null && s['.type'] == 'wifi-iface') {
for (var radioname in _cache.wifi) { for (var radioname in _state.radios) {
for (var i = 0; i < _cache.wifi[radioname].interfaces.length; i++) { for (var i = 0; i < _state.radios[radioname].interfaces.length; i++) {
var netstate = _cache.wifi[radioname].interfaces[i]; var netstate = _state.radios[radioname].interfaces[i];
if (typeof(netstate.section) != 'string') if (typeof(netstate.section) != 'string')
continue; continue;
@ -210,7 +189,7 @@ function getWifiStateBySid(sid) {
var s2 = uci.get('wireless', netstate.section); var s2 = uci.get('wireless', netstate.section);
if (s2 != null && s['.type'] == s2['.type'] && s['.name'] == s2['.name']) if (s2 != null && s['.type'] == s2['.type'] && s['.name'] == s2['.name'])
return [ radioname, _cache.wifi[radioname], netstate ]; return [ radioname, _state.radios[radioname], netstate ];
} }
} }
} }
@ -219,15 +198,15 @@ function getWifiStateBySid(sid) {
} }
function getWifiStateByIfname(ifname) { function getWifiStateByIfname(ifname) {
for (var radioname in _cache.wifi) { for (var radioname in _state.radios) {
for (var i = 0; i < _cache.wifi[radioname].interfaces.length; i++) { for (var i = 0; i < _state.radios[radioname].interfaces.length; i++) {
var netstate = _cache.wifi[radioname].interfaces[i]; var netstate = _state.radios[radioname].interfaces[i];
if (typeof(netstate.ifname) != 'string') if (typeof(netstate.ifname) != 'string')
continue; continue;
if (netstate.ifname == ifname) if (netstate.ifname == ifname)
return [ radioname, _cache.wifi[radioname], netstate ]; return [ radioname, _state.radios[radioname], netstate ];
} }
} }
@ -367,7 +346,7 @@ function appendValue(config, section, option, value) {
rv = false; rv = false;
if (isArray == false) if (isArray == false)
values = String(values || '').split(/\s+/); values = L.toArray(values);
if (values.indexOf(value) == -1) { if (values.indexOf(value) == -1) {
values.push(value); values.push(value);
@ -385,7 +364,7 @@ function removeValue(config, section, option, value) {
rv = false; rv = false;
if (isArray == false) if (isArray == false)
values = String(values || '').split(/\s+/); values = L.toArray(values);
for (var i = values.length - 1; i >= 0; i--) { for (var i = values.length - 1; i >= 0; i--) {
if (values[i] == value) { if (values[i] == value) {
@ -444,159 +423,160 @@ function maskToPrefix(mask, v6) {
return bits; return bits;
} }
function initNetworkState() { function initNetworkState(refresh) {
var flush = _flush; if (_state == null || refresh) {
_init = _init || Promise.all([
getInterfaceState(), getDeviceState(), getBoardState(),
getWifiState(), getIfaddrState(), getNetdevState(), getProtocolHandlers(),
uci.load('network'), uci.load('wireless'), uci.load('luci')
]).then(function(data) {
var board = data[2], ifaddrs = data[4], devices = data[5];
var s = {
isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {},
ifaces: data[0], devices: data[1], radios: data[3],
netdevs: {}, bridges: {}, switches: {}
};
_flush = false; for (var i = 0, a; (a = ifaddrs[i]) != null; i++) {
var name = a.name.replace(/:.+$/, '');
if (_state != null && !flush) if (isVirtualIfname(name))
return Promise.resolve(_state); s.isTunnel[name] = true;
if (_cache.pendingInit != null) if (s.isTunnel[name] || !(isIgnoredIfname(name) || isVirtualIfname(name))) {
return Promise.resolve(_cache.pendingInit); s.netdevs[name] = s.netdevs[name] || {
idx: a.ifindex || i,
name: name,
rawname: a.name,
flags: [],
ipaddrs: [],
ip6addrs: []
};
return (_cache.pendingInit = Promise.all([ if (a.family == 'packet') {
getInterfaceState(flush), getDeviceState(flush), getBoardState(flush), s.netdevs[name].flags = a.flags;
getWifiState(flush), getIfaddrState(flush), getNetdevState(flush), getProtocolHandlers(flush), s.netdevs[name].stats = a.data;
uci.load('network'), uci.load('wireless'), uci.load('luci') s.netdevs[name].macaddr = a.addr;
]).finally(function() { }
var ifaddrs = _cache.ifaddrs, else if (a.family == 'inet') {
devices = _cache.devices, s.netdevs[name].ipaddrs.push(a.addr + '/' + a.netmask);
board = _cache.board, }
s = { isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {}, interfaces: {}, bridges: {}, switches: {} }; else if (a.family == 'inet6') {
s.netdevs[name].ip6addrs.push(a.addr + '/' + a.netmask);
for (var i = 0, a; (a = ifaddrs[i]) != null; i++) { }
var name = a.name.replace(/:.+$/, '');
if (isVirtualIfname(name))
s.isTunnel[name] = true;
if (s.isTunnel[name] || !(isIgnoredIfname(name) || isVirtualIfname(name))) {
s.interfaces[name] = s.interfaces[name] || {
idx: a.ifindex || i,
name: name,
rawname: a.name,
flags: [],
ipaddrs: [],
ip6addrs: []
};
if (a.family == 'packet') {
s.interfaces[name].flags = a.flags;
s.interfaces[name].stats = a.data;
s.interfaces[name].macaddr = a.addr;
}
else if (a.family == 'inet') {
s.interfaces[name].ipaddrs.push(a.addr + '/' + a.netmask);
}
else if (a.family == 'inet6') {
s.interfaces[name].ip6addrs.push(a.addr + '/' + a.netmask);
} }
} }
}
for (var devname in devices) { for (var devname in devices) {
var dev = devices[devname]; var dev = devices[devname];
if (dev.bridge) { if (dev.bridge) {
var b = { var b = {
name: devname, name: devname,
id: dev.id, id: dev.id,
stp: dev.stp, stp: dev.stp,
ifnames: [] ifnames: []
}; };
for (var i = 0; dev.ports && i < dev.ports.length; i++) { for (var i = 0; dev.ports && i < dev.ports.length; i++) {
var subdev = s.interfaces[dev.ports[i]]; var subdev = s.netdevs[dev.ports[i]];
if (subdev == null) if (subdev == null)
continue; continue;
b.ifnames.push(subdev); b.ifnames.push(subdev);
subdev.bridge = b; subdev.bridge = b;
}
s.bridges[devname] = b;
s.isBridge[devname] = true;
} }
s.bridges[devname] = b; if (s.netdevs.hasOwnProperty(devname)) {
Object.assign(s.netdevs[devname], {
macaddr: dev.mac,
type: dev.type,
mtu: dev.mtu,
qlen: dev.qlen
});
}
} }
if (s.interfaces.hasOwnProperty(devname)) { if (L.isObject(board.switch)) {
Object.assign(s.interfaces[devname], { for (var switchname in board.switch) {
macaddr: dev.mac, var layout = board.switch[switchname],
type: dev.type, netdevs = {},
mtu: dev.mtu, nports = {},
qlen: dev.qlen ports = [],
}); pnum = null,
} role = null;
}
if (L.isObject(board.switch)) { if (L.isObject(layout) && Array.isArray(layout.ports)) {
for (var switchname in board.switch) { for (var i = 0, port; (port = layout.ports[i]) != null; i++) {
var layout = board.switch[switchname], if (typeof(port) == 'object' && typeof(port.num) == 'number' &&
netdevs = {}, (typeof(port.role) == 'string' || typeof(port.device) == 'string')) {
nports = {}, var spec = {
ports = [], num: port.num,
pnum = null, role: port.role || 'cpu',
role = null; index: (port.index != null) ? port.index : port.num
};
if (L.isObject(layout) && Array.isArray(layout.ports)) { if (port.device != null) {
for (var i = 0, port; (port = layout.ports[i]) != null; i++) { spec.device = port.device;
if (typeof(port) == 'object' && typeof(port.num) == 'number' && spec.tagged = spec.need_tag;
(typeof(port.role) == 'string' || typeof(port.device) == 'string')) { netdevs[port.num] = port.device;
var spec = { }
num: port.num,
role: port.role || 'cpu',
index: (port.index != null) ? port.index : port.num
};
if (port.device != null) { ports.push(spec);
spec.device = port.device;
spec.tagged = spec.need_tag; if (port.role != null)
netdevs[port.num] = port.device; nports[port.role] = (nports[port.role] || 0) + 1;
}
}
ports.sort(function(a, b) {
if (a.role != b.role)
return (a.role < b.role) ? -1 : 1;
return (a.index - b.index);
});
for (var i = 0, port; (port = ports[i]) != null; i++) {
if (port.role != role) {
role = port.role;
pnum = 1;
} }
ports.push(spec); if (role == 'cpu')
port.label = 'CPU (%s)'.format(port.device);
else if (nports[role] > 1)
port.label = '%s %d'.format(role.toUpperCase(), pnum++);
else
port.label = role.toUpperCase();
if (port.role != null) delete port.role;
nports[port.role] = (nports[port.role] || 0) + 1; delete port.index;
}
}
ports.sort(function(a, b) {
if (a.role != b.role)
return (a.role < b.role) ? -1 : 1;
return (a.index - b.index);
});
for (var i = 0, port; (port = ports[i]) != null; i++) {
if (port.role != role) {
role = port.role;
pnum = 1;
} }
if (role == 'cpu') s.switches[switchname] = {
port.label = 'CPU (%s)'.format(port.device); ports: ports,
else if (nports[role] > 1) netdevs: netdevs
port.label = '%s %d'.format(role.toUpperCase(), pnum++); };
else
port.label = role.toUpperCase();
delete port.role;
delete port.index;
} }
s.switches[switchname] = {
ports: ports,
netdevs: netdevs
};
} }
} }
}
delete _cache.pendingInit; if (L.isObject(board.dsl) && L.isObject(board.dsl.modem)) {
s.hasDSLModem = board.dsl.modem;
}
return (_state = s); _init = null;
}));
return (_state = s);
});
}
return (_state != null ? Promise.resolve(_state) : _init);
} }
function ifnameOf(obj) { function ifnameOf(obj) {
@ -637,9 +617,8 @@ Network = L.Class.extend({
maskToPrefix: maskToPrefix, maskToPrefix: maskToPrefix,
flushCache: function() { flushCache: function() {
return Promise.resolve(_state).then(function() { initNetworkState(true);
_flush = true; return _init;
});
}, },
getProtocol: function(protoname, netname) { getProtocol: function(protoname, netname) {
@ -660,7 +639,7 @@ Network = L.Class.extend({
}, },
registerProtocol: function(protoname, methods) { registerProtocol: function(protoname, methods) {
var spec = L.isObject(_cache.protocols) ? _cache.protocols[protoname] : null; var spec = L.isObject(_protospecs) ? _protospecs[protoname] : null;
var proto = Protocol.extend(Object.assign({ var proto = Protocol.extend(Object.assign({
getI18n: function() { getI18n: function() {
return protoname; return protoname;
@ -740,9 +719,9 @@ Network = L.Class.extend({
return this.instantiateNetwork(name); return this.instantiateNetwork(name);
} }
else if (name != null) { else if (name != null) {
for (var i = 0; i < _cache.interfacedump.length; i++) for (var i = 0; i < _state.ifaces.length; i++)
if (_cache.interfacedump[i].interface == name) if (_state.ifaces[i].interface == name)
return this.instantiateNetwork(name, _cache.interfacedump[i].proto); return this.instantiateNetwork(name, _state.ifaces[i].proto);
} }
return null; return null;
@ -757,10 +736,10 @@ Network = L.Class.extend({
for (var i = 0; i < uciInterfaces.length; i++) for (var i = 0; i < uciInterfaces.length; i++)
networks[uciInterfaces[i]['.name']] = this.instantiateNetwork(uciInterfaces[i]['.name']); networks[uciInterfaces[i]['.name']] = this.instantiateNetwork(uciInterfaces[i]['.name']);
for (var i = 0; i < _cache.interfacedump.length; i++) for (var i = 0; i < _state.ifaces.length; i++)
if (networks[_cache.interfacedump[i].interface] == null) if (networks[_state.ifaces[i].interface] == null)
networks[_cache.interfacedump[i].interface] = networks[_state.ifaces[i].interface] =
this.instantiateNetwork(_cache.interfacedump[i].interface, _cache.interfacedump[i].proto); this.instantiateNetwork(_state.ifaces[i].interface, _state.ifaces[i].proto);
var rv = []; var rv = [];
@ -874,7 +853,7 @@ Network = L.Class.extend({
if (name == null) if (name == null)
return null; return null;
if (_state.interfaces.hasOwnProperty(name) || isWifiIfname(name)) if (_state.netdevs.hasOwnProperty(name) || isWifiIfname(name))
return this.instantiateDevice(name); return this.instantiateDevice(name);
var netid = getWifiNetidBySid(name); var netid = getWifiNetidBySid(name);
@ -905,7 +884,7 @@ Network = L.Class.extend({
} }
} }
for (var ifname in _state.interfaces) { for (var ifname in _state.netdevs) {
if (devices.hasOwnProperty(ifname)) if (devices.hasOwnProperty(ifname))
continue; continue;
@ -1096,7 +1075,7 @@ Network = L.Class.extend({
var radioname = existingDevice['.name'], var radioname = existingDevice['.name'],
netid = getWifiNetidBySid(sid) || []; netid = getWifiNetidBySid(sid) || [];
return this.instantiateWifiNetwork(sid, radioname, _cache.wifi[radioname], netid[0], null, { ifname: netid }); return this.instantiateWifiNetwork(sid, radioname, _state.radios[radioname], netid[0], null, { ifname: netid });
}, this)); }, this));
}, },
@ -1116,20 +1095,24 @@ Network = L.Class.extend({
return initNetworkState().then(L.bind(function() { return initNetworkState().then(L.bind(function() {
var rv = []; var rv = [];
for (var i = 0; i < _state.interfacedump.length; i++) { for (var i = 0; i < _state.ifaces.length; i++) {
if (!Array.isArray(_state.interfacedump[i].route)) if (!Array.isArray(_state.ifaces[i].route))
continue; continue;
for (var j = 0; j < _state.interfacedump[i].route.length; j++) { for (var j = 0; j < _state.ifaces[i].route.length; j++) {
if (typeof(_state.interfacedump[i].route[j]) != 'object' || if (typeof(_state.ifaces[i].route[j]) != 'object' ||
typeof(_state.interfacedump[i].route[j].target) != 'string' || typeof(_state.ifaces[i].route[j].target) != 'string' ||
typeof(_state.interfacedump[i].route[j].mask) != 'number') typeof(_state.ifaces[i].route[j].mask) != 'number')
continue; continue;
if (_state.interfacedump[i].route[j].table) if (_state.ifaces[i].route[j].table)
continue; continue;
rv.push(_state.interfacedump[i]); if (_state.ifaces[i].route[j].target != addr ||
_state.ifaces[i].route[j].mask != mask)
continue;
rv.push(_state.ifaces[i]);
} }
} }
@ -1141,25 +1124,25 @@ Network = L.Class.extend({
return initNetworkState().then(L.bind(function() { return initNetworkState().then(L.bind(function() {
var rv = []; var rv = [];
for (var i = 0; i < _state.interfacedump.length; i++) { for (var i = 0; i < _state.ifaces.length; i++) {
if (Array.isArray(_state.interfacedump[i]['ipv4-address'])) if (Array.isArray(_state.ifaces[i]['ipv4-address']))
for (var j = 0; j < _state.interfacedump[i]['ipv4-address'].length; j++) for (var j = 0; j < _state.ifaces[i]['ipv4-address'].length; j++)
if (typeof(_state.interfacedump[i]['ipv4-address'][j]) == 'object' && if (typeof(_state.ifaces[i]['ipv4-address'][j]) == 'object' &&
_state.interfacedump[i]['ipv4-address'][j].address == addr) _state.ifaces[i]['ipv4-address'][j].address == addr)
return _state.interfacedump[i]; return _state.ifaces[i];
if (Array.isArray(_state.interfacedump[i]['ipv6-address'])) if (Array.isArray(_state.ifaces[i]['ipv6-address']))
for (var j = 0; j < _state.interfacedump[i]['ipv6-address'].length; j++) for (var j = 0; j < _state.ifaces[i]['ipv6-address'].length; j++)
if (typeof(_state.interfacedump[i]['ipv6-address'][j]) == 'object' && if (typeof(_state.ifaces[i]['ipv6-address'][j]) == 'object' &&
_state.interfacedump[i]['ipv6-address'][j].address == addr) _state.ifaces[i]['ipv6-address'][j].address == addr)
return _state.interfacedump[i]; return _state.ifaces[i];
if (Array.isArray(_state.interfacedump[i]['ipv6-prefix-assignment'])) if (Array.isArray(_state.ifaces[i]['ipv6-prefix-assignment']))
for (var j = 0; j < _state.interfacedump[i]['ipv6-prefix-assignment'].length; j++) for (var j = 0; j < _state.ifaces[i]['ipv6-prefix-assignment'].length; j++)
if (typeof(_state.interfacedump[i]['ipv6-prefix-assignment'][j]) == 'object' && if (typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]) == 'object' &&
typeof(_state.interfacedump[i]['ipv6-prefix-assignment'][j]['local-address']) == 'object' && typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address']) == 'object' &&
_state.interfacedump[i]['ipv6-prefix-assignment'][j]['local-address'].address == addr) _state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address'].address == addr)
return _state.interfacedump[i]; return _state.ifaces[i];
} }
return null; return null;
@ -1218,6 +1201,12 @@ Network = L.Class.extend({
getIfnameOf: function(obj) { getIfnameOf: function(obj) {
return ifnameOf(obj); return ifnameOf(obj);
},
getDSLModemType: function() {
return initNetworkState().then(function() {
return _state.hasDSLModem ? _state.hasDSLModem.type : null;
});
} }
}); });
@ -1236,11 +1225,11 @@ Protocol = L.Class.extend({
}, },
_ubus: function(field) { _ubus: function(field) {
for (var i = 0; i < _cache.interfacedump.length; i++) { for (var i = 0; i < _state.ifaces.length; i++) {
if (_cache.interfacedump[i].interface != this.sid) if (_state.ifaces[i].interface != this.sid)
continue; continue;
return (field != null ? _cache.interfacedump[i][field] : _cache.interfacedump[i]); return (field != null ? _state.ifaces[i][field] : _state.ifaces[i]);
} }
}, },
@ -1538,11 +1527,6 @@ Protocol = L.Class.extend({
return new Device(ifname, this); return new Device(ifname, this);
} }
else { else {
var ifname = this._ubus('l3_device') || this._ubus('device');
if (ifname != null)
return L.network.instantiateDevice(ifname, this);
var ifnames = L.toArray(uci.get('network', this.sid, 'ifname')); var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
for (var i = 0; i < ifnames.length; i++) { for (var i = 0; i < ifnames.length; i++) {
@ -1561,6 +1545,11 @@ Protocol = L.Class.extend({
return (ifname != null ? L.network.instantiateDevice(ifname, this) : null); return (ifname != null ? L.network.instantiateDevice(ifname, this) : null);
}, },
getL3Device: function() {
var ifname = this._ubus('l3_device');
return (ifname != null ? L.network.instantiateDevice(ifname, this) : null);
},
getDevices: function() { getDevices: function() {
var rv = []; var rv = [];
@ -1647,12 +1636,12 @@ Device = L.Class.extend({
} }
this.ifname = this.ifname || ifname; this.ifname = this.ifname || ifname;
this.dev = _state.interfaces[this.ifname]; this.dev = _state.netdevs[this.ifname];
this.network = network; this.network = network;
}, },
_ubus: function(field) { _ubus: function(field) {
var dump = _cache.devicedump[this.ifname] || {}; var dump = _state.devices[this.ifname] || {};
return (field != null ? dump[field] : dump); return (field != null ? dump[field] : dump);
}, },
@ -1751,7 +1740,9 @@ Device = L.Class.extend({
return null; return null;
for (var i = 0; i < br.ifnames.length; i++) for (var i = 0; i < br.ifnames.length; i++)
rv.push(L.network.instantiateDevice(br.ifnames[i])); rv.push(L.network.instantiateDevice(br.ifnames[i].name));
rv.sort(deviceSort);
return rv; return rv;
}, },
@ -1882,8 +1873,8 @@ WifiDevice = L.Class.extend({
}, },
isUp: function() { isUp: function() {
if (L.isObject(_cache.wifi[this.sid])) if (L.isObject(_state.radios[this.sid]))
return (_cache.wifi[this.sid].up == true); return (_state.radios[this.sid].up == true);
return false; return false;
}, },