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++)
77 var swname = switches[i]['switch'];
80 var v4k_opt = undefined;
81 var pvid_opt = undefined;
82 var max_vid = switches[i].num_vlans - 1;
83 var num_vlans = switches[i].num_vlans;
85 for (var j = 0; j < switches[i].vlan_attrs.length; j++)
87 switch (switches[i].vlan_attrs[j].name)
92 vid_opt = switches[i].vlan_attrs[j].name;
98 for (var j = 0; j < switches[i].port_attrs.length; j++)
100 switch (switches[i].port_attrs[j].name)
103 pvid_opt = switches[i].port_attrs[j].name;
109 var sw = m.section(L.cbi.TypedSection, 'switch', {
110 caption: L.tr('Switch "%s"').format(switches[i].model),
114 sw.filter = function(section) {
115 return (section['.name'] == this.options.swname ||
116 section.name == this.options.swname);
119 for (var j = 0; j < switches[i].attrs.length; j++)
121 switch (switches[i].attrs[j].name)
124 sw.option(L.cbi.CheckboxValue, 'enable_vlan', {
125 caption: L.tr('Enable VLAN functionality')
129 case 'enable_learning':
130 sw.option(L.cbi.CheckboxValue, 'enable_learning', {
131 caption: L.tr('Enable learning and aging'),
138 sw.option(L.cbi.CheckboxValue, 'max_length', {
139 caption: L.tr('Enable Jumbo Frame passthrough'),
145 case 'enable_vlan4k':
146 v4k_opt = switches[i].attrs[j].name;
151 var vlans = m.section(L.cbi.TableSection, 'switch_vlan', {
152 caption: L.tr('VLANs on "%s"').format(switches[i].model),
155 add_caption: L.tr('Add VLAN entry …')
158 vlans.add = function() {
159 var sections = this.sections();
162 for (var j = 0; j < sections.length; j++)
164 var v = this.map.get('network', sections[j]['.name'], 'vlan');
169 for (var j = 1; j < num_vlans; j++)
171 if (used_vids[j.toString()])
174 var sid = this.map.add('network', 'switch_vlan');
175 this.map.set('network', sid, 'device', this.options.swname);
176 this.map.set('network', sid, 'vlan', j);
181 vlans.filter = function(section) {
182 return (section.device == this.options.swname);
185 vlans.sections = function() {
186 var s = this.callSuper('sections');
188 s.sort(function(a, b) {
189 var x = parseInt(a[vid_opt] || a.vlan);
193 var y = parseInt(b[vid_opt] || b.vlan);
205 var vo = vlans.option(L.cbi.InputValue, vid_opt, {
206 caption: L.tr('VLAN ID'),
207 datatype: function(val) {
208 var sections = vlans.sections();
211 for (var j = 0; j < sections.length; j++)
213 var v = vlans.fields[vid_opt].formvalue(sections[j]['.name']);
218 return L.tr('VLAN ID must be unique');
226 return L.tr('Invalid VLAN ID');
228 if (v < 1 || v > max_vid)
229 return L.tr('VLAN ID must be value between %u and %u').format(1, max_vid);
235 vo.ucivalue = function(sid) {
236 var id = this.map.get('network', sid, vid_opt);
238 if (isNaN(parseInt(id)))
239 id = this.map.get('network', sid, 'vlan');
244 vo.save = function(sid) {
245 var old_ports = this.map.get('network', sid, 'ports');
248 for (var j = 0; j < port_opts.length; j++)
250 var v = port_opts[j].formvalue(sid);
252 new_ports += '%s%d%s'.format(
253 new_ports ? ' ' : '', j,
254 (v == 'u') ? '' : 't');
257 if (new_ports != old_ports)
258 this.map.set('network', sid, 'ports', new_ports);
262 var s = sw.sections();
263 for (var j = 0; j < s.length; j++)
264 this.map.set('network', s[j]['.name'], v4k_opt, '1');
267 this.callSuper('save', sid);
270 for (var j = 0; j < switches[i].num_ports; j++)
272 var label = L.trc('Switch port label', 'Port %d').format(j);
274 if (j == switches[i].cpu_port)
275 label = L.trc('Switch port label', 'CPU');
277 var po = vlans.option(self.switchPortState, j.toString(), {
278 caption: label + '<br /><small id="portstatus-%s-%d"></small>'.format(swname, j)
285 m.insertInto('#map');
287 self.repeat(function() {
288 return L.network.getSwitchStatus(swname).then(function(ports) {
289 for (var j = 0; j < ports.length; j++)
291 var s = L.tr('No link');
296 s = '%dbaseT'.format(ports[j].speed);
297 d = ports[j].full_duplex ? L.tr('Full-duplex') : L.tr('Half-duplex');
300 $('#portstatus-%s-%d'.format(swname, j))
301 .empty().append(s + '<br />' + d);