1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.0//EN'
>
4 Copyright (C) 2011-2012 Augusto Bott
5 http://code.google.com/p/tomato-sdhc-vlan/
8 Copyright (C) 2006-2007 Jonathan Zarate
9 http://www.polarcloud.com/tomato/
11 Tomato VLAN update and bug correction
12 Copyright (C) 2011-2012 Vicente Soriano
15 For use with Tomato Firmware only.
16 No part of this file may be used without permission.
20 <meta http-equiv='content-type' content='text/html;charset=utf-
8'
>
21 <meta name='robots' content='noindex,nofollow'
>
22 <title>[<%
ident(); %>] Advanced: VLAN
</title>
23 <link rel='stylesheet' type='text/css' href='tomato.css'
>
25 <script type='text/javascript' src='tomato.js'
></script>
26 <style type='text/css'
>
46 #vlan-grid .centered
{
50 <script type='text/javascript' src='wireless.jsx?_http_id=<%
nv(http_id
); %>'
></script>
51 <script type='text/javascript' src='interfaces.js'
></script>
52 <script type='text/javascript'
>
53 <% nvram ("vlan0ports,vlan1ports,vlan2ports,vlan3ports,vlan4ports,vlan5ports,vlan6ports,vlan7ports,vlan8ports,vlan9ports,vlan10ports,vlan11ports,vlan12ports,vlan13ports,vlan14ports,vlan15ports,vlan0hwname,vlan1hwname,vlan2hwname,vlan3hwname,vlan4hwname,vlan5hwname,vlan6hwname,vlan7hwname,vlan8hwname,vlan9hwname,vlan10hwname,vlan11hwname,vlan12hwname,vlan13hwname,vlan14hwname,vlan15hwname,wan_ifnameX,manual_boot_nv,boardtype,boardflags,trunk_vlan_so,lan_ifname,lan_ifnames,lan1_ifname,lan1_ifnames,lan2_ifname,lan2_ifnames,lan3_ifname,lan3_ifnames,boardrev,vlan0tag,vlan0vid,vlan1vid,vlan2vid,vlan3vid,vlan4vid,vlan5vid,vlan6vid,vlan7vid,vlan8vid,vlan9vid,vlan10vid,vlan11vid,vlan12vid,vlan13vid,vlan14vid,vlan15vid");%>
55 var port_vlan_supported
= 0;
56 var trunk_vlan_supported
= 0;
58 // does not seem to be strictly necessary for boardflags as it's supposed to be a bitmap
59 nvram
['boardflags'] = ((nvram
['boardflags'].toLowerCase().indexOf('0x') != -1) ? '0x' : '') + String('0000' + ((nvram
['boardflags'].toLowerCase()).replace('0x',''))).slice(-4);
60 // but the contents of router/shared/id.c seem to indicate string formatting/padding might be required for some models as we check if strings match
61 nvram
['boardtype'] = ((nvram
['boardtype'].toLowerCase().indexOf('0x') != -1) ? '0x' : '') + String('0000' + ((nvram
['boardtype'].toLowerCase()).replace('0x',''))).slice(-4);
63 // see http://www.dd-wrt.com/wiki/index.php/Hardware#Boardflags and router/shared/id.c
64 if(nvram
['boardflags'] & 0x0100) { // BFL_ENETVLAN = this board has vlan capability
65 port_vlan_supported
= 1;
68 // TESTED ONLY ON WRT54G v2 (boardtype 0x0101) and WRT54GL v1.1 (boardtype 0x0467)
69 // attempt of cross-referencing boardtypes/routers mentioned on id.c and the wiki page above
70 switch(nvram
['boardtype']) {
71 case '0x0467': // WRT54GL 1.x, WRT54GS 3.x/4.x
72 case '0x048e': // WL-520GU, WL-500G Premium v2
73 case '0x04ef': // WRT320N/E2000
74 case '0x04cf': // WRT610Nv2/E3000, RT-N16
75 case '0xf52c': // E4200v1
76 case '0xf52a': // E3200v1
77 case '0xf5b2': // RT-N66
78 trunk_vlan_supported
= 1;
84 // TESTED ONLY ON WRT54G v2 (boardtype 0x0101),WRT54GL v1.1 (boardtype 0x0467) and WNR3500L (boardtype 0x04cf)
85 // info on some of these boardtypes/routers obtained from
86 // http://wiki.openwrt.org/toh/asus/start
87 // http://wiki.openwrt.org/toh/linksys/start
88 // http://wiki.openwrt.org/toh/start
89 switch(nvram
['boardtype']) {
90 case '0x0467': // WRT54GL 1.x, WRT54GS 3.x/4.x
91 if (nvram
['boardrev'] == '0x13') { // WHR-G54S
99 case '0xa4cf': // Belkin F7D3301
100 if (nvram
['boardrev'] == '0x1100') { //Belkin F5D8235-4 v3
108 case '0xd4cf': // Belkin F7D4301
109 case '0x048e': // WL-520GU, WL-500G Premium v2
110 case '0x0550': // RT-N53 (boardrev = 0x1442), RT-N10U ( boardrev = 0x1102)
111 if (((nvram
['boardrev'] == '0x1102') || (nvram
['boardrev'] == '0x1100')) || (nvram
['boardrev'] == '0x1400')) { //RT-N10U, CW-5358U, L600N
119 if (nvram
['boardrev'] == '0x1100') { //CW-5358U
133 case '0x04ef': // WRT320N/E2000
134 case '0x04cf': // WRT610Nv2/E3000, RT-N16, WNR3500L
135 case '0xf5b2': // RT-N66
136 case '0x052b': // WNR3500Lv2
143 case '0xf53a': // E1000v2.1/E1200v1
144 case '0xf53b': // E1000v2/E1500
145 if (((nvram
['boot_hw_model'] == 'E1200') && (nvram
['boot_hw_ver'] == '1.0')) || (nvram
['boot_hw_model'] == 'E1500')) {
159 case '0xc550': // E1550
160 case '0xf550': // E2500
161 case '0x058e': // E900
162 case '0xf52a': // E3200
163 case '0xf52c': // E4200v1
164 case '0x1202': // HG320 - not sure, need test
165 if (nvram
['boardrev'] == '0x1153') { //RG200E-CA type 0x058e same as E900
179 if (nvram
['boardrev'] == '0x1204') { //rt-n15u
187 // should work on WRT54G v2/v3, WRT54GS v1/v2 and others
209 var COL_VID_DEF
= 12;
212 var vlt
= nvram
.vlan0tag
| '0';
214 // set to either 5 or 8 when nvram settings are read (FastE or GigE routers)
215 var SWITCH_INTERNAL_PORT
=0;
216 // option made available for experimental purposes on routers known to support port-based VLANs, but not confirmed to support 801.11q trunks
217 var PORT_VLAN_SUPPORT_OVERRIDE
= ((nvram
['trunk_vlan_so'] == '1') ? 1 : 0);
219 function verifyFields(focused
, quiet
){
220 PORT_VLAN_SUPPORT_OVERRIDE
=(E('_f_trunk_vlan_so').checked
? 1 : 0);
221 for (var uidx
= 0; uidx
< wl_ifaces
.length
; ++uidx
) {
222 var u
= wl_fface(uidx
);
223 var wlan
= E('_f_bridge_wlan'+u
+'_to');
224 if(nvram
.lan_ifname
.length
< 1)
225 wlan
.options
[0].disabled
=true;
226 if(nvram
.lan1_ifname
.length
< 1)
227 wlan
.options
[1].disabled
=true;
228 if(nvram
.lan2_ifname
.length
< 1)
229 wlan
.options
[2].disabled
=true;
230 if(nvram
.lan3_ifname
.length
< 1)
231 wlan
.options
[3].disabled
=true;
233 var e
= E('_vlan0tag');
234 if (!v_range('_vlan0tag', quiet
, 0, 4080)) return 0;
235 var v
= parseInt(e
.value
);
236 e
.value
= v
- (v
% 16);
237 if ((e
.value
!= vlt
) && (typeof(vlg
) != 'undefined')) {
245 if (vlg
.isEditing()) return;
248 fom
.trunk_vlan_so
.value
= (E('_f_trunk_vlan_so').checked
? 1 : 0);
249 // wipe out relevant fields just in case this is not the first time we try to submit
250 for (var i
= 0 ; i
<= MAX_VLAN_ID
; i
++) {
251 fom
['vlan' + i
+ 'ports'].value
= '';
252 fom
['vlan' + i
+ 'hwname'].value
= '';
253 fom
['vlan' + i
+ 'vid'].value
= '';
255 fom
['wan_ifnameX'].value
= '';
256 fom
['lan_ifnames'].value
= '';
257 fom
['lan1_ifnames'].value
= '';
258 fom
['lan2_ifnames'].value
= '';
259 fom
['lan3_ifnames'].value
= '';
262 var d
= vlg
.getAllData();
264 for (var i
= 0; i
< d
.length
; ++i
) {
266 p
+= (d
[i
][COL_P0
].toString() != '0') ? COL_P0N
: '';
267 p
+= (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (d
[i
][COL_P0T
].toString() != '0')) ? 't' : '';
268 p
+= trailingSpace(p
);
270 p
+= (d
[i
][COL_P1
].toString() != '0') ? COL_P1N
: '';
271 p
+= (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (d
[i
][COL_P1T
].toString() != '0')) ? 't' : '';
272 p
+= trailingSpace(p
);
274 p
+= (d
[i
][COL_P2
].toString() != '0') ? COL_P2N
: '';
275 p
+= (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (d
[i
][COL_P2T
].toString() != '0')) ? 't' : '';
276 p
+= trailingSpace(p
);
278 p
+= (d
[i
][COL_P3
].toString() != '0') ? COL_P3N
: '';
279 p
+= (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (d
[i
][COL_P3T
].toString() != '0')) ? 't' : '';
280 p
+= trailingSpace(p
);
282 p
+= (d
[i
][COL_P4
].toString() != '0') ? COL_P4N
: '';
283 p
+= (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (d
[i
][COL_P4T
].toString() != '0')) ? 't' : '';
284 p
+= trailingSpace(p
);
286 p
+= (d
[i
][COL_VID_DEF
].toString() != '0') ? (SWITCH_INTERNAL_PORT
+ '*') : SWITCH_INTERNAL_PORT
;
288 // arrange port numbers in ascending order just to be safe (not sure if this is really needed... mostly, cosmetics?)
293 v
+= (d
[i
][COL_VID_DEF
].toString() != '0') ? d
[i
][0] : '';
295 fom
['vlan'+d
[i
][COL_VID
]+'ports'].value
= p
;
296 fom
['vlan'+d
[i
][COL_VID
]+'hwname'].value
= 'et0';
297 fom
['vlan'+d
[i
][COL_VID
]+'vid'].value
= ((d
[i
][COL_MAP
].toString() != '') && (d
[i
][COL_MAP
].toString() != '0')) ? d
[i
][COL_MAP
] : '';
299 fom
['wan_ifnameX'].value
+= (d
[i
][COL_BRI
] == '2') ? 'vlan'+d
[i
][0] : '';
300 fom
['lan_ifnames'].value
+= (d
[i
][COL_BRI
] == '3') ? 'vlan'+d
[i
][0] : '';
302 // fom['lan_ifnames'].value += trailingSpace(fom['lan_ifnames'].value);
303 // alert('vlan'+d[i][0]+'ports='+fom['vlan'+d[i][0]+'ports'].value+'\nvlan'+d[i][0]+'hwname='+fom['vlan'+d[i][0]+'hwname'].value);
305 fom
['lan1_ifnames'].value
+= (d
[i
][COL_BRI
] == '4') ? 'vlan'+d
[i
][0] : '';
306 fom
['lan2_ifnames'].value
+= (d
[i
][COL_BRI
] == '5') ? 'vlan'+d
[i
][0] : '';
307 fom
['lan3_ifnames'].value
+= (d
[i
][COL_BRI
] == '6') ? 'vlan'+d
[i
][0] : '';
310 for (var uidx
= 0; uidx
< wl_ifaces
.length
; ++uidx
) {
311 var u
= wl_fface(uidx
);
312 var wlan
= E('_f_bridge_wlan'+u
+'_to');
314 // var wlan = E('_f_bridge_wlan_to');
315 // alert(wlan.selectedIndex);
317 switch(parseInt(wlan
.selectedIndex
)) {
319 fom
['lan_ifnames'].value
+= ' ' + wl_ifaces
[uidx
][0];
322 fom
['lan1_ifnames'].value
+= ' ' + wl_ifaces
[uidx
][0];
325 fom
['lan2_ifnames'].value
+= ' ' + wl_ifaces
[uidx
][0];
328 fom
['lan3_ifnames'].value
+= ' ' + wl_ifaces
[uidx
][0];
333 // var lif = nvram['lan_ifnames'].split(' ');
334 // for (var j = 0; j < lif.length; j++) {
335 // fom['lan_ifnames'].value += (lif[j].indexOf('vlan') != -1) ? '' : lif[j];
336 // fom['lan_ifnames'].value += trailingSpace(fom['lan_ifnames'].value);
338 // alert('lan_ifnames=' + fom['lan_ifnames'].value + '\n' +
339 // 'lan1_ifnames=' + fom['lan1_ifnames'].value + '\n' +
340 // 'lan2_ifnames=' + fom['lan2_ifnames'].value + '\n' +
341 // 'lan3_ifnames=' + fom['lan3_ifnames'].value);
344 // for some models, Tomato checks for a few vital/crucial nvram settings at init time
345 // in some cases, if some/any of them are not found, a full nvram reset/clean could be triggered
346 // so, to (try to) play it safe, we check for the 1st needed/available/required
347 // VLAN for FastE (vlan0 is usually LAN) and GigE routers (vlan1 is usually LAN)
348 if((fom
['vlan0ports'].value
.length
< 1) || (fom
['vlan0hwname'].value
.length
< 1) ||
349 (fom
['vlan1ports'].value
.length
< 1) || (fom
['vlan1hwname'].value
.length
< 1))
350 fom
['manual_boot_nv'].value
= '1';
352 fom
['manual_boot_nv'].value
= nvram
['manual_boot_nv'];
354 var e
= E('footer-msg');
356 if(vlg
.countWan() != 1) {
357 e
.innerHTML
= 'Cannot proceed: one VID must be assigned to WAN.';
358 e
.style
.visibility
= 'visible';
362 e
.style
.visibility
= 'hidden';
367 if(vlg
.countLan(0) != 1) {
368 e
.innerHTML
= 'Cannot proceed: one and only one VID must be assigned to the primary LAN (br0).';
369 e
.style
.visibility
= 'visible';
373 e
.style
.visibility
= 'hidden';
379 e
.innerHTML
= 'Cannot proceed without setting a default VID';
380 e
.style
.visibility
= 'visible';
384 e
.style
.visibility
= 'hidden';
389 if (confirm("Router must be rebooted to proceed. Commit changes to NVRAM and reboot now?"))
393 function trailingSpace(s
)
395 return ((s
.length
>0)&&(s
.charAt(s
.length
-1) != ' ')) ? ' ' : '';
398 if(port_vlan_supported
) { // aka if(supported_hardware) block
399 var vlg
= new TomatoGrid();
400 vlg
.setup = function() {
401 this.init('vlan-grid', '', (MAX_VLAN_ID
+ 1), [
402 { type
: 'select', options
: [[0, '0'],[1, '1'],[2, '2'],[3, '3'],[4, '4'],[5, '5'],[6, '6'],[7, '7'],[8, '8'],[9, '9'],[10, '10'],[11, '11'],[12, '12'],[13, '13'],[14, '14'],[15, '15']], prefix
: '<div class="centered">', suffix
: '</div>' },
403 { type
: 'text', maxlen
: 4, prefix
: '<div class="centered">', suffix
: '</div>' },
404 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
405 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
406 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
407 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
408 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
409 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
410 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
411 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
412 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
413 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
414 { type
: 'checkbox', prefix
: '<div class="centered">', suffix
: '</div>' },
415 { type
: 'select', options
: [[1, 'none'],[2, 'WAN'],[3, 'LAN (br0)'],[4, 'LAN1 (br1)'],[5, 'LAN2 (br2)'],[6, 'LAN3 (br3)']], prefix
: '<div class="centered">', suffix
: '</div>' }]);
417 this.headerSet(['VLAN', 'VID', 'Port 1', 'Tagged', 'Port 2', 'Tagged', 'Port 3', 'Tagged', 'Port 4', 'Tagged', 'WAN Port', 'Tagged', 'Default', 'Bridge']);
420 vlg
.canDelete
= false;
423 vlg
.resetNewEditor();
426 vlg
.populate = function() {
429 // find out which vlans are supposed to be bridged to each LAN
432 for (var i
= 0 ; i
<= MAX_BRIDGE_ID
; i
++) {
433 var j
= (i
== 0) ? '' : i
.toString();
434 var l
= nvram
['lan' + j
+ '_ifnames'].split(' ');
436 // alert('lan' + j + '_ifnames=' + l);
438 for (var k
= 0 ; k
< l
.length
; k
++) {
440 // alert("bridge br" + i + "=vlan" + parseInt(l[k].replace('vlan','')));
442 if(l
[k
].indexOf('vlan') != -1) {
444 // alert('lan' + j + '_ifname=br' + nvram['lan' + j + '_ifname'].replace('br',''));
446 if (nvram
['lan' + j
+ '_ifname'] != '')
447 bridged
[parseInt(l
[k
].replace('vlan',''))] = (3 + parseInt(nvram
['lan' + j
+ '_ifname'].replace('br',''))).toString();
449 bridged
[parseInt(l
[k
].replace('vlan',''))] = '1';
452 for (var uidx
= 0; uidx
< wl_ifaces
.length
; ++uidx
) {
453 if(l
[k
].indexOf(wl_ifaces
[uidx
][0]) != -1) {
454 E('_f_bridge_wlan'+wl_fface(uidx
)+'_to').selectedIndex
=i
;
461 bridged
[parseInt(nvram
['wan_ifnameX'].replace('vlan',''))] = '2';
463 // go thru all possible VLANs
464 for (var i
= 0 ; i
<= MAX_VLAN_ID
; i
++) {
467 if ((nvram
['vlan' + i
+ 'hwname'].length
> 0) || (nvram
['vlan' + i
+ 'ports'].length
> 0)) {
468 // (re)initialize our bitmap for this particular iteration
469 for (var j
=0; j
<= MAX_PORT_ID
; j
++) {
473 // which ports are members of this VLAN?
474 var m
=nvram
['vlan' + i
+ 'ports'].split(' ');
475 for (var j
= 0; j
< (m
.length
) ; j
++) {
476 port
[parseInt(m
[j
].charAt(0))] = '1';
477 tagged
[parseInt(m
[j
].charAt(0))] = (((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (m
[j
].indexOf('t') != -1)) ? '1' : '0';
480 if (port_vlan_supported
) {
481 if((nvram
['vlan' + i
+ 'ports']).indexOf('*') != -1)
482 SWITCH_INTERNAL_PORT
=(nvram
['vlan' + i
+ 'ports']).charAt((nvram
['vlan' + i
+ 'ports']).indexOf('*')-1);
484 vlg
.insertData(-1, [ i
.toString(),
485 ((nvram
['vlan' + i
+ 'vid'] != '') && (nvram
['vlan' + i
+ 'vid'] > 0)) ? (nvram
['vlan' + i
+ 'vid']).toString() : '0',
486 port
[COL_P0N
], tagged
[COL_P0N
],
487 port
[COL_P1N
], tagged
[COL_P1N
],
488 port
[COL_P2N
], tagged
[COL_P2N
],
489 port
[COL_P3N
], tagged
[COL_P3N
],
490 port
[COL_P4N
], tagged
[COL_P4N
],
491 (((nvram
['vlan' + i
+ 'ports']).indexOf('*') != -1) ? '1' : '0' ),
492 (bridged
[i
] != null) ? bridged
[i
] : '1' ]);
498 vlg
.countElem = function(f
, v
)
500 var data
= this.getAllData();
502 for (var i
= 0; i
< data
.length
; ++i
) {
503 total
+= (data
[i
][f
] == v
) ? 1 : 0;
508 vlg
.countDefaultVID = function()
510 return this.countElem(COL_VID_DEF
,1);
513 vlg
.countVID = function (v
)
515 return this.countElem(COL_VID
,v
);
518 vlg
.countWan = function()
520 return this.countElem(COL_BRI
,2);
523 vlg
.countLan = function(l
)
525 return this.countElem(COL_BRI
,l
+3);
528 vlg
.verifyFields = function(row
, quiet
) {
530 var f
= fields
.getAll(row
);
532 for(var i
=0; i
<= MAX_VLAN_ID
; i
++) {
533 f
[COL_VID
].options
[i
].disabled
= (this.countVID(i
) > 0);
536 for (var i
=0; i
<= MAX_BRIDGE_ID
; i
++) {
537 var j
= (i
==0) ? '' : i
.toString();
538 f
[COL_BRI
].options
[i
+2].disabled
= (nvram
['lan' + j
+ '_ifname'].length
< 1);
541 if (!v_range(f
[COL_MAP
], quiet
, 0, 4094)) valid
= 0;
543 if(((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (f
[COL_P0
].checked
== 1)) {
544 f
[COL_P0T
].disabled
=0;
546 // if((f[COL_P0T].checked==0) || (this.countElem(COL_P0,1)>0) )
547 // if(this.countElem(COL_P0,1)>0) {
551 f
[COL_P0T
].disabled
=1;
552 f
[COL_P0T
].checked
=0;
554 if(((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (f
[COL_P1
].checked
== 1)) {
555 f
[COL_P1T
].disabled
=0;
557 f
[COL_P1T
].disabled
=1;
558 f
[COL_P1T
].checked
=0;
560 if(((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (f
[COL_P2
].checked
== 1)) {
561 f
[COL_P2T
].disabled
=0;
563 f
[COL_P2T
].disabled
=1;
564 f
[COL_P2T
].checked
=0;
566 if(((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (f
[COL_P3
].checked
== 1)) {
567 f
[COL_P3T
].disabled
=0;
569 f
[COL_P3T
].disabled
=1;
570 f
[COL_P3T
].checked
=0;
572 if(((trunk_vlan_supported
) || (PORT_VLAN_SUPPORT_OVERRIDE
)) && (f
[COL_P4
].checked
== 1)) {
573 f
[COL_P4T
].disabled
=0;
575 f
[COL_P4T
].disabled
=1;
576 f
[COL_P4T
].checked
=0;
579 if ((f
[COL_P0
].checked
== 1) && (this.countElem(COL_P0
,1)>0)) {
580 if (((this.countElem(COL_P0
,1) != this.countElem(COL_P0T
,1)) || (f
[COL_P0T
].checked
==0))) {
581 ferror
.set(f
[COL_P0T
], 'Port 1 cannot be assigned to more than one VLAN unless frames are tagged on all VLANs Port 1 is member', quiet
);
584 ferror
.clear(f
[COL_P0T
]);
587 if ((f
[COL_P1
].checked
== 1) && (this.countElem(COL_P1
,1)>0)) {
588 if (((this.countElem(COL_P1
,1) != this.countElem(COL_P1T
,1)) || (f
[COL_P1T
].checked
==0))) {
589 ferror
.set(f
[COL_P1T
], 'Port 2 cannot be assigned to more than one VLAN unless frames are tagged on all VLANs Port 2 is member', quiet
);
592 ferror
.clear(f
[COL_P1T
]);
595 if ((f
[COL_P2
].checked
== 1) && (this.countElem(COL_P2
,1)>0)) {
596 if (((this.countElem(COL_P2
,1) != this.countElem(COL_P2T
,1)) || (f
[COL_P2T
].checked
==0))) {
597 ferror
.set(f
[COL_P2T
], 'Port 3 cannot be assigned to more than one VLAN unless frames are tagged on all VLANs Port 3 is member', quiet
);
600 ferror
.clear(f
[COL_P2T
]);
603 if ((f
[COL_P3
].checked
== 1) && (this.countElem(COL_P3
,1)>0)) {
604 if (((this.countElem(COL_P3
,1) != this.countElem(COL_P3T
,1)) || (f
[COL_P3T
].checked
==0))) {
605 ferror
.set(f
[COL_P3T
], 'Port 4 cannot be assigned to more than one VLAN unless frames are tagged on all VLANs Port 4 is member', quiet
);
608 ferror
.clear(f
[COL_P3T
]);
611 if ((f
[COL_P4
].checked
== 1) && (this.countElem(COL_P4
,1)>0)) {
612 if (((this.countElem(COL_P4
,1) != this.countElem(COL_P4T
,1)) || (f
[COL_P4T
].checked
==0))) {
613 ferror
.set(f
[COL_P4T
], 'WAN port cannot be assigned to more than one VLAN unless frames are tagged on all VLANs WAN port is member', quiet
);
616 ferror
.clear(f
[COL_P4T
]);
620 if(this.countDefaultVID() > 0) {
621 f
[COL_VID_DEF
].disabled
=1;
622 f
[COL_VID_DEF
].checked
=0;
625 if((this.countDefaultVID() > 0) && (f
[COL_VID_DEF
].checked
==1)) {
626 ferror
.set(f
[COL_VID_DEF
], 'Only one VID can be selected as the default VID', quiet
);
629 ferror
.clear(f
[COL_VID_DEF
]);
632 if(this.countVID(f
[COL_VID
].selectedIndex
) > 0) {
633 ferror
.set(f
[COL_VID
], 'Cannot add more than one entry with VID ' + f
[0].selectedIndex
, quiet
);
636 ferror
.clear(f
[COL_VID
]);
639 if ((this.countWan() > 0) && (f
[COL_BRI
].selectedIndex
== 1)) {
640 ferror
.set(f
[COL_BRI
],'Only one VID can be used as WAN at any time', quiet
);
643 ferror
.clear(f
[COL_BRI
]);
646 for(var i
=0; i
<4; i
++) {
647 if ((this.countLan(i
) > 0) && (f
[COL_BRI
].selectedIndex
== (i
+2))) {
648 ferror
.set(f
[COL_BRI
],'One and only one VID can be used for LAN' + ((i
==0) ? '' : i
) + ' (br'+i
+') at any time', quiet
);
651 ferror
.clear(f
[COL_BRI
]);
658 vlg
.dataToView = function(data
) {
659 return [data
[COL_VID
],
660 ((data
[COL_MAP
].toString() == '') || (data
[COL_MAP
].toString() == '0')) ? (parseInt(E('_vlan0tag').value
) * 1 + data
[COL_VID
] *1 ).toString() : data
[COL_MAP
].toString(),
661 (data
[COL_P0
].toString() != '0') ? 'Yes' : '',
662 (data
[COL_P0T
].toString() != '0') ? 'On' : '',
663 (data
[COL_P1
].toString() != '0') ? 'Yes' : '',
664 (data
[COL_P1T
].toString() != '0') ? 'On' : '',
665 (data
[COL_P2
].toString() != '0') ? 'Yes' : '',
666 (data
[COL_P2T
].toString() != '0') ? 'On' : '',
667 (data
[COL_P3
].toString() != '0') ? 'Yes' : '',
668 (data
[COL_P3T
].toString() != '0') ? 'On' : '',
669 (data
[COL_P4
].toString() != '0') ? 'Yes' : '',
670 (data
[COL_P4T
].toString() != '0') ? 'On' : '',
671 (data
[COL_VID_DEF
].toString() != '0') ? '*' : '',
672 ['', 'WAN', 'LAN (br0)', 'LAN1 (br1)', 'LAN2 (br2)', 'LAN3 (br3)' ][data
[COL_BRI
] - 1]];
675 vlg
.dataToFieldValues = function (data
) {
676 return [data
[COL_VID
],
678 (data
[COL_P0
] != 0) ? 'checked' : '',
679 (data
[COL_P0T
] != 0) ? 'checked' : '',
680 (data
[COL_P1
] != 0) ? 'checked' : '',
681 (data
[COL_P1T
] != 0) ? 'checked' : '',
682 (data
[COL_P2
] != 0) ? 'checked' : '',
683 (data
[COL_P2T
] != 0) ? 'checked' : '',
684 (data
[COL_P3
] != 0) ? 'checked' : '',
685 (data
[COL_P3T
] != 0) ? 'checked' : '',
686 (data
[COL_P4
] != 0) ? 'checked' : '',
687 (data
[COL_P4T
] != 0) ? 'checked' : '',
688 (data
[COL_VID_DEF
] != 0) ? 'checked' : '',
692 vlg
.fieldValuesToData = function(row
) {
693 var f
= fields
.getAll(row
);
694 return [f
[COL_VID
].value
,
696 f
[COL_P0
].checked
? 1 : 0,
697 f
[COL_P0T
].checked
? 1 : 0,
698 f
[COL_P1
].checked
? 1 : 0,
699 f
[COL_P1T
].checked
? 1 : 0,
700 f
[COL_P2
].checked
? 1 : 0,
701 f
[COL_P2T
].checked
? 1 : 0,
702 f
[COL_P3
].checked
? 1 : 0,
703 f
[COL_P3T
].checked
? 1 : 0,
704 f
[COL_P4
].checked
? 1 : 0,
705 f
[COL_P4T
].checked
? 1 : 0,
706 f
[COL_VID_DEF
].checked
? 1 : 0,
710 vlg
.onCancel = function() {
713 this.disableNewEditor(false);
715 this.resetNewEditor();
718 vlg
.onAdd = function() {
724 if (!this.verifyFields(this.newEditor
, false)) return;
726 data
= this.fieldValuesToData(this.newEditor
);
727 this.insertData(-1, data
);
729 this.disableNewEditor(false);
730 this.resetNewEditor();
735 vlg
.onOK = function() {
738 if (!this.verifyFields(this.editor
, false)) return;
740 data
= this.fieldValuesToData(this.editor
);
741 view
= this.dataToView(data
);
743 this.source
.setRowData(data
);
744 for (i
= 0; i
< this.source
.cells
.length
; ++i
) {
745 this.source
.cells
[i
].innerHTML
= view
[i
];
750 this.disableNewEditor(false);
752 this.resetNewEditor();
756 vlg
.onDelete = function() {
758 elem
.remove(this.source
);
760 this.disableNewEditor(false);
762 this.resetNewEditor();
765 vlg
.sortCompare = function(a
, b
) {
767 var col
= obj
.sortColumn
;
768 if (this.sortColumn
== 0) {
769 var r
= cmpInt(parseInt(a
.cells
[col
].innerHTML
), parseInt(b
.cells
[col
].innerHTML
));
771 var r
= cmpText(a
.cells
[col
].innerHTML
, b
.cells
[col
].innerHTML
);
773 return obj
.sortAscending
? r
: -r
;
776 vlg
.resetNewEditor = function() {
777 var f
= fields
.getAll(this.newEditor
);
779 for (var i
=0; i
<= MAX_BRIDGE_ID
; i
++) {
780 var j
= (i
==0) ? '' : i
.toString();
781 f
[COL_BRI
].options
[i
+2].disabled
= (nvram
['lan' + j
+ '_ifname'].length
< 1);
784 f
[COL_MAP
].value
= '0';
786 f
[COL_VID
].selectedIndex
=0;
788 while((this.countVID(f
[COL_VID
].selectedIndex
) > 0) && (t
> 0)) {
789 f
[COL_VID
].selectedIndex
= (f
[COL_VID
].selectedIndex
%(MAX_VLAN_ID
))+1;
793 for(var i
=0; i
<= MAX_VLAN_ID
; i
++) {
794 f
[COL_VID
].options
[i
].disabled
= (this.countVID(i
) > 0);
797 f
[COL_P0
].checked
= 0;
798 f
[COL_P0T
].checked
= 0;
799 f
[COL_P0T
].disabled
= 1;
800 f
[COL_P1
].checked
= 0;
801 f
[COL_P1T
].checked
= 0;
802 f
[COL_P1T
].disabled
= 1;
803 f
[COL_P2
].checked
= 0;
804 f
[COL_P2T
].checked
= 0;
805 f
[COL_P2T
].disabled
= 1;
806 f
[COL_P3
].checked
= 0;
807 f
[COL_P3T
].checked
= 0;
808 f
[COL_P3T
].disabled
= 1;
809 f
[COL_P4
].checked
= 0;
810 f
[COL_P4T
].checked
= 0;
811 f
[COL_P4T
].disabled
= 1;
812 f
[COL_VID_DEF
].checked
= 0;
813 if (this.countDefaultVID()>0)
814 f
[COL_VID_DEF
].disabled
= 1;
815 f
[COL_BRI
].selectedIndex
= 0;
816 ferror
.clearAll(fields
.getAll(this.newEditor
));
818 } // end of the so-called if(supported_device) block
821 if(port_vlan_supported
) {
823 vlg
.resetNewEditor();
825 if (((c
= cookie
.get('advanced_vlan_notes_vis')) != null) && (c
== '1')) toggleVisibility("notes");
826 if (((c
= cookie
.get('advanced_vlan_wireless_vis')) != null) && (c
== '1')) toggleVisibility("wireless");
827 if (((c
= cookie
.get('advanced_vlan_vidmap_vis')) != null) && (c
== '1')) toggleVisibility("vidmap");
831 function toggleVisibility(whichone
) {
832 if (E('sesdiv_' + whichone
).style
.display
== '') {
833 E('sesdiv_' + whichone
).style
.display
= 'none';
834 E('sesdiv_' + whichone
+ '_showhide').innerHTML
= '(Click here to show)';
835 cookie
.set('advanced_vlan_' + whichone
+ '_vis', 0);
837 E('sesdiv_' + whichone
).style
.display
='';
838 E('sesdiv_' + whichone
+ '_showhide').innerHTML
= '(Click here to hide)';
839 cookie
.set('advanced_vlan_' + whichone
+ '_vis', 1);
843 function earlyInit() {
844 if(!port_vlan_supported
) {
845 E('save-button').disabled
= 1;
848 PORT_VLAN_SUPPORT_OVERRIDE
= ((nvram
['trunk_vlan_so'] == '1') ? 1 : 0);
853 <body onload='init()'
>
854 <form id='_fom' method='post' action='tomato.cgi'
>
855 <table id='container' cellspacing=
0>
856 <tr><td colspan=
2 id='header'
>
857 <div class='title'
>Tomato
</div>
858 <div class='version'
>Version <%
version(); %></div>
860 <tr id='body'
><td id='navi'
><script type='text/javascript'
>navi()</script></td>
862 <div id='ident'
><%
ident(); %></div>
863 <input type='hidden' name='_nextpage' value='advanced-vlan.asp'
>
864 <input type='hidden' name='_nextwait' value='
30'
>
865 <input type='hidden' name='_reboot' value='
1'
>
866 <input type='hidden' name='_nvset' value='
1'
>
867 <input type='hidden' name='_commit' value='
1'
>
868 <input type='hidden' name='vlan0ports'
>
869 <input type='hidden' name='vlan1ports'
>
870 <input type='hidden' name='vlan2ports'
>
871 <input type='hidden' name='vlan3ports'
>
872 <input type='hidden' name='vlan4ports'
>
873 <input type='hidden' name='vlan5ports'
>
874 <input type='hidden' name='vlan6ports'
>
875 <input type='hidden' name='vlan7ports'
>
876 <input type='hidden' name='vlan8ports'
>
877 <input type='hidden' name='vlan9ports'
>
878 <input type='hidden' name='vlan10ports'
>
879 <input type='hidden' name='vlan11ports'
>
880 <input type='hidden' name='vlan12ports'
>
881 <input type='hidden' name='vlan13ports'
>
882 <input type='hidden' name='vlan14ports'
>
883 <input type='hidden' name='vlan15ports'
>
884 <input type='hidden' name='vlan0hwname'
>
885 <input type='hidden' name='vlan1hwname'
>
886 <input type='hidden' name='vlan2hwname'
>
887 <input type='hidden' name='vlan3hwname'
>
888 <input type='hidden' name='vlan4hwname'
>
889 <input type='hidden' name='vlan5hwname'
>
890 <input type='hidden' name='vlan6hwname'
>
891 <input type='hidden' name='vlan7hwname'
>
892 <input type='hidden' name='vlan8hwname'
>
893 <input type='hidden' name='vlan9hwname'
>
894 <input type='hidden' name='vlan10hwname'
>
895 <input type='hidden' name='vlan11hwname'
>
896 <input type='hidden' name='vlan12hwname'
>
897 <input type='hidden' name='vlan13hwname'
>
898 <input type='hidden' name='vlan14hwname'
>
899 <input type='hidden' name='vlan15hwname'
>
900 <input type='hidden' name='wan_ifnameX'
>
901 <input type='hidden' name='manual_boot_nv'
>
902 <input type='hidden' name='lan_ifnames'
>
903 <input type='hidden' name='lan1_ifnames'
>
904 <input type='hidden' name='lan2_ifnames'
>
905 <input type='hidden' name='lan3_ifnames'
>
906 <input type='hidden' name='trunk_vlan_so'
>
907 <input type='hidden' name='vlan0vid'
>
908 <input type='hidden' name='vlan1vid'
>
909 <input type='hidden' name='vlan2vid'
>
910 <input type='hidden' name='vlan3vid'
>
911 <input type='hidden' name='vlan4vid'
>
912 <input type='hidden' name='vlan5vid'
>
913 <input type='hidden' name='vlan6vid'
>
914 <input type='hidden' name='vlan7vid'
>
915 <input type='hidden' name='vlan8vid'
>
916 <input type='hidden' name='vlan9vid'
>
917 <input type='hidden' name='vlan10vid'
>
918 <input type='hidden' name='vlan11vid'
>
919 <input type='hidden' name='vlan12vid'
>
920 <input type='hidden' name='vlan13vid'
>
921 <input type='hidden' name='vlan14vid'
>
922 <input type='hidden' name='vlan15vid'
>
924 <div id='sesdiv' style='display:none'
>
925 <div class='section-title'
>VLAN
</div>
926 <div class='section'
>
927 <table class='tomato-grid' cellspacing=
1 id='vlan-grid'
></table>
932 <div class='section-title'
>VID Offset
<small><i><a href='javascript:toggleVisibility(
"vidmap");'
><span id='sesdiv_vidmap_showhide'
>(Click here to show)
</span></a></i></small></div>
933 <div class='section' id='sesdiv_vidmap' style='display:none'
>
934 <script type='text/javascript'
>
935 createFieldTable('', [
936 { title
: 'First 802.1Q VLAN tag', name
: 'vlan0tag', type
: 'text', maxlen
:4, size
:6,
937 value
: fixInt(nvram
.vlan0tag
, 0, 4080, 0),
938 suffix
: ' <small><i>(range: 0 - 4080; must be a multiple of 16; set to 0 to disable)</i></small>' }
945 <div class='section-title'
>Wireless
<small><i><a href='javascript:toggleVisibility(
"wireless");'
><span id='sesdiv_wireless_showhide'
>(Click here to show)
</span></a></i></small></div>
946 <div class='section' id='sesdiv_wireless' style='display:none'
>
947 <script type='text/javascript'
>
949 for (var uidx
= 0; uidx
< wl_ifaces
.length
; ++uidx
) {
950 var u
= wl_fface(uidx
);
952 { title
: ('Bridge ' + wl_ifaces
[uidx
][0] + ' to'), name
: ('f_bridge_wlan'+u
+'_to'), type
: 'select',
953 options
: [[0,'LAN (br0)'],[1,'LAN1 (br1)'],[2,'LAN2 (br2)'],[3,'LAN3 (br3)'],[4,'none']], value
: 4 } );
955 createFieldTable('',f
);
956 if(port_vlan_supported
) vlg
.setup();
962 <div class='section-title'
>Notes
<small><i><a href='javascript:toggleVisibility(
"notes");'
><span id='sesdiv_notes_showhide'
>(Click here to show)
</span></a></i></small></div>
963 <div class='section' id='sesdiv_notes' style='display:none'
>
965 <li><b>VLAN
</b> - Unique identifier of a VLAN.
</li>
966 <li><b>VID
</b> -
<i>EXPERIMENTAL
</i> - Allows overriding 'traditional' VLAN/VID mapping with arbitrary VIDs for each VLAN (set to '
0' to use 'regular' VLAN/VID mappings instead). Warning: this hasn't been verified/tested on anything but a Cisco/Linksys E3000 and may not be supported by your particular device/model (
<small><b><i>see notes on
"VID Offset" below
</i></b></small>).
</li>
967 <li><b>Ports
1-
4 & WAN
</b> - Which ethernet ports on the router should be members of this VLAN.
</li>
968 <li><b>Tagged
</b> - Enable
802.1Q tagging of ethernet frames on a particular port/VLAN
969 <script type='text/javascript'
>
970 if(!trunk_vlan_supported
)
971 W(' <i><b>(unknown support for this model...contact the developper (Victek))</i></b>');
974 <li><b>Default
</b> - VLAN ID assigned to untagged frames received by the router.
</li>
975 <li><b>Bridge
</b> - Determines if this VLAN ID should be treated as WAN, part of a LAN bridge or just left alone (i.e. member of a
802.1Q trunk, being managed manually via scripts, etc...).
</li>
979 <li><b>VID Offset
</b> -
<i>EXPERIMENTAL
</i> - First
802.1Q VLAN tag to be used as
<i>base/initial tag/VID
</i> for VLAN and VID assignments. This allows using VIDs larger than
15 on (older) devices such as the Linksys WRT54GL v1.1 (in contiguous blocks/ranges with up to
16 VLANs/VIDs). Set to '
0' (zero) to disable this feature and VLANs will have the very same/identical value for its VID, as usual (from
0 to
15).
</li>
983 <li><b>Wireless
</b> - Assignments of wireless interfaces to different LAN briges. You should probably be using and/or check things on
<a href=advanced-wlanvifs.asp
>Advanced/Virtual Wireless
</a> and
<a href=basic-network.asp
>Basic/Network
</a>.
</li>
988 <li><b>Other relevant notes/hints:
</b>
990 <li>One VID
<i>must
</i> be assigned to WAN.
</li>
991 <li>One VID
<i>must
</i> be selected as the default.
</li>
992 <script type='text/javascript'
>
993 if((trunk_vlan_supported
) || (nvram
.trunk_vlan_so
== '1')) {
994 W('<li>To prevent 802.1Q compatibility issues, avoid using VID "0" as 802.1Q specifies that frames with a tag of "0" do not belong to any VLAN (the tag contains only user priority information).</li>');
995 W('<li>It may be also recommended to avoid using VID "1" as some vendors consider it special/reserved (for management purposes).</li>');
1001 <li>This is an
<b>experimental
</b> feature and hasn't been tested in anything but a Linksys WRT54GL v1.1 running a Teaman-ND K24 build and a Cisco/Linksys E3000 running a Teaman-RT K26 build.
</li>
1002 <li>There's lots of things that could go wrong, please do think about what you're doing and take a backup before hitting the 'Save' button on this page!
</li>
1005 <div id='trunk_vlan_override' style='display:none'
>
1006 <div class='section-title'
>Trunk VLAN support override (experimental)
</div>
1007 <div class='section'
>
1008 <script type='text/javascript'
>
1009 createFieldTable('', [
1010 { title
: 'Enable', name
: 'f_trunk_vlan_so', type
: 'checkbox', value
: nvram
.trunk_vlan_so
== '1' },
1019 <script type='text/javascript'
>
1020 if(!port_vlan_supported
)
1021 W('<i>This feature is not supported on this router.</i>');
1023 E('sesdiv').style
.display
= '';
1024 if(!trunk_vlan_supported
)
1025 E('trunk_vlan_override').style
.display
= '';
1029 <tr><td id='footer' colspan=
2>
1030 <span id='footer-msg'
></span>
1031 <input type='button' value='Save' id='save-button' onclick='save()'
>
1032 <input type='button' value='Cancel' id='cancel-button' onclick='javascript:reloadPage();'
>
1036 <script type='text/javascript'
>earlyInit(); verifyFields(null,1);</script>