3 description: L.tr('The network ports on this device can be combined to several VLANs in which computers can communicate directly with each other. VLANs are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network.'),
5 switchPortState: L.cbi.ListValue.extend({
7 [ 'n', L.trc('Switch port state', 'off') ],
8 [ 'u', L.trc('Switch port state', 'untagged') ],
9 [ 't', L.trc('Switch port state', 'tagged') ]
12 init: function(name, options)
16 options.datatype = function(val, elem)
21 var sections = self.section.sections();
23 for (var i = 0; i < sections.length; i++)
25 var v = self.formvalue(sections[i]['.name']);
29 return L.tr('Port must not be untagged in multiple VLANs');
39 this.callSuper('init', name, options);
42 ucivalue: function(sid)
44 var ports = (this.map.get('network', sid, 'ports') || '').match(/[0-9]+[tu]?/g);
47 for (var i = 0; i < ports.length; i++)
48 if (ports[i].match(/^([0-9]+)([tu]?)$/))
49 if (RegExp.$1 == this.name)
50 return RegExp.$2 || 'u';
63 L.network.listSwitchNames().then(function(switches) {
66 for (var i = 0; i < switches.length; i++)
67 L.network.getSwitchInfo(switches[i]);
70 }).then(function(switches) {
71 var m = new L.cbi.Map('network', {
72 readonly: !self.options.acls['switch']
75 for (var i = 0; i < switches.length; i++)
78 var v4k_opt = undefined;
79 var pvid_opt = undefined;
80 var max_vid = switches[i].num_vlans - 1;
81 var num_vlans = switches[i].num_vlans;
83 for (var j = 0; j < switches[i].vlan_attrs.length; j++)
85 switch (switches[i].vlan_attrs[j].name)
90 vid_opt = switches[i].vlan_attrs[j].name;
96 for (var j = 0; j < switches[i].port_attrs.length; j++)
98 switch (switches[i].port_attrs[j].name)
101 pvid_opt = switches[i].port_attrs[j].name;
107 var sw = m.section(L.cbi.TypedSection, 'switch', {
108 caption: L.tr('Switch "%s"').format(switches[i].model),
109 swname: switches[i]['switch']
112 sw.filter = function(section) {
113 return (section['.name'] == this.options.swname ||
114 section.name == this.options.swname);
117 for (var j = 0; j < switches[i].attrs.length; j++)
119 switch (switches[i].attrs[j].name)
122 sw.option(L.cbi.CheckboxValue, 'enable_vlan', {
123 caption: L.tr('Enable VLAN functionality')
127 case 'enable_learning':
128 sw.option(L.cbi.CheckboxValue, 'enable_learning', {
129 caption: L.tr('Enable learning and aging'),
136 sw.option(L.cbi.CheckboxValue, 'max_length', {
137 caption: L.tr('Enable Jumbo Frame passthrough'),
143 case 'enable_vlan4k':
144 v4k_opt = switches[i].attrs[j].name;
149 var vlans = m.section(L.cbi.TableSection, 'switch_vlan', {
150 caption: L.tr('VLANs on "%s"').format(switches[i].model),
151 swname: switches[i]['switch'],
153 add_caption: L.tr('Add VLAN entry …')
156 vlans.add = function() {
157 var sections = this.sections();
160 for (var j = 0; j < sections.length; j++)
162 var v = this.map.get('network', sections[j]['.name'], 'vlan');
167 for (var j = 1; j < num_vlans; j++)
169 if (used_vids[j.toString()])
172 var sid = this.map.add('network', 'switch_vlan');
173 this.map.set('network', sid, 'device', this.options.swname);
174 this.map.set('network', sid, 'vlan', j);
179 vlans.filter = function(section) {
180 return (section.device == this.options.swname);
183 vlans.sections = function() {
184 var s = this.callSuper('sections');
186 s.sort(function(a, b) {
187 var x = parseInt(a[vid_opt] || a.vlan);
191 var y = parseInt(b[vid_opt] || b.vlan);
203 var vo = vlans.option(L.cbi.InputValue, vid_opt, {
204 caption: L.tr('VLAN ID'),
205 datatype: function(val) {
206 var sections = vlans.sections();
209 for (var j = 0; j < sections.length; j++)
211 var v = vlans.fields[vid_opt].formvalue(sections[j]['.name']);
216 return L.tr('VLAN ID must be unique');
224 return L.tr('Invalid VLAN ID');
226 if (v < 1 || v > max_vid)
227 return L.tr('VLAN ID must be value between %u and %u').format(1, max_vid);
233 vo.ucivalue = function(sid) {
234 var id = this.map.get('network', sid, vid_opt);
236 if (isNaN(parseInt(id)))
237 id = this.map.get('network', sid, 'vlan');
242 vo.save = function(sid) {
243 var old_ports = this.map.get('network', sid, 'ports');
246 for (var j = 0; j < port_opts.length; j++)
248 var v = port_opts[j].formvalue(sid);
250 new_ports += '%s%d%s'.format(
251 new_ports ? ' ' : '', j,
252 (v == 'u') ? '' : 't');
255 if (new_ports != old_ports)
256 this.map.set('network', sid, 'ports', new_ports);
260 var s = sw.sections();
261 for (var j = 0; j < s.length; j++)
262 this.map.set('network', s[j]['.name'], v4k_opt, '1');
265 this.callSuper('save', sid);
268 for (var j = 0; j < switches[i].num_ports; j++)
270 var label = L.trc('Switch port label', 'Port %d').format(j);
272 if (j == switches[i].cpu_port)
273 label = L.trc('Switch port label', 'CPU');
275 var po = vlans.option(self.switchPortState, j.toString(), {
283 return m.insertInto('#map');