Commit Graph
107 Commits
Author SHA1 Message Date
d00f 22a09bd06a l2: drop the comments and define the column list once
Review feedback on #307: these files are served from flash byte for byte,
so comments ride along on every page load. The three added in this branch
are gone, 357 bytes across l2.js and style.css. The column list existed in
three copies inside renderL2() and is now a single const.
2026-08-08 17:55:27 +02:00
d00f ccb90ed16f l2: refresh the type column when a row is reused
The paint loop reuses existing rows and rewrites port, MAC, VLAN and the
delete button, but never the type cell - only the insert path set it. With a
fixed row order that stayed invisible, since a row usually landed back where
it was. Sorting moves rows, so every other column followed the data while
type kept the previous row's value, which made sorting by type look broken
when the sort itself was correct.
2026-08-05 21:42:54 +02:00
d00f 4389cfcd8b l2: show which column sorts and in which direction
Clicking a heading sorted the table but nothing said so afterwards - the
only feedback was the rows moving, which is no help when the sort key is a
column you are not looking at.

Give every sortable heading a permanent marker: a neutral double arrow when
it is not the sort key, up or down when it is. The marker sits in its own
span so the i18n pass, which replaces the heading text, does not wipe it.
2026-08-05 21:35:54 +02:00
d00f 5e901fb5c2 l2: sort and filter the forwarding table from its header
The table lists every learned and static entry in one flat block, which is
fine with a handful and unusable with a few hundred: finding out where one
MAC sits, or what a port has learned, meant reading the whole thing.

Make the column headings sort and give each one a filter box. Filters are
substring matches combined with AND, so "port 8 + static" is two keystrokes.
A counter above the table shows matched out of total, so a filter that hides
everything is obvious rather than looking like an empty table.

Sorting keeps the CPU entry from comparing as a number - it sorts last
instead of landing between ports 8 and 9, where a string-vs-number compare
would otherwise put it.

The filter inputs live inside the existing header cells rather than in a
second row: the paint loop addresses data rows as rows[i+1], and a second
header row would have shifted every one of them.
2026-08-05 21:21:03 +02:00
d00f 2974e4b66a l2: stop labelling the SFP port as CPU
The port column was mapped from logical to physical numbering first and the
CPU label applied afterwards, testing for port 9. On an 8+1 board the SFP
port maps to physical 9 as well, so every entry learned on the SFP was shown
as CPU - on this switch that was 26 of 30 entries.

Label the CPU while the number is still logical, before the mapping, so the
two cannot collide.
2026-08-05 21:21:03 +02:00
d00f ed74ec1e97 httpd/login: complete CSP + password autocomplete hint
Two hygiene fixes for the web UI, prompted by a login that appeared to fail
under privacy shields (Brave Shields / NoScript-family extensions):

- httpd: replace the partial "style-src 'self' 'unsafe-inline'" CSP with a
  complete, first-party policy (default-src 'self'; script-src 'self'
  'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;
  connect-src 'self'; form-action 'self'). Everything the UI needs is
  same-origin; the explicit policy stops shields injecting their own
  restrictive report-only probes (the noisy script-src-elem 'none' console
  spam) and passes a strict-CSP audit. Verified: no CSP violations in-browser.
- login.html: add autocomplete="current-password" so password managers
  recognise the field (they showed "unknown password" without it).

NOTE: these do NOT bypass a browser's LAN-device protection (NoScript "lan" /
Brave Shields), which strips the POST body of requests to a LAN address and is
why the login can fail in-browser while the same credentials work over curl.
That is a deliberate browser security feature; the user must allow the site in
their shields to log in. The backend password (default 1234) is unchanged and
correct.
2026-07-21 06:47:10 +02:00
Your Name e765d17c2b feat: add language selection to system settings
Add a language selector to the System Settings page supporting English,
Japanese, and Chinese. The i18n dictionary already contained zh
translations but lacked the UI to switch languages.

Changes:
- html/i18n.js: add sys_language key to en/ja/zh
- html/system.html: add language selector dropdown
- html/system.js: add changeLang() and selector initialization
- tools/httpd_sim.c: fix cookie parsing for multi-cookie headers;
  fix Set-Cookie response (missing Path=/, missing \r\n\r\n);
  add SO_REUSEADDR for faster port reuse
2026-07-15 01:35:10 +09:00
logicog f86b8f32de Merge pull request #283 from Lynn-Becky/translate/chinese
Translate to Chinese
2026-07-13 07:15:52 +02:00
Your Name 519c3a8df3 fix: rename local variable to avoid shadowing global translation function 2026-07-10 13:09:41 +09:00
Lynn-Becky 64422367d5 feat(translate):translate to Chinese 2026-07-08 20:40:00 +08:00
Your Name fcf1b3c310 Fix: Remove the language-specific display logic. 2026-07-05 02:31:37 +09:00
Your Name e75a4c2a95 support i18n & translate japanese 2026-07-05 00:51:27 +09:00
Erdnusschokolade 4eaf16f96d Drop dead exact-match check in vlan delete filter
A bare "vlan N" line never matches conf_cmds (a VLAN entry always carries
a member port or the mgmt/name keyword), so it is never stored. The
c !== "vlan N" comparison could therefore never match an entry; the
startsWith(prefix) check alone covers all stored vlan lines.
2026-06-20 08:13:43 +02:00
Erdnusschokolade 718745e7b5 Reduce stale management VLAN entries on config save
The firmware has a single management VLAN (one management_vlan variable),
so a stored config should never carry more than one "vlan N mgmt" line.
When parsing a mgmt command, drop any previously stored mgmt entry so
repeatedly changing the management VLAN no longer accumulates stale lines.
2026-06-20 08:00:54 +02:00
Erdnusschokolade 06ee1ce38e Persist port speed settings in config parser
parseConf() only recognized "port N name" in conf_cmds, so "port N <speed>"
lines were treated as unknown commands and dropped on save - configured port
speeds never persisted.

Add the speed command (incl. optional half/full duplex suffix) to conf_cmds,
add a "port N" entry to conf_overwrite so re-saving a speed replaces the
previous value, and guard the per-port name entry so changing a port's speed
no longer wipes its configured name.
2026-06-18 14:49:56 +02:00
Erdnusschokolade 592b903305 Fix conf_overwrite filter removing vlan mgmt entries
The vlan/mgmt lookahead split (commit dcc60c3) correctly separated the
patterns so that `vlan N mgmt` and `vlan N <members>` match different
conf_overwrite entries. But the filter that applies the overwrite still
used `item.startsWith(matchStr + " ")` with matchStr = "vlan N", which
also matches "vlan N mgmt" — so the management entry was removed whenever
the VLAN's membership definition was re-saved.

Example: with both `vlan 44 management 2t 4t 5 6t` and `vlan 44 mgmt`
in the config, changing the membership dropped `vlan 44 mgmt` entirely.

Added a `!item.endsWith(" mgmt")` guard so management entries survive the
filter. No reordering is needed: `vlan N mgmt` only sets the global
management_vlan variable (cmd_parser.c) and does not depend on the VLAN
table entry existing, so its position in the config is irrelevant.
2026-06-02 22:52:06 +02:00
logicog 5a8a8ed91b Merge pull request #237 from Erdnusschokolade/fix/config-persistence
Fix config persistence: missing commands, delete handling, multipart upload
2026-06-01 06:46:11 +02:00
Erdnusschokolade dcc60c3824 Fix conf_overwrite vlan/mgmt conflict
The pattern /^vlan\s+\d{1,4}\b/ matched both VLAN membership entries
(vlan N <ports>) and management entries (vlan N mgmt), causing them
to overwrite each other in configuration[]. When saving, whichever
form came last in the cmd_log would dedupe the other out of the
final config — resulting in either lost membership or a stale mgmt
setting.

Split into two patterns using negative lookahead:
- /^vlan\s+\d{1,4}\s+mgmt$/      matches only mgmt entries
- /^vlan\s+\d{1,4}(?!\s+mgmt\b)/  matches everything else

Both dedup independently. Discovered via hardware test on 6XH-X
where 'vlan 44 mgmt' silently dropped 'vlan 44 management 2t 5u'
from saved config, locking out web UI on next boot.
2026-05-24 11:26:04 +02:00
Erdnusschokolade caad366b3b Fix config persistence: missing commands, delete handling, multipart
Multiple related bugs in the Save-to-Flash path:

1. Multipart upload was missing the required filename argument,
   causing the backend parser to fail. Added 'config.txt' to the
   form.append call. This was likely the primary reason Save-to-Flash
   was unreliable.

2. Web UI was not pausing its polling interval during flash write,
   causing CPU contention and intermittent crashes. Added isSaving
   lock and clearInterval before sendConfig.

3. conf_cmds whitelist was incomplete. Added: syslog, passwd, pvid,
   ingress, port name, lag, laghash, isolate, stp, igmp, mtu, bw,
   vlan N mgmt, vlan N d.

4. VLAN regex blocked named VLANs. New pattern allows optional name
   (starts with letter, matching CLI parser semantics).

5. vlan N d (delete) was not persisted. parseConf now removes the
   matching vlan N ... entry from configuration[] when seeing a
   delete command, without storing the delete itself. Result: the
   saved config describes the end state.

6. configuration[] was not cleared between flashSave invocations,
   leading to stale entries from prior interactions.

7. conf_overwrite boundary fix: 'pvid 1' no longer matches 'pvid 10'
   etc. Added trailing space in startsWith check.

8. All conf_cmds patterns now anchored with ^...$ for full-line
   match. parseConf normalizes whitespace before testing.

9. Port range widened to \d{1,2} so ports 11+ are accepted.

Structural fixes (1, 2, 6, 7, 8) ported from mcaptur's closed PR #219;
remaining fixes (3, 4, 5, 9) and overall regex strategy are new.
2026-05-24 11:26:04 +02:00
Erdnusschokolade ce0ee859d6 Fix: Untagged Ports column included non-member ports
The hardware bitmask format encodes both "untagged members" and
"non-members" in the upper 10 bits (per doc/vlan.md). The existing
fetchVLAN() correctly masks this with the membership bitmask before
display, but loadVlanTable() did not, causing non-member ports to
appear in the Untagged Ports column.

Tested on KeepLiNK KP-9000-6XH-X.
2026-05-24 11:20:57 +02:00
Erdnusschokolade a369e46fe6 Add VLAN overview table to VLAN configuration page
Below the configuration form, a new table lists all configured VLANs
with their port memberships: Member, Tagged, Untagged, and PVID
columns. Port ranges are formatted compactly (e.g. "1-2,5").

Port-to-bit mapping uses the existing physToLogPort[] array populated
by /status.json, so the table is consistent with the icon view in
fetchVLAN() and works on any supported machine.

Each row has a delete button that sends "vlan N d" via /cmd, with
a confirmation dialog. VLAN 1 cannot be deleted (no button shown).

Table and dropdown both refresh automatically after Update/Create
and after delete via a new refreshVlanViews() helper.

The N+1 request pattern (1x /vlanlist + Nx /vlan.json) keeps the
backend simple and avoids buffer overflow risks for systems with
many VLANs. For typical configurations (<50 VLANs), page load
remains under one second.
2026-05-24 11:20:57 +02:00
Erdnusschokolade defb37c06a Add VLAN selector dropdown to VLAN configuration page
A new <select> element above the VLAN ID input lets users pick an
existing VLAN by name instead of typing the ID. Options are loaded
from /vlanlist on page load and re-loaded after successful
Update/Create operations.

Selection triggers the existing fetchVLAN() flow.

Falls back gracefully if /vlanlist returns an empty list or fails:
the dropdown is hidden and the existing ID input remains functional.
2026-05-24 11:20:57 +02:00
UAb5eSMn 2316ffd493 Support for executing multiple commands via /cmd 2026-05-15 13:27:09 +02:00
René van Dorst 09d90d6d97 Merge pull request #175 from logicog/ZX310S-4T2XH
10GBit Ethernet Switch support (Horaco ZX310S-4T2XH)
2026-05-02 17:22:52 +00:00
logicog 7877ce60f3 Add support for 5G link speeds, make 5G/10G LED blue 2026-04-24 10:53:05 +02:00
feelfree69 f7989cc737 Merge branch 'logicog:main' into syslog 2026-04-21 14:29:44 +02:00
feelfree69 2565aeadf4 Do no show empty names in tooltips 2026-04-14 18:28:13 +02:00
feelfree69 41f0dad49d Add ability to assign a name to a port 2026-04-13 14:55:10 +02:00
feelfree69 c91177d992 Web-If: Add Console-Cmd input 2026-04-12 13:02:42 +02:00
Jan Hoffmann 05693f5171 Also show SFP TX/RX power in dBm 2026-03-29 00:33:48 +01:00
Jan Hoffmann 6eaa1985aa Fix SFP diagnostic monitoring data in web interface
If the module is not internally calibrated, it is necessary to apply
calibration values to get meaningful results.
2026-03-29 00:33:48 +01:00
Jan Hoffmann 45ba32f65d Fix scaling for power values in SFP diagnostics 2026-03-29 00:33:48 +01:00
logicog fce64ac368 Fix display of VLANs for ports 2026-03-22 13:45:42 +01:00
logicog d21d269d49 Merge pull request #152 from mmmspatz/mspatz/fix_vlan_page
Fix "Get Configuration" on vlan.html
2026-03-19 11:36:59 +01:00
logicog 59e7a21955 Merge pull request #159 from diijkstra/web_sfp_state
Web: Add SFP state/pin status
2026-03-19 05:22:24 +01:00
logicog 090283d538 Add retry mechanism for xhttp requests to make Chrome happy 2026-03-16 17:32:50 +01:00
diijkstra b47a868db3 Web: Handle missing LOS pin
When device has no LOS pin and module has no extended status, the
RX LOS value will not be shown. When both are present, the equality
check is performed. When only one is present, the present value
will be shown.

json from the switch, will still contain the field, but can be
null for when pin is not available.
2026-03-15 12:18:02 +01:00
diijkstra 6b64534f40 WEB: Display single RX LOS
As sugested, lets display single value, and raise alarm when pin
is different than module.
2026-03-14 13:15:01 +01:00
diijkstra 1f6e07a1af Web: Add SFP state/pin status
The state of the SFP module is being already send in status.json,
but was not parsed via Web UI. When debuging SFP LOS/Signal detection
it is usefull to see what module is reporting back.

Extended the SFP mouse-over information with:
 - RX LOS as reported in 0x02 bit of register 238
 - External TX Disabled from 0x80 bit of register 238
 - TX fault from 0x04 of the same register
 - The last state of RX LOS pin (available also when there is no 0x40
   option on the module)

This should help identify missing/incorrect setup of TX disabled pin.
2026-03-13 23:56:43 +01:00
logicog fa37940075 Control xhttp concurrency 2026-03-10 06:16:18 +01:00
Mark H. Spatz 364d538abd Fix "VLAN ID" field max value on vlan.html 2026-03-08 17:50:54 -04:00
logicog 20fb626cc1 Make bandwidth control page accessible 2026-03-08 20:55:50 +01:00
logicog 31a488e4e9 Add web page for bandwidth control 2026-03-08 20:55:50 +01:00
Mark H. Spatz 4cef63200f Fix "Get Configuration" on vlan.html
I noticed that entering some vlan config, clicking "Update/Create", then
clicking "Get Configuration" resulted in Tagged/Untagged/PVID displaying
completely wrong data. It looks like the parisng in fetchVLAN() in
vlan.js was just completely disconnected from the layout of the
registers read by vlan_get() in rtl837x_port.c. Who knows how that
happened.

1. Fix fetchVLAN() member/untag parsing: the old code read bits [9:0]
   as untagged and bits [10:19] as tagged, but the VLAN table register
   layout is members in [9:0] and untag in [19:10]. Now correctly
   derives tagged (member && !untag) and untagged (member && untag).

2. Add PVID to vlan.json response: PVID is stored per-port in separate
   PVID registers (RTL837x_PVID_BASE_REG), not in the VLAN table entry.
   The old code nonsensically tried to read it from bits [20:29] of the
   VLAN table. Add port_pvid_get() and build a pvid bitmask in
   send_vlan() so the JS can parse it correctly.

3. Remove auto-PVID logic from setC(): setC() is called by fetchVLAN()
   while it's loading existing config, and so this logic mangled the
   display of the existing config. Also, it doesn't make sense to
   auto-set the PVID for tagged members (PVID relates to untagged
   ingress.)
2026-03-07 15:18:06 -05:00
chriz 0e2a5fb7bc Reload startup config after save. 2026-02-14 11:02:05 +01:00
chriz d5019b41df Add warning for advanced safe. 2026-02-13 10:32:23 +01:00
chriz eae7f10d7a Make Advanced configuration tabbed. 2026-02-13 08:43:48 +01:00
chriz ea37126e87 New apporach: Make startup config independent. 2026-02-12 14:17:22 +01:00
TylerDurden-23 1d91c1bf2c Merge branch 'logicog:main' into opt-system-settings 2026-02-11 21:15:56 +01:00
chriz 0099c2a03a Fix no 10Mbit link speed shown. Determine link state and speed seperately. Additional handling for port > 8. 2026-02-09 20:16:57 +01:00