system: pick the management VLAN from System Settings

`vlan <id> mgmt` existed on the CLI, but nothing reported which VLAN
currently carries management, so the setting was invisible from the web UI -
the only way to find out was to read the startup config.

Report it in information.json and offer it where the other switch-wide
addressing settings live, between Gateway and Language, as a picker filled
from the configured VLANs. When management is untagged there is no VLAN to
select, so that state shows as a disabled entry rather than inventing an id
the switch would reject.

Confirm before applying, and say what will happen rather than echoing the
action back: the switch starts tagging its own frames, and if the port you
came in on does not carry that VLAN the page becomes unreachable and the way
back is the console. Cancelling puts the picker back where it was.
This commit is contained in:
d00f
2026-08-08 18:26:49 +02:00
parent 23f0ba995c
commit 1a55a134c7
4 changed files with 64 additions and 2 deletions
+12
View File
@@ -144,6 +144,10 @@ var LANG = {
sys_netmask: 'Netmask:', sys_netmask: 'Netmask:',
sys_gateway: 'Gateway:', sys_gateway: 'Gateway:',
sys_language: 'Language:', sys_language: 'Language:',
sys_mgmt_vlan: 'Management VLAN:',
sys_mgmt_untagged: 'untagged',
sys_mgmt_confirm: 'Move switch management to VLAN ',
sys_mgmt_warn: 'The switch will start tagging its own traffic with that VLAN. If the port you are connected through does not carry it, this page becomes unreachable and the setting can only be undone over the console. Continue?',
sys_ip_note: 'When updating the above settings, remember to point your browser to the new IP afterwards:', sys_ip_note: 'When updating the above settings, remember to point your browser to the new IP afterwards:',
sys_update: 'Update Settings', sys_update: 'Update Settings',
sys_save_label: 'Save all current settings to Flash:', sys_save_label: 'Save all current settings to Flash:',
@@ -326,6 +330,10 @@ var LANG = {
sys_netmask: 'ネットマスク:', sys_netmask: 'ネットマスク:',
sys_gateway: 'ゲートウェイ:', sys_gateway: 'ゲートウェイ:',
sys_language: '言語:', sys_language: '言語:',
sys_mgmt_vlan: 'Management VLAN:',
sys_mgmt_untagged: 'untagged',
sys_mgmt_confirm: 'Move switch management to VLAN ',
sys_mgmt_warn: 'The switch will start tagging its own traffic with that VLAN. If the port you are connected through does not carry it, this page becomes unreachable and the setting can only be undone over the console. Continue?',
sys_ip_note: '上記設定を変更した場合は、ブラウザで新しい IP にアクセスしてください:', sys_ip_note: '上記設定を変更した場合は、ブラウザで新しい IP にアクセスしてください:',
sys_update: '設定更新', sys_update: '設定更新',
sys_save_label: '現在の設定をフラッシュに保存:', sys_save_label: '現在の設定をフラッシュに保存:',
@@ -508,6 +516,10 @@ var LANG = {
sys_netmask: '子网掩码:', sys_netmask: '子网掩码:',
sys_gateway: '网关:', sys_gateway: '网关:',
sys_language: '语言:', sys_language: '语言:',
sys_mgmt_vlan: 'Management VLAN:',
sys_mgmt_untagged: 'untagged',
sys_mgmt_confirm: 'Move switch management to VLAN ',
sys_mgmt_warn: 'The switch will start tagging its own traffic with that VLAN. If the port you are connected through does not carry it, this page becomes unreachable and the setting can only be undone over the console. Continue?',
sys_ip_note: '更新上述设置后,请使用新的 IP 地址重新访问管理界面:', sys_ip_note: '更新上述设置后,请使用新的 IP 地址重新访问管理界面:',
sys_update: '更新设置', sys_update: '更新设置',
sys_save_label: '将当前全部设置保存到 Flash:', sys_save_label: '将当前全部设置保存到 Flash:',
+5 -1
View File
@@ -32,7 +32,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="lcol"> <label data-i18n="sys_model">Model:</label></div> <div class="lcol"> <label data-i18n="sys_model">Model:</label></div>
<div class="rcol"><span id="model"></span></div> <div class="rcol"><span id="model" class="rotext"></span></div>
</div> </div>
<div class="row"> <div class="row">
<div class="lcol"> <label for="ip" data-i18n="sys_ip">IP address:</label></div> <div class="lcol"> <label for="ip" data-i18n="sys_ip">IP address:</label></div>
@@ -46,6 +46,10 @@
<div class="lcol"> <label for="gw" data-i18n="sys_gateway">Gateway:</label></div> <div class="lcol"> <label for="gw" data-i18n="sys_gateway">Gateway:</label></div>
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div> <div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div> </div>
<div class="row">
<div class="lcol"> <label for="mgmtvlan" data-i18n="sys_mgmt_vlan">Management VLAN:</label></div>
<div class="rcol"><select id="mgmtvlan" class="ip" onchange="mgmtVlanChanged()"></select></div>
</div>
<div class="row"> <div class="row">
<div class="lcol"> <label data-i18n="sys_language">Language:</label></div> <div class="lcol"> <label data-i18n="sys_language">Language:</label></div>
<div class="rcol"> <div class="rcol">
+42
View File
@@ -133,6 +133,7 @@ function fetchIP() {
document.getElementById("gw").value=s.ip_gateway; document.getElementById("gw").value=s.ip_gateway;
document.getElementById("hostname").value=s.hostname; document.getElementById("hostname").value=s.hostname;
document.getElementById("model").textContent=s.hw_ver; document.getElementById("model").textContent=s.hw_ver;
loadMgmtVlan(parseInt(s.mgmt_vlan, 10) || 0);
clearInterval(systemInterval); clearInterval(systemInterval);
// Fetch and populate the config textbox // Fetch and populate the config textbox
fetchConfig().then((configText) => { fetchConfig().then((configText) => {
@@ -165,3 +166,44 @@ window.addEventListener("load", function() {
if (langSel) langSel.value = rtlLang; if (langSel) langSel.value = rtlLang;
systemInterval = setInterval(fetchIP, 1000); systemInterval = setInterval(fetchIP, 1000);
}); });
var mgmtVlanCurrent = 0;
/* Populate the management-VLAN picker from the configured VLANs. If management
* is untagged there is no VLAN to select, so show that as a disabled entry
* rather than inventing an id the switch would reject. */
function loadMgmtVlan(cur) {
var sel = document.getElementById('mgmtvlan');
if (!sel) return;
mgmtVlanCurrent = cur;
fetch('/vlanlist').then(function(r) { return r.json(); }).then(function(list) {
sel.innerHTML = '';
if (!cur) {
var none = document.createElement('option');
none.value = 0; none.disabled = true;
none.textContent = t('sys_mgmt_untagged');
sel.appendChild(none);
}
for (var i = 0; i < list.length; i++) {
var o = document.createElement('option');
o.value = list[i].id;
o.textContent = list[i].name ? (list[i].id + ' (' + list[i].name + ')') : list[i].id;
sel.appendChild(o);
}
sel.value = cur;
}).catch(function(err) { console.error('VLAN list failed:', err); });
}
function mgmtVlanChanged() {
var sel = document.getElementById('mgmtvlan');
var id = parseInt(sel.value, 10);
if (!id || id === mgmtVlanCurrent) return;
if (!confirm(t('sys_mgmt_confirm') + id + '.\n\n' + t('sys_mgmt_warn'))) {
sel.value = mgmtVlanCurrent;
return;
}
fetch('/cmd', { method: 'POST', body: 'vlan ' + id + ' mgmt' })
.then(function() { mgmtVlanCurrent = id; })
.catch(function(err) { console.error('Set management VLAN failed:', err); sel.value = mgmtVlanCurrent; });
}
+5 -1
View File
@@ -26,6 +26,7 @@
extern __code const struct machine machine; extern __code const struct machine machine;
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
extern __xdata uint16_t slen; extern __xdata uint16_t slen;
extern __xdata uint16_t management_vlan;
extern __xdata uint16_t cont_len; extern __xdata uint16_t cont_len;
extern __xdata uint32_t cont_addr; extern __xdata uint32_t cont_addr;
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
@@ -264,7 +265,10 @@ void send_basic_info(void)
slen += strtox(outbuf + slen, BUILD_DATE); slen += strtox(outbuf + slen, BUILD_DATE);
slen += strtox(outbuf + slen, "\",\"hw_ver\":\""); slen += strtox(outbuf + slen, "\",\"hw_ver\":\"");
slen += strtox(outbuf + slen, machine.machine_name); slen += strtox(outbuf + slen, machine.machine_name);
slen += strtox(outbuf + slen, "\",\"flash_size\":\""); /* VLAN carrying switch management, 0 = untagged. */
slen += strtox(outbuf + slen, "\",\"mgmt_vlan\":");
itoa16_html(management_vlan);
slen += strtox(outbuf + slen, ",\"flash_size\":\"");
string_to_html(get_flash_size_str()); string_to_html(get_flash_size_str());
if (machine.n_sfp) { if (machine.n_sfp) {