From ec020cee0c44793f8ce1b346675c6a36e63b0154 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 17 May 2021 10:53:57 +0200 Subject: [PATCH] luci-mod-network: drop support for *editing* legacy bridges MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The old way of defining bridge (L2) as part of interface (L3) is deprecated. All such configs should be migrated to define bridge as L3 UCI section type "device". Signed-off-by: Rafał Miłecki --- .../luci-static/resources/tools/network.js | 388 +++++++----------- .../resources/view/network/interfaces.js | 7 +- 2 files changed, 147 insertions(+), 248 deletions(-) diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js index 5ed55e24fc..b4d941c60d 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js @@ -385,107 +385,41 @@ return baseclass.extend({ }, addDeviceOptions: function(s, dev, isNew) { - var isIface = (s.sectiontype == 'interface'), - ifc = isIface ? network.instantiateNetwork(s.section) : null, - gensection = ifc ? 'physical' : 'devgeneral', - advsection = ifc ? 'physical' : 'devadvanced', - simpledep = ifc ? { type: '', ifname_single: /^[^@]/ } : { type: '' }, - disableLegacyBridging = isIface && deviceSectionExists(null, 'br-%s'.format(ifc.getName()), 'bridge'), - o, ss; - - if (isIface) { - if (!s.hasOwnProperty('parse')) - s.parse = sectionParse; - - var type; - - /* If an externally configured br-xxx interface already exists, - * then disable legacy bridge configuration */ - if (disableLegacyBridging) { - type = this.addOption(s, gensection, form.HiddenValue, 'type'); - type.cfgvalue = function() { return '' }; - } - else { - type = this.addOption(s, gensection, form.Flag, 'type', _('Bridge interfaces'), _('Creates a bridge over specified interface(s)')); - } - - type.modalonly = true; - type.disabled = ''; - type.enabled = 'bridge'; - type.write = type.remove = function(section_id, value) { - var protoname = this.section.formvalue(section_id, 'proto'), - protocol = network.getProtocol(protoname), - new_ifnames = this.isActive(section_id) ? L.toArray(this.section.formvalue(section_id, value ? 'ifname_multi' : 'ifname_single')) : []; - - if (!protocol.isVirtual() && !this.isActive(section_id)) - return; - - var old_ifnames = [], - devs = ifc.getDevices() || L.toArray(ifc.getDevice()); - - for (var i = 0; i < devs.length; i++) - old_ifnames.push(devs[i].getName()); + var o, ss; - if (!value) - new_ifnames.length = Math.max(new_ifnames.length, 1); - - old_ifnames.sort(); - new_ifnames.sort(); - - for (var i = 0; i < Math.max(old_ifnames.length, new_ifnames.length); i++) { - if (old_ifnames[i] != new_ifnames[i]) { - // backup_ifnames() - for (var j = 0; j < old_ifnames.length; j++) - ifc.deleteDevice(old_ifnames[j]); - - for (var j = 0; j < new_ifnames.length; j++) - ifc.addDevice(new_ifnames[j]); - - break; - } - } + s.tab('devgeneral', _('General device options')); + s.tab('devadvanced', _('Advanced device options')); + s.tab('brport', _('Bridge port specific options')); + s.tab('bridgevlan', _('Bridge VLAN filtering')); - if (value) - uci.set('network', section_id, 'type', 'bridge'); - else - uci.unset('network', section_id, 'type'); - }; - } - else { - s.tab('devgeneral', _('General device options')); - s.tab('devadvanced', _('Advanced device options')); - s.tab('brport', _('Bridge port specific options')); - s.tab('bridgevlan', _('Bridge VLAN filtering')); - - o = this.addOption(s, gensection, form.ListValue, 'type', _('Device type')); - o.readonly = !isNew; - o.value('', _('Network device')); - o.value('bridge', _('Bridge device')); - o.value('8021q', _('VLAN (802.1q)')); - o.value('8021ad', _('VLAN (802.1ad)')); - o.value('macvlan', _('MAC VLAN')); - o.value('veth', _('Virtual Ethernet')); - - o = this.addOption(s, gensection, widgets.DeviceSelect, 'name_simple', _('Existing device')); - o.readonly = !isNew; - o.rmempty = false; - o.noaliases = true; - o.default = (dev ? dev.getName() : ''); - o.ucioption = 'name'; - o.write = o.remove = setIfActive; - o.filter = function(section_id, value) { - return !deviceSectionExists(section_id, value); - }; - o.validate = function(section_id, value) { - return deviceSectionExists(section_id, value) ? _('A configuration for the device "%s" already exists').format(value) : true; - }; - o.depends('type', ''); - } + o = this.addOption(s, 'devgeneral', form.ListValue, 'type', _('Device type')); + o.readonly = !isNew; + o.value('', _('Network device')); + o.value('bridge', _('Bridge device')); + o.value('8021q', _('VLAN (802.1q)')); + o.value('8021ad', _('VLAN (802.1ad)')); + o.value('macvlan', _('MAC VLAN')); + o.value('veth', _('Virtual Ethernet')); + + o = this.addOption(s, 'devgeneral', widgets.DeviceSelect, 'name_simple', _('Existing device')); + o.readonly = !isNew; + o.rmempty = false; + o.noaliases = true; + o.default = (dev ? dev.getName() : ''); + o.ucioption = 'name'; + o.write = o.remove = setIfActive; + o.filter = function(section_id, value) { + return !deviceSectionExists(section_id, value); + }; + o.validate = function(section_id, value) { + return deviceSectionExists(section_id, value) ? _('A configuration for the device "%s" already exists').format(value) : true; + }; + o.depends('type', ''); - o = this.addOption(s, gensection, widgets.DeviceSelect, 'ifname_single', isIface ? _('Interface') : _('Base device')); + o = this.addOption(s, 'devgeneral', widgets.DeviceSelect, 'ifname_single', _('Base device')); o.readonly = !isNew; o.rmempty = false; - o.noaliases = !isIface; + o.noaliases = true; o.default = (dev ? dev.getName() : '').match(/^.+\.\d+$/) ? dev.getName().replace(/\.\d+$/, '') : ''; o.ucioption = 'ifname'; o.validate = function(section_id, value) { @@ -504,29 +438,12 @@ return baseclass.extend({ return true; }; - if (isIface) { - o.write = o.remove = function() {}; - o.cfgvalue = function(section_id) { - return (ifc.getDevices() || L.toArray(ifc.getDevice())).map(function(dev) { - return dev.getName(); - }); - }; - o.onchange = function(ev, section_id, values) { - for (var i = 0, co; (co = this.section.children[i]) != null; i++) - if (co !== this && co.refresh) - co.refresh(section_id); - - }; - o.depends('type', ''); - } - else { - o.write = o.remove = setIfActive; - o.depends('type', '8021q'); - o.depends('type', '8021ad'); - o.depends('type', 'macvlan'); - } + o.write = o.remove = setIfActive; + o.depends('type', '8021q'); + o.depends('type', '8021ad'); + o.depends('type', 'macvlan'); - o = this.addOption(s, gensection, form.Value, 'vid', _('VLAN ID')); + o = this.addOption(s, 'devgeneral', form.Value, 'vid', _('VLAN ID')); o.readonly = !isNew; o.datatype = 'range(1, 4094)'; o.rmempty = false; @@ -546,74 +463,64 @@ return baseclass.extend({ o.depends('type', '8021q'); o.depends('type', '8021ad'); - o = this.addOption(s, gensection, form.ListValue, 'mode', _('Mode')); + o = this.addOption(s, 'devgeneral', form.ListValue, 'mode', _('Mode')); o.value('vepa', _('VEPA (Virtual Ethernet Port Aggregator)', 'MACVLAN mode')); o.value('private', _('Private (Prevent communication between MAC VLANs)', 'MACVLAN mode')); o.value('bridge', _('Bridge (Support direct communication between MAC VLANs)', 'MACVLAN mode')); o.value('passthru', _('Pass-through (Mirror physical device to single MAC VLAN)', 'MACVLAN mode')); o.depends('type', 'macvlan'); - if (!isIface) { - o = this.addOption(s, gensection, form.Value, 'name_complex', _('Device name')); - o.rmempty = false; - o.datatype = 'maxlength(15)'; - o.readonly = !isNew; - o.ucioption = 'name'; - o.write = o.remove = setIfActive; - o.validate = function(section_id, value) { - return deviceSectionExists(section_id, value) ? _('The device name "%s" is already taken').format(value) : true; - }; - o.depends({ type: '', '!reverse': true }); - } + o = this.addOption(s, 'devgeneral', form.Value, 'name_complex', _('Device name')); + o.rmempty = false; + o.datatype = 'maxlength(15)'; + o.readonly = !isNew; + o.ucioption = 'name'; + o.write = o.remove = setIfActive; + o.validate = function(section_id, value) { + return deviceSectionExists(section_id, value) ? _('The device name "%s" is already taken').format(value) : true; + }; + o.depends({ type: '', '!reverse': true }); - o = this.addOption(s, advsection, form.DynamicList, 'ingress_qos_mapping', _('Ingress QoS mapping'), _('Defines a mapping of VLAN header priority to the Linux internal packet priority on incoming frames')); + o = this.addOption(s, 'devadvanced', form.DynamicList, 'ingress_qos_mapping', _('Ingress QoS mapping'), _('Defines a mapping of VLAN header priority to the Linux internal packet priority on incoming frames')); o.rmempty = true; o.validate = validateQoSMap; o.depends('type', '8021q'); o.depends('type', '8021ad'); - o = this.addOption(s, advsection, form.DynamicList, 'egress_qos_mapping', _('Egress QoS mapping'), _('Defines a mapping of Linux internal packet priority to VLAN header priority but for outgoing frames')); + o = this.addOption(s, 'devadvanced', form.DynamicList, 'egress_qos_mapping', _('Egress QoS mapping'), _('Defines a mapping of Linux internal packet priority to VLAN header priority but for outgoing frames')); o.rmempty = true; o.validate = validateQoSMap; o.depends('type', '8021q'); o.depends('type', '8021ad'); - o = this.addOption(s, gensection, widgets.DeviceSelect, 'ifname_multi', _('Bridge ports')); + o = this.addOption(s, 'devgeneral', widgets.DeviceSelect, 'ifname_multi', _('Bridge ports')); o.size = 10; o.rmempty = true; o.multiple = true; o.noaliases = true; o.nobridges = true; o.ucioption = 'ifname'; - if (isIface) { - o.write = o.remove = function() {}; - o.cfgvalue = function(section_id) { - return (ifc.getDevices() || L.toArray(ifc.getDevice())).map(function(dev) { return dev.getName() }); - }; - } - else { - o.write = o.remove = setIfActive; - o.default = L.toArray(dev ? dev.getPorts() : null).filter(function(p) { return p.getType() != 'wifi' }).map(function(p) { return p.getName() }); - o.filter = function(section_id, device_name) { - var bridge_name = uci.get('network', section_id, 'name'), - choice_dev = network.instantiateDevice(device_name), - parent_dev = choice_dev.getParent(); - - /* only show wifi networks which are already present in "option ifname" */ - if (choice_dev.getType() == 'wifi') { - var ifnames = L.toArray(uci.get('network', section_id, 'ifname')); - - for (var i = 0; i < ifnames.length; i++) - if (ifnames[i] == device_name) - return true; - - return false; - } + o.write = o.remove = setIfActive; + o.default = L.toArray(dev ? dev.getPorts() : null).filter(function(p) { return p.getType() != 'wifi' }).map(function(p) { return p.getName() }); + o.filter = function(section_id, device_name) { + var bridge_name = uci.get('network', section_id, 'name'), + choice_dev = network.instantiateDevice(device_name), + parent_dev = choice_dev.getParent(); + + /* only show wifi networks which are already present in "option ifname" */ + if (choice_dev.getType() == 'wifi') { + var ifnames = L.toArray(uci.get('network', section_id, 'ifname')); + + for (var i = 0; i < ifnames.length; i++) + if (ifnames[i] == device_name) + return true; + + return false; + } - return (!parent_dev || parent_dev.getName() != bridge_name); - }; - o.description = _('Specifies the wired ports to attach to this bridge. In order to attach wireless networks, choose the associated interface as network in the wireless settings.') - } + return (!parent_dev || parent_dev.getName() != bridge_name); + }; + o.description = _('Specifies the wired ports to attach to this bridge. In order to attach wireless networks, choose the associated interface as network in the wireless settings.') o.onchange = function(ev, section_id, values) { ss.updatePorts(values); @@ -623,64 +530,64 @@ return baseclass.extend({ }; o.depends('type', 'bridge'); - o = this.replaceOption(s, gensection, form.Flag, 'bridge_empty', _('Bring up empty bridge'), _('Bring up the bridge interface even if no ports are attached')); + o = this.replaceOption(s, 'devgeneral', form.Flag, 'bridge_empty', _('Bring up empty bridge'), _('Bring up the bridge interface even if no ports are attached')); o.default = o.disabled; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Value, 'priority', _('Priority')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'priority', _('Priority')); o.placeholder = '32767'; o.datatype = 'range(0, 65535)'; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Value, 'ageing_time', _('Ageing time'), _('Timeout in seconds for learned MAC addresses in the forwarding database')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'ageing_time', _('Ageing time'), _('Timeout in seconds for learned MAC addresses in the forwarding database')); o.placeholder = '30'; o.datatype = 'uinteger'; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Flag, 'stp', _('Enable STP'), _('Enables the Spanning Tree Protocol on this bridge')); + o = this.replaceOption(s, 'devadvanced', form.Flag, 'stp', _('Enable STP'), _('Enables the Spanning Tree Protocol on this bridge')); o.default = o.disabled; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Value, 'hello_time', _('Hello interval'), _('Interval in seconds for STP hello packets')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'hello_time', _('Hello interval'), _('Interval in seconds for STP hello packets')); o.placeholder = '2'; o.datatype = 'range(1, 10)'; o.depends({ type: 'bridge', stp: '1' }); - o = this.replaceOption(s, advsection, form.Value, 'forward_delay', _('Forward delay'), _('Time in seconds to spend in listening and learning states')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'forward_delay', _('Forward delay'), _('Time in seconds to spend in listening and learning states')); o.placeholder = '15'; o.datatype = 'range(2, 30)'; o.depends({ type: 'bridge', stp: '1' }); - o = this.replaceOption(s, advsection, form.Value, 'max_age', _('Maximum age'), _('Timeout in seconds until topology updates on link loss')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'max_age', _('Maximum age'), _('Timeout in seconds until topology updates on link loss')); o.placeholder = '20'; o.datatype = 'range(6, 40)'; o.depends({ type: 'bridge', stp: '1' }); - o = this.replaceOption(s, advsection, form.Flag, 'igmp_snooping', _('Enable IGMP snooping'), _('Enables IGMP snooping on this bridge')); + o = this.replaceOption(s, 'devadvanced', form.Flag, 'igmp_snooping', _('Enable IGMP snooping'), _('Enables IGMP snooping on this bridge')); o.default = o.disabled; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Value, 'hash_max', _('Maximum snooping table size')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'hash_max', _('Maximum snooping table size')); o.placeholder = '512'; o.datatype = 'uinteger'; o.depends({ type: 'bridge', igmp_snooping: '1' }); - o = this.replaceOption(s, advsection, form.Flag, 'multicast_querier', _('Enable multicast querier')); + o = this.replaceOption(s, 'devadvanced', form.Flag, 'multicast_querier', _('Enable multicast querier')); o.defaults = { '1': [{'igmp_snooping': '1'}], '0': [{'igmp_snooping': '0'}] }; o.depends('type', 'bridge'); - o = this.replaceOption(s, advsection, form.Value, 'robustness', _('Robustness'), _('The robustness value allows tuning for the expected packet loss on the network. If a network is expected to be lossy, the robustness value may be increased. IGMP is robust to (Robustness-1) packet losses')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'robustness', _('Robustness'), _('The robustness value allows tuning for the expected packet loss on the network. If a network is expected to be lossy, the robustness value may be increased. IGMP is robust to (Robustness-1) packet losses')); o.placeholder = '2'; o.datatype = 'min(1)'; o.depends({ type: 'bridge', multicast_querier: '1' }); - o = this.replaceOption(s, advsection, form.Value, 'query_interval', _('Query interval'), _('Interval in centiseconds between multicast general queries. By varying the value, an administrator may tune the number of IGMP messages on the subnet; larger values cause IGMP Queries to be sent less often')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'query_interval', _('Query interval'), _('Interval in centiseconds between multicast general queries. By varying the value, an administrator may tune the number of IGMP messages on the subnet; larger values cause IGMP Queries to be sent less often')); o.placeholder = '12500'; o.datatype = 'uinteger'; o.depends({ type: 'bridge', multicast_querier: '1' }); - o = this.replaceOption(s, advsection, form.Value, 'query_response_interval', _('Query response interval'), _('The max response time in centiseconds inserted into the periodic general queries. By varying the value, an administrator may tune the burstiness of IGMP messages on the subnet; larger values make the traffic less bursty, as host responses are spread out over a larger interval')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'query_response_interval', _('Query response interval'), _('The max response time in centiseconds inserted into the periodic general queries. By varying the value, an administrator may tune the burstiness of IGMP messages on the subnet; larger values make the traffic less bursty, as host responses are spread out over a larger interval')); o.placeholder = '1000'; o.datatype = 'uinteger'; o.validate = function(section_id, value) { @@ -694,24 +601,24 @@ return baseclass.extend({ }; o.depends({ type: 'bridge', multicast_querier: '1' }); - o = this.replaceOption(s, advsection, form.Value, 'last_member_interval', _('Last member interval'), _('The max response time in centiseconds inserted into group-specific queries sent in response to leave group messages. It is also the amount of time between group-specific query messages. This value may be tuned to modify the "leave latency" of the network. A reduced value results in reduced time to detect the loss of the last member of a group')); + o = this.replaceOption(s, 'devadvanced', form.Value, 'last_member_interval', _('Last member interval'), _('The max response time in centiseconds inserted into group-specific queries sent in response to leave group messages. It is also the amount of time between group-specific query messages. This value may be tuned to modify the "leave latency" of the network. A reduced value results in reduced time to detect the loss of the last member of a group')); o.placeholder = '100'; o.datatype = 'uinteger'; o.depends({ type: 'bridge', multicast_querier: '1' }); - o = this.addOption(s, gensection, form.Value, 'mtu', _('MTU')); - o.placeholder = getDeviceValue(ifc || dev, 'getMTU'); + o = this.addOption(s, 'devgeneral', form.Value, 'mtu', _('MTU')); + o.placeholder = getDeviceValue(dev, 'getMTU'); o.datatype = 'max(9200)'; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, gensection, form.Value, 'macaddr', _('MAC address')); - o.placeholder = getDeviceValue(ifc || dev, 'getMAC'); + o = this.addOption(s, 'devgeneral', form.Value, 'macaddr', _('MAC address')); + o.placeholder = getDeviceValue(dev, 'getMAC'); o.datatype = 'macaddr'; - o.depends(simpledep); + o.depends('type', ''); o.depends('type', 'macvlan'); o.depends('type', 'veth'); - o = this.addOption(s, gensection, form.Value, 'peer_name', _('Peer device name')); + o = this.addOption(s, 'devgeneral', form.Value, 'peer_name', _('Peer device name')); o.rmempty = true; o.datatype = 'maxlength(15)'; o.depends('type', 'veth'); @@ -730,21 +637,21 @@ return baseclass.extend({ return form.Value.prototype.load.apply(this, arguments); }; - o = this.addOption(s, gensection, form.Value, 'peer_macaddr', _('Peer MAC address')); + o = this.addOption(s, 'devgeneral', form.Value, 'peer_macaddr', _('Peer MAC address')); o.rmempty = true; o.datatype = 'macaddr'; o.depends('type', 'veth'); - o = this.addOption(s, gensection, form.Value, 'txqueuelen', _('TX queue length')); + o = this.addOption(s, 'devgeneral', form.Value, 'txqueuelen', _('TX queue length')); o.placeholder = dev ? dev._devstate('qlen') : ''; o.datatype = 'uinteger'; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Flag, 'promisc', _('Enable promiscious mode')); + o = this.addOption(s, 'devadvanced', form.Flag, 'promisc', _('Enable promiscious mode')); o.default = o.disabled; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.ListValue, 'rpfilter', _('Reverse path filter')); + o = this.addOption(s, 'devadvanced', form.ListValue, 'rpfilter', _('Reverse path filter')); o.default = ''; o.value('', _('disabled')); o.value('loose', _('Loose filtering')); @@ -765,96 +672,96 @@ return baseclass.extend({ return ''; } }; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Flag, 'acceptlocal', _('Accept local'), _('Accept packets with local source addresses')); + o = this.addOption(s, 'devadvanced', form.Flag, 'acceptlocal', _('Accept local'), _('Accept packets with local source addresses')); o.default = o.disabled; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Flag, 'sendredirects', _('Send ICMP redirects')); + o = this.addOption(s, 'devadvanced', form.Flag, 'sendredirects', _('Send ICMP redirects')); o.default = o.enabled; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Value, 'neighreachabletime', _('Neighbour cache validity'), _('Time in milliseconds')); + o = this.addOption(s, 'devadvanced', form.Value, 'neighreachabletime', _('Neighbour cache validity'), _('Time in milliseconds')); o.placeholder = '30000'; o.datatype = 'uinteger'; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Value, 'neighgcstaletime', _('Stale neighbour cache timeout'), _('Timeout in seconds')); + o = this.addOption(s, 'devadvanced', form.Value, 'neighgcstaletime', _('Stale neighbour cache timeout'), _('Timeout in seconds')); o.placeholder = '60'; o.datatype = 'uinteger'; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.Value, 'neighlocktime', _('Minimum ARP validity time'), _('Minimum required time in seconds before an ARP entry may be replaced. Prevents ARP cache thrashing.')); + o = this.addOption(s, 'devadvanced', form.Value, 'neighlocktime', _('Minimum ARP validity time'), _('Minimum required time in seconds before an ARP entry may be replaced. Prevents ARP cache thrashing.')); o.placeholder = '0'; o.datatype = 'uinteger'; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, gensection, form.Flag, 'ipv6', _('Enable IPv6')); + o = this.addOption(s, 'devgeneral', form.Flag, 'ipv6', _('Enable IPv6')); o.migrate = false; o.default = o.enabled; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, gensection, form.Value, 'mtu6', _('IPv6 MTU')); - o.placeholder = getDeviceValue(ifc || dev, 'getMTU'); + o = this.addOption(s, 'devgeneral', form.Value, 'mtu6', _('IPv6 MTU')); + o.placeholder = getDeviceValue(dev, 'getMTU'); o.datatype = 'max(9200)'; - o.depends(Object.assign({ ipv6: '1' }, simpledep)); + o.depends(Object.assign({ ipv6: '1' }, 'type', '')); - o = this.addOption(s, gensection, form.Value, 'dadtransmits', _('DAD transmits'), _('Amount of Duplicate Address Detection probes to send')); + o = this.addOption(s, 'devgeneral', form.Value, 'dadtransmits', _('DAD transmits'), _('Amount of Duplicate Address Detection probes to send')); o.placeholder = '1'; o.datatype = 'uinteger'; - o.depends(Object.assign({ ipv6: '1' }, simpledep)); + o.depends(Object.assign({ ipv6: '1' }, 'type', '')); - o = this.addOption(s, advsection, form.Flag, 'multicast', _('Enable multicast support')); + o = this.addOption(s, 'devadvanced', form.Flag, 'multicast', _('Enable multicast support')); o.default = o.enabled; - o.depends(simpledep); + o.depends('type', ''); - o = this.addOption(s, advsection, form.ListValue, 'igmpversion', _('Force IGMP version')); + o = this.addOption(s, 'devadvanced', form.ListValue, 'igmpversion', _('Force IGMP version')); o.value('', _('No enforcement')); o.value('1', _('Enforce IGMPv1')); o.value('2', _('Enforce IGMPv2')); o.value('3', _('Enforce IGMPv3')); - o.depends(Object.assign({ multicast: '1' }, simpledep)); + o.depends(Object.assign({ multicast: '1' }, 'type', '')); - o = this.addOption(s, advsection, form.ListValue, 'mldversion', _('Force MLD version')); + o = this.addOption(s, 'devadvanced', form.ListValue, 'mldversion', _('Force MLD version')); o.value('', _('No enforcement')); o.value('1', _('Enforce MLD version 1')); o.value('2', _('Enforce MLD version 2')); - o.depends(Object.assign({ multicast: '1' }, simpledep)); + o.depends(Object.assign({ multicast: '1' }, 'type', '')); if (isBridgePort(dev)) { o = this.addOption(s, 'brport', form.Flag, 'learning', _('Enable MAC address learning')); o.default = o.enabled; - o.depends(simpledep); + o.depends('type', ''); o = this.addOption(s, 'brport', form.Flag, 'unicast_flood', _('Enable unicast flooding')); o.default = o.enabled; - o.depends(simpledep); + o.depends('type', ''); o = this.addOption(s, 'brport', form.Flag, 'isolated', _('Port isolation'), _('Only allow communication with non-isolated bridge ports when enabled')); o.default = o.disabled; - o.depends(simpledep); + o.depends('type', ''); o = this.addOption(s, 'brport', form.ListValue, 'multicast_router', _('Multicast routing')); o.value('', _('Never')); o.value('1', _('Learn')); o.value('2', _('Always')); - o.depends(Object.assign({ multicast: '1' }, simpledep)); + o.depends(Object.assign({ multicast: '1' }, 'type', '')); o = this.addOption(s, 'brport', form.Flag, 'multicast_to_unicast', _('Multicast to unicast'), _('Forward multicast packets as unicast packets on this device.')); o.default = o.disabled; - o.depends(Object.assign({ multicast: '1' }, simpledep)); + o.depends(Object.assign({ multicast: '1' }, 'type', '')); o = this.addOption(s, 'brport', form.Flag, 'multicast_fast_leave', _('Enable multicast fast leave')); o.default = o.disabled; - o.depends(Object.assign({ multicast: '1' }, simpledep)); + o.depends(Object.assign({ multicast: '1' }, 'type', '')); } o = this.addOption(s, 'bridgevlan', form.Flag, 'vlan_filtering', _('Enable VLAN filterering')); o.depends('type', 'bridge'); o.updateDefaultValue = function(section_id) { - var device = isIface ? 'br-%s'.format(s.section) : uci.get('network', s.section, 'name'), + var device = uci.get('network', s.section, 'name'), uielem = this.getUIElement(section_id), has_vlans = false; @@ -896,7 +803,7 @@ return baseclass.extend({ }; ss.filter = function(section_id) { - var devname = isIface ? 'br-%s'.format(s.section) : uci.get('network', s.section, 'name'); + var devname = uci.get('network', s.section, 'name'); return (uci.get('network', section_id, 'device') == devname); }; @@ -943,7 +850,7 @@ return baseclass.extend({ ss.handleAdd = function(ev) { return s.parse().then(L.bind(function() { - var device = isIface ? 'br-%s'.format(s.section) : uci.get('network', s.section, 'name'), + var device = uci.get('network', s.section, 'name'), section_ids = this.cfgsections(), section_id = null, max_vlan_id = 0; @@ -1007,38 +914,25 @@ return baseclass.extend({ o = ss.option(form.Flag, 'local', _('Local')); o.default = o.enabled; - /* Do not touch bridge port state from interface config if legacy - * bridge config is disabled due to explicitely declared br-xxx - * device section... */ - if (disableLegacyBridging) - return; - var ports = []; - if (isIface) { - Array.prototype.push.apply(ports, L.toArray(ifc.getDevices() || ifc.getDevice()).map(function(dev) { - return dev.getName(); - })); - } - else { - var seen_ports = {}; + var seen_ports = {}; - L.toArray(uci.get('network', s.section, 'ifname')).forEach(function(ifname) { - seen_ports[ifname] = true; - }); + L.toArray(uci.get('network', s.section, 'ifname')).forEach(function(ifname) { + seen_ports[ifname] = true; + }); - uci.sections('network', 'bridge-vlan', function(bvs) { - L.toArray(bvs.ports).forEach(function(portspec) { - var m = portspec.match(/^([^:]+)(?::[ut*]+)?$/); + uci.sections('network', 'bridge-vlan', function(bvs) { + L.toArray(bvs.ports).forEach(function(portspec) { + var m = portspec.match(/^([^:]+)(?::[ut*]+)?$/); - if (m) - seen_ports[m[1]] = true; - }); + if (m) + seen_ports[m[1]] = true; }); + }); - for (var port_name in seen_ports) - ports.push(port_name); - } + for (var port_name in seen_ports) + ports.push(port_name); ports.sort(); diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js index 5cc85eadb3..7de1e04ac2 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js @@ -405,6 +405,12 @@ return view.extend({ }, this); o.write = function() {}; + o = s.taboption('general', widgets.DeviceSelect, 'ifname', _('Device')); + o.nobridges = false; + o.noaliases = false; + o.optional = false; + o.network = ifc.getName(); + proto_select = s.taboption('general', form.ListValue, 'proto', _('Protocol')); proto_select.modalonly = true; @@ -677,7 +683,6 @@ return view.extend({ } ifc.renderFormOptions(s); - nettools.addDeviceOptions(s, null, true); // Common interface options o = nettools.replaceOption(s, 'advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured')); -- 2.30.2