mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
Compare commits
31
Commits
8224b06f9e
...
a202842107
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a202842107 | ||
|
|
6fad2836ae | ||
|
|
2415015a87 | ||
|
|
d9fc20addf | ||
|
|
c15b2d48da | ||
|
|
f17ca1c9fc | ||
|
|
be5dee04e3 | ||
|
|
496ac8b757 | ||
|
|
bf670aed0b | ||
|
|
6af5580433 | ||
|
|
6194356f66 | ||
|
|
bd56c1a8c5 | ||
|
|
d562fd661e | ||
|
|
0b6b613c03 | ||
|
|
f325bdbd11 | ||
|
|
adecc26ae2 | ||
|
|
44ae7a8d3b | ||
|
|
c3fc541339 | ||
|
|
28ea2184c2 | ||
|
|
d5f84cc2fb | ||
|
|
682ac462c4 | ||
|
|
ecc8356f4d | ||
|
|
3a8d1d323f | ||
|
|
e125ebd097 | ||
|
|
4050555667 | ||
|
|
e890e429a5 | ||
|
|
813a62ca7d | ||
|
|
8a7c847ad9 | ||
|
|
b94d2aeabc | ||
|
|
0e85137e7a | ||
|
|
706dea63a2 |
No files matched your search
@@ -99,6 +99,7 @@ SRCS = \
|
|||||||
# RTL837x
|
# RTL837x
|
||||||
SRCS += \
|
SRCS += \
|
||||||
rtl837x_bandwidth.c \
|
rtl837x_bandwidth.c \
|
||||||
|
rtl837x_cabletest.c \
|
||||||
rtl837x_flash.c \
|
rtl837x_flash.c \
|
||||||
rtl837x_igmp.c \
|
rtl837x_igmp.c \
|
||||||
rtl837x_init.c \
|
rtl837x_init.c \
|
||||||
|
|||||||
@@ -103,24 +103,29 @@ docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
|
|||||||
tools/output/httpd_sim /workspace/html
|
tools/output/httpd_sim /workspace/html
|
||||||
```
|
```
|
||||||
|
|
||||||
Edit `machine.h` or `config.txt` on your host, then re-run `make` — the
|
Edit `config.txt` on your host, then re-run `make` — the
|
||||||
source directory is mounted into the container, so changes take effect
|
source directory is mounted into the container, so changes take effect
|
||||||
immediately. To build for a different machine, pass `MACHINE=...`.
|
immediately. To build for a different machine, pass `MACHINE=<name>`, which
|
||||||
|
selects `machine/<name>.c` (see [Adding a new device](doc/adding-a-device.md)).
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
## (1) Compiling for direct chip flashing AND upgrading an existing RTLPlayground running device
|
||||||
|
|
||||||
Edit machine.h with an editor like vi or nano. Select the correct machine the firmware should build for.
|
Pass the machine that matches your device, for example:
|
||||||
|
```
|
||||||
|
make MACHINE=DEFAULT_8C_1SFP
|
||||||
|
```
|
||||||
|
The name selects the board definition `machine/<name>.c`; `make` without a
|
||||||
|
`MACHINE` value stops with an error listing what is expected. If your board is
|
||||||
|
not in the list yet, see [Adding a new device](doc/adding-a-device.md).
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> You can write configuration parameters in config.txt (see below) in order your switch to get
|
> You can write configuration parameters in config.txt (see below) in order your switch to get
|
||||||
> straight at the first boot, a correct IP configuration.
|
> straight at the first boot, a correct IP configuration.
|
||||||
|
|
||||||
Now, building the firmware image should work:
|
Now, building the firmware image should work.
|
||||||
```
|
|
||||||
make
|
|
||||||
```
|
|
||||||
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
|
Note, that the image generated ends in .bin, not .img, in order to make IMSProg happy.
|
||||||
|
|
||||||
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
|
image location is stored in `RTLPlayground/output/rtlplayground_version_machine.bin`
|
||||||
@@ -353,6 +358,7 @@ Enjoy playing!
|
|||||||
## (11) Other documents
|
## (11) Other documents
|
||||||
|
|
||||||
The following documents give further documentation on specific features of the RTL837x SoCs:
|
The following documents give further documentation on specific features of the RTL837x SoCs:
|
||||||
|
- [Adding a new device](doc/adding-a-device.md)
|
||||||
- [RTL8372/3 Feature support](doc/hardware.md)
|
- [RTL8372/3 Feature support](doc/hardware.md)
|
||||||
- [CPU Port](doc/CpuPort.md)
|
- [CPU Port](doc/CpuPort.md)
|
||||||
- [L2 learning](doc/l2.md)
|
- [L2 learning](doc/l2.md)
|
||||||
|
|||||||
+14
-2
@@ -20,6 +20,7 @@
|
|||||||
#include "rtl837x_lldp.h"
|
#include "rtl837x_lldp.h"
|
||||||
#include "rtl837x_storm.h"
|
#include "rtl837x_storm.h"
|
||||||
#include "rtl837x_trap.h"
|
#include "rtl837x_trap.h"
|
||||||
|
#include "rtl837x_cabletest.h"
|
||||||
#include "sfp.h"
|
#include "sfp.h"
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "syslog.h"
|
#include "syslog.h"
|
||||||
@@ -166,10 +167,15 @@ uint8_t atoi_hex(uint8_t idx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (h_idx == 8) {
|
||||||
|
h_idx = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// swap hex nibbles
|
// swap hex nibbles
|
||||||
val = (val >> 4) | (val << 4);
|
val = (val >> 4) | (val << 4);
|
||||||
|
|
||||||
if (c - '0' < 10) {
|
if ((uint8_t)(c - '0') < 10) {
|
||||||
val |= c - '0';
|
val |= c - '0';
|
||||||
} else {
|
} else {
|
||||||
c |= 0x20;
|
c |= 0x20;
|
||||||
@@ -903,6 +909,7 @@ void parse_port(void)
|
|||||||
"\nport <port> [show|on|off]" \
|
"\nport <port> [show|on|off]" \
|
||||||
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
|
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
|
||||||
"\nport <port> lldp [block|permit]" \
|
"\nport <port> lldp [block|permit]" \
|
||||||
|
"\nport <port> cabletest [show]" \
|
||||||
"\nport <port> name [custom port name]\n");
|
"\nport <port> name [custom port name]\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -945,6 +952,11 @@ void parse_port(void)
|
|||||||
}
|
}
|
||||||
} else if (machine.is_sfp[phy_settings.port]) {
|
} else if (machine.is_sfp[phy_settings.port]) {
|
||||||
print_string(" is SFP no PHY information available.\n");
|
print_string(" is SFP no PHY information available.\n");
|
||||||
|
} else if (cmd_compare(2, "cabletest")) {
|
||||||
|
if (cmd_words_len > 3 && cmd_compare(3, "show"))
|
||||||
|
cabletest_show();
|
||||||
|
else
|
||||||
|
cabletest_run();
|
||||||
} else if (cmd_compare(2, "10m")) {
|
} else if (cmd_compare(2, "10m")) {
|
||||||
print_string(" 10M\n");
|
print_string(" 10M\n");
|
||||||
phy_settings.speed = PHY_SPEED_10M;
|
phy_settings.speed = PHY_SPEED_10M;
|
||||||
@@ -2143,7 +2155,7 @@ void execute_config(void) __banked
|
|||||||
skipping = 1;
|
skipping = 1;
|
||||||
}
|
}
|
||||||
c = flash_buf[cfg_idx++];
|
c = flash_buf[cfg_idx++];
|
||||||
if (c == 0 || c == '\n') {
|
if (c == 0 || c == '\n' || c == '\r') {
|
||||||
if (skipping) {
|
if (skipping) {
|
||||||
skipping = 0;
|
skipping = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
# Adding a new device
|
||||||
|
|
||||||
|
A device is supported by adding one board definition `.h` and board configuration `.c` file
|
||||||
|
under `machine/`.
|
||||||
|
the build selects the definition by name, and CI compiles every file it finds.
|
||||||
|
|
||||||
|
To compile for your added device, do:
|
||||||
|
```
|
||||||
|
make MACHINE=<NAME>
|
||||||
|
```
|
||||||
|
|
||||||
|
## What a new device consists of
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `machine/<NAME>.c` | the `struct machine machine` board definition |
|
||||||
|
| `machine/<NAME>.h` | `MACHINE_MODEL`, the model string shown in the UI and the CLI |
|
||||||
|
| `doc/devices/<name>.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation |
|
||||||
|
|
||||||
|
`<NAME>` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is
|
||||||
|
passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0`
|
||||||
|
needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`.
|
||||||
|
|
||||||
|
## Step 1: the model header
|
||||||
|
|
||||||
|
`machine/<NAME>.h` only carries the product string. Use the existing files as
|
||||||
|
the template:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#ifndef _MACHINE_MY_BOARD_1_0_H_
|
||||||
|
#define _MACHINE_MY_BOARD_1_0_H_
|
||||||
|
|
||||||
|
#define MACHINE_MODEL "Brand Model V1.0"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> `machine_name` is a `char[30]` and `MACHINE_MODEL` is copied into it at
|
||||||
|
> compile time. A longer model string still builds, but SDCC emits
|
||||||
|
> `warning 147: excess elements in array of chars initializer` and the name is
|
||||||
|
> truncated in the UI. Keep it to 29 characters or less.
|
||||||
|
|
||||||
|
## Step 2: the board definition
|
||||||
|
|
||||||
|
`machine/<NAME>.c` starts with the shared prelude and then defines the single
|
||||||
|
`machine` object. Copy the closest existing board and adjust it — do not start
|
||||||
|
from a blank file, the field meanings are easier to see in a real example.
|
||||||
|
The best choice is usually a device that has the same number and type of Ethernet
|
||||||
|
ports and the same number of SFP+ cages.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "machine_defs.h"
|
||||||
|
|
||||||
|
__code const struct machine machine = {
|
||||||
|
.machine_name = MACHINE_MODEL,
|
||||||
|
.isRTL8373 = 1,
|
||||||
|
.min_port = 0,
|
||||||
|
.max_port = 8,
|
||||||
|
.n_sfp = 1,
|
||||||
|
.log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||||
|
.phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
|
.is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
|
||||||
|
.sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN,
|
||||||
|
.sfp_port[0].pin_los = GPIO37,
|
||||||
|
.sfp_port[0].pin_tx_disable = GPIO_NA,
|
||||||
|
.sfp_port[0].sds = 1,
|
||||||
|
.sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ),
|
||||||
|
.reset_pin = GPIO_NA,
|
||||||
|
|
||||||
|
.high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 },
|
||||||
|
.port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
|
.led_sets = {
|
||||||
|
{ /* RJ45 ports */
|
||||||
|
LEDS_2G5 | LEDS_LINK,
|
||||||
|
LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
}, { /* SFP port, single green LED */
|
||||||
|
LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
| Field | Meaning |
|
||||||
|
|-------|---------|
|
||||||
|
| `machine_name` | always `MACHINE_MODEL` |
|
||||||
|
| `isRTL8373` | `1` for an RTL8373 SoC, `0` for RTL8372 |
|
||||||
|
| `min_port` / `max_port` | range of logical port numbers the device has; `min_port` is `0` for RTL8373 boards and `3` for RTL8372 boards (logical ports 1–2 are the SoC's internal ports on the 8372), `max_port` is usually 8. |
|
||||||
|
| `n_sfp` | number of SFP+ cages |
|
||||||
|
| `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes |
|
||||||
|
| `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number |
|
||||||
|
| `phys_to_log_port[9]` | the inverse, physical port 1 is index 0, unused slots are 0 |
|
||||||
|
| `is_sfp[9]` | `0` for copper, `1` for left slot and `2` for right slot |
|
||||||
|
| `sfp_port[2]` | per-cage wiring, `sfp_port[0]` is the leftmost cage |
|
||||||
|
| `reset_pin` | GPIO of the reset button, `GPIO_NA` if unpopulated |
|
||||||
|
| `high_leds` | mux/enable for the LED pins 27–29 (`LED_27`, `LED_28_SYS`, `LED_29`) |
|
||||||
|
| `port_led_set[9]` | which LED set (0–3) each logical port uses |
|
||||||
|
| `led_sets[4][4]` | Each port can have up to 4 GPIO output pins assigned. 4 sets of LEDs with 4 LED-conditions per set; the conditions define which GPIO pins become active for a port given a port link-state. Which LEDs are then enabled depends on the wiring of the pins to up to 3 LEDs for that port, which can make a logical combination of the 4 LED output-pins. |
|
||||||
|
| `led_mux_custom` / `led_mux[28]` | `1` plus the 28 mux values when the stock LED muxing does not fit the board |
|
||||||
|
| `mac_flash_offset` | flash offset of the factory MAC address, omit or `0` if the board does not store one |
|
||||||
|
|
||||||
|
Each `struct sfp_port` entry holds `pin_detect`, `pin_los`, `pin_tx_disable`,
|
||||||
|
`sds` (which SerDes drives the cage) and `i2c` (built with `I2CBUS(sda, scl)`,
|
||||||
|
or `GPIO_NA`-based values where a cage has no such pin).
|
||||||
|
|
||||||
|
`I2CBUS(...)` only accepts the pin pairs listed in `machine_defs.h`. A wrong
|
||||||
|
pair is caught at compile time: SDCC reports
|
||||||
|
`error 176: sizeof applied to an incomplete type` pointing at the offending
|
||||||
|
`.i2c` line, because the macro deliberately turns an invalid bus number into an
|
||||||
|
array of size 0.
|
||||||
|
|
||||||
|
### Reusing an existing definition
|
||||||
|
|
||||||
|
If the new board is electrically identical to one that already exists — same
|
||||||
|
port mapping, same SFP wiring, same LEDs — do not copy the file. Make the new
|
||||||
|
`.c` a symlink and keep only a distinct `.h`, so the two boards cannot drift
|
||||||
|
apart:
|
||||||
|
|
||||||
|
```
|
||||||
|
ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c
|
||||||
|
```
|
||||||
|
|
||||||
|
The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on the PCB) with its own
|
||||||
|
`MACHINE_MODEL`, because `MACHINE_MODEL` is what distinguishes the products.
|
||||||
|
Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c`
|
||||||
|
and the six `KP_9000_*` revision variants.
|
||||||
|
|
||||||
|
Two files that differ only in whitespace or comments are duplicates and should
|
||||||
|
be collapsed this way.
|
||||||
|
|
||||||
|
## Step 3: build and verify
|
||||||
|
|
||||||
|
```
|
||||||
|
make MACHINE=MY_BOARD_1_0
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated flash image appears as `output/rtlplayground-<version>-MY_BOARD_1_0.bin`. An
|
||||||
|
unknown or empty `MACHINE` fails immediately with a message naming the expected
|
||||||
|
file, before anything is compiled.
|
||||||
|
|
||||||
|
Then run the checks CI runs:
|
||||||
|
|
||||||
|
```
|
||||||
|
make machine_check # compiles machine/<NAME>.c and machine_init.c for every machine
|
||||||
|
make -C test # host-side unit tests
|
||||||
|
```
|
||||||
|
|
||||||
|
`make machine_check` discovers the definitions with
|
||||||
|
`$(wildcard machine/*.c)`, so a new file is covered without registering it
|
||||||
|
anywhere. CI (`.github/workflows/build.yml`) runs it on every push and pull
|
||||||
|
request, alongside full builds for a 4+2 and an 8+1 board.
|
||||||
|
|
||||||
|
A successful compile only proves the definition is syntactically valid. The
|
||||||
|
actual behaviour — port numbering, SFP detection, LEDs — has to be confirmed on
|
||||||
|
hardware, and the console commands (`port`, `stat`, `sfp`, `leds`) are the
|
||||||
|
tools for that.
|
||||||
|
|
||||||
|
## Step 4: documentation
|
||||||
|
|
||||||
|
Once the board has been tested on hardware:
|
||||||
|
|
||||||
|
1. Add a row to the table in [Supported devices](supported_devices.md).
|
||||||
|
2. Add `doc/devices/<name>.md` describing the board, the build target
|
||||||
|
(`make MACHINE=MY_BOARD_1_0`), what works and what is unverified, plus
|
||||||
|
photos and the PCB silkscreen marking.
|
||||||
|
3. If the board shares a PCB with other revisions, follow
|
||||||
|
`doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for
|
||||||
|
which silkscreen.
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ The original web interface reports this board as hardware version V3.2
|
|||||||
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
|
The component placement matches [2M-PCB23-V3.1](2M-PCB23-V3_1.md): same
|
||||||
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
|
positions for the flash (U8), the T7/T8/T9/T10 headers, the SFP cage and its
|
||||||
LED, and the unpopulated U7/U9 footprints. Build with
|
LED, and the unpopulated U7/U9 footprints. Build with
|
||||||
`MACHINE=KP_9000_9XHML_X_V3_2`, which uses the V3.1 machine definition and
|
`make MACHINE=KP_9000_9XHML_X_V3_2`, whose board file is a symlink to the V3.1
|
||||||
only differs in the reported name.
|
definition and only differs in the reported name.
|
||||||
|
|
||||||
## Tested
|
## Tested
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ and sold by Mokerlink.
|
|||||||
The device is fully supported:
|
The device is fully supported:
|
||||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||||
- The SFP+ port supports 1G, 2.5G and 10G modules
|
- The SFP+ port supports 1G, 2.5G and 10G modules
|
||||||
- LEDs work with the same indiciations as the OEM firmware (use KP_9000_6XHML_X2_V1_1 in machine.h if building yourself or the corresponding pre-compiled binary)
|
- LEDs work with the same indiciations as the OEM firmware (build with `make MACHINE=KP_9000_6XHML_X2_V1_1` if building yourself, or use the corresponding pre-compiled binary)
|
||||||
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
- untested due to missing Hardware: SFP+ ports equipped with 1G or 2.5G SFPs.
|
||||||
|
|
||||||
### Hardware overview
|
### Hardware overview
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO
|
|||||||
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
|Brand|Type|Managed|PCB|Flash|Chip RTL|
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
|
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
|
||||||
|
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | ??? |
|
||||||
|
|
||||||
### Label specifications
|
### Label specifications
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
## RTLPlayground target
|
## RTLPlayground target
|
||||||
|
|
||||||
Use machine target `MACHINE_LIANGUO_ZX_SWTGW215AS` for this device.
|
Build for this device with `make MACHINE=LIANGUO_ZX_SWTGW215AS`, which selects the `machine/LIANGUO_ZX_SWTGW215AS.c` board definition.
|
||||||
|
|
||||||
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
|
Physical hardware verification: 5x RJ45 ports + 1x SFP port.
|
||||||
Port 5 RJ45 is interfaced through a RTL8221B IC.
|
Port 5 RJ45 is interfaced through a RTL8221B IC.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ The following devices have been tested and are fully working:
|
|||||||
| FOXNEO | FNS-1200P | No | [PCB-K0402W-U13-V2.0](devices/FNS-1200P.md) | 2M | 4 + 2 |
|
| FOXNEO | FNS-1200P | No | [PCB-K0402W-U13-V2.0](devices/FNS-1200P.md) | 2M | 4 + 2 |
|
||||||
| Goalake | IG108 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
|
| Goalake | IG108 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 |
|
||||||
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | ? | 8 + 1 |
|
| GoodTop | GT-ST018M | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | ? | 8 + 1 |
|
||||||
|
| GoodTop | GT-ST024M | Yes | [SWTG024AS-A V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 |
|
||||||
| Hasivo | S1100WP_8GT_1SX_SE | Yes | [S1100WP_8GT_1SX_SE-V1.05](devices/HASIVO_S1100WP_8GT_1SX_SE.md) | 2M | 8 + 1 |
|
| Hasivo | S1100WP_8GT_1SX_SE | Yes | [S1100WP_8GT_1SX_SE-V1.05](devices/HASIVO_S1100WP_8GT_1SX_SE.md) | 2M | 8 + 1 |
|
||||||
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 |
|
||||||
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 |
|
| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 |
|
||||||
|
|||||||
+32
-47
@@ -11,15 +11,15 @@ th_sel_light:"Selenized Light",th_sel_dark:"Selenized Dark",
|
|||||||
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Apply",c_cancel:"Cancel",c_confirm:"Confirm",
|
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Apply",c_cancel:"Cancel",c_confirm:"Confirm",
|
||||||
c_close:"Close",c_refresh:"Refresh",c_off:"off",c_offc:"Off",c_down:"down",c_on:"On",c_auto:"Auto",c_delete:"Delete",
|
c_close:"Close",c_refresh:"Refresh",c_off:"off",c_offc:"Off",c_down:"down",c_on:"On",c_auto:"Auto",c_delete:"Delete",
|
||||||
c_type:"Type",c_state:"State",c_enabled:"Enabled",c_load:"Load",c_disable:"Disable",c_sfp:"SFP",
|
c_type:"Type",c_state:"State",c_enabled:"Enabled",c_load:"Load",c_disable:"Disable",c_sfp:"SFP",
|
||||||
c_full:"full",c_half:"half",c_devices:"devices",c_yes:"yes",c_no:"no",
|
c_full:"full",c_half:"half",c_yes:"yes",c_no:"no",
|
||||||
d_ports:"Ports",d_ports_h:"click a port for details",d_system:"System",d_traffic:"Traffic",
|
d_system:"System",d_traffic:"Traffic",
|
||||||
d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad",
|
d_traffic_h:"packets/s, live",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX bad",d_rxbad:"RX bad",
|
||||||
i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
i_host:"Hostname",i_ip:"IP address",i_mask:"Netmask",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
||||||
i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"Syslog",
|
i_built:"Built",i_hw:"Hardware",i_temp:"Temperature",i_flash:"Flash",i_syslog:"Syslog",
|
||||||
p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad",
|
p_state:"State",p_disabled:"disabled",p_up:"up",p_txgb:"TX good / bad",p_rxgb:"RX good / bad",
|
||||||
p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power",
|
p_pkts:"pkts",p_module:"Module",p_temp:"Temperature",p_vcc:"Vcc",p_txbias:"TX bias",p_txpower:"TX power",
|
||||||
p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising",
|
p_rxpower:"RX power",p_txfault:"TX fault",p_txdis:"TX disabled",p_rxlos:"RX LOS",p_adv:"Advertising",
|
||||||
pt_title:"Port configuration",pt_conn:"Connected",pt_speed:"Speed",pt_mtu:"MTU",
|
pt_title:"Port configuration",pt_conn:"Devices learned",pt_speed:"Speed",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"SFP speed is set per slot and is not saved in the startup config.",
|
pt_sfp_note:"SFP speed is set per slot and is not saved in the startup config.",
|
||||||
pt_name_err:"Port name: 1-15 characters, no spaces",pt_mtu_err:"MTU must be 64-16383",
|
pt_name_err:"Port name: 1-15 characters, no spaces",pt_mtu_err:"MTU must be 64-16383",
|
||||||
stp_title:"Spanning tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP compatible",
|
stp_title:"Spanning tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP compatible",
|
||||||
@@ -142,15 +142,15 @@ th_sel_light:"Selenized ライト",th_sel_dark:"Selenized ダーク",
|
|||||||
c_port:"ポート",c_name:"名前",c_link:"リンク",c_apply:"適用",c_cancel:"キャンセル",c_confirm:"確認",
|
c_port:"ポート",c_name:"名前",c_link:"リンク",c_apply:"適用",c_cancel:"キャンセル",c_confirm:"確認",
|
||||||
c_close:"閉じる",c_refresh:"更新",c_off:"オフ",c_offc:"オフ",c_down:"リンクダウン",c_on:"オン",c_auto:"自動",c_delete:"削除",
|
c_close:"閉じる",c_refresh:"更新",c_off:"オフ",c_offc:"オフ",c_down:"リンクダウン",c_on:"オン",c_auto:"自動",c_delete:"削除",
|
||||||
c_type:"タイプ",c_state:"状態",c_enabled:"有効",c_load:"読み込み",c_disable:"無効化",c_sfp:"SFP",
|
c_type:"タイプ",c_state:"状態",c_enabled:"有効",c_load:"読み込み",c_disable:"無効化",c_sfp:"SFP",
|
||||||
c_full:"全二重",c_half:"半二重",c_devices:"デバイス",c_yes:"はい",c_no:"いいえ",
|
c_full:"全二重",c_half:"半二重",c_yes:"はい",c_no:"いいえ",
|
||||||
d_ports:"ポート",d_ports_h:"ポートをクリックすると詳細を表示",d_system:"システム",d_traffic:"トラフィック",
|
d_system:"システム",d_traffic:"トラフィック",
|
||||||
d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常",
|
d_traffic_h:"パケット/秒、リアルタイム",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 異常",d_rxbad:"RX 異常",
|
||||||
i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア",
|
i_host:"ホスト名",i_ip:"IP アドレス",i_mask:"ネットマスク",i_gw:"ゲートウェイ",i_mac:"MAC",i_fw:"ファームウェア",
|
||||||
i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog",
|
i_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog",
|
||||||
p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常",
|
p_state:"状態",p_disabled:"無効",p_up:"アップ",p_txgb:"TX 正常 / 異常",p_rxgb:"RX 正常 / 異常",
|
||||||
p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力",
|
p_pkts:"pkts",p_module:"モジュール",p_temp:"温度",p_vcc:"電圧",p_txbias:"TX バイアス",p_txpower:"TX 電力",
|
||||||
p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ",
|
p_rxpower:"RX 電力",p_txfault:"TX 障害",p_txdis:"TX 無効",p_rxlos:"RX 信号ロス",p_adv:"アドバタイズ",
|
||||||
pt_title:"ポート設定",pt_conn:"接続デバイス",pt_speed:"速度",pt_mtu:"MTU",
|
pt_title:"ポート設定",pt_conn:"学習済みデバイス",pt_speed:"速度",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"SFP の速度はスロット単位で設定され、起動設定には保存されません。",
|
pt_sfp_note:"SFP の速度はスロット単位で設定され、起動設定には保存されません。",
|
||||||
pt_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください",
|
pt_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください",
|
||||||
stp_title:"スパニングツリー",stp_h:"RSTP, 802.1w",stp_version:"バージョン",stp_v_stp:"STP 互換",
|
stp_title:"スパニングツリー",stp_h:"RSTP, 802.1w",stp_version:"バージョン",stp_v_stp:"STP 互換",
|
||||||
@@ -255,15 +255,15 @@ th_sel_light:"Selenized 浅色",th_sel_dark:"Selenized 深色",
|
|||||||
c_port:"端口",c_name:"名称",c_link:"链路",c_apply:"应用",c_cancel:"取消",c_confirm:"确认",
|
c_port:"端口",c_name:"名称",c_link:"链路",c_apply:"应用",c_cancel:"取消",c_confirm:"确认",
|
||||||
c_close:"关闭",c_refresh:"刷新",c_off:"关",c_offc:"关",c_down:"未连接",c_on:"开",c_auto:"自动",c_delete:"删除",
|
c_close:"关闭",c_refresh:"刷新",c_off:"关",c_offc:"关",c_down:"未连接",c_on:"开",c_auto:"自动",c_delete:"删除",
|
||||||
c_type:"类型",c_state:"状态",c_enabled:"启用",c_load:"读取",c_disable:"禁用",c_sfp:"SFP",
|
c_type:"类型",c_state:"状态",c_enabled:"启用",c_load:"读取",c_disable:"禁用",c_sfp:"SFP",
|
||||||
c_full:"全双工",c_half:"半双工",c_devices:"台设备",c_yes:"是",c_no:"否",
|
c_full:"全双工",c_half:"半双工",c_yes:"是",c_no:"否",
|
||||||
d_ports:"端口",d_ports_h:"点击端口查看详情",d_system:"系统",d_traffic:"流量",
|
d_system:"系统",d_traffic:"流量",
|
||||||
d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误",
|
d_traffic_h:"包/秒,实时",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX 错误",d_rxbad:"RX 错误",
|
||||||
i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件",
|
i_host:"主机名",i_ip:"IP 地址",i_mask:"子网掩码",i_gw:"网关",i_mac:"MAC",i_fw:"固件",
|
||||||
i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog",
|
i_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog",
|
||||||
p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误",
|
p_state:"状态",p_disabled:"已禁用",p_up:"已连接",p_txgb:"TX 正常 / 错误",p_rxgb:"RX 正常 / 错误",
|
||||||
p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率",
|
p_pkts:"个包",p_module:"模块",p_temp:"温度",p_vcc:"供电电压",p_txbias:"TX 偏置电流",p_txpower:"TX 光功率",
|
||||||
p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力",
|
p_rxpower:"RX 光功率",p_txfault:"TX 故障",p_txdis:"TX 禁用",p_rxlos:"RX 信号丢失",p_adv:"通告能力",
|
||||||
pt_title:"端口配置",pt_conn:"已连接设备",pt_speed:"速率",pt_mtu:"MTU",
|
pt_title:"端口配置",pt_conn:"已学习设备",pt_speed:"速率",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"SFP 速率按插槽设置,不会保存到启动配置。",
|
pt_sfp_note:"SFP 速率按插槽设置,不会保存到启动配置。",
|
||||||
pt_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383",
|
pt_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383",
|
||||||
stp_title:"生成树",stp_h:"RSTP, 802.1w",stp_version:"版本",stp_v_stp:"STP 兼容",
|
stp_title:"生成树",stp_h:"RSTP, 802.1w",stp_version:"版本",stp_v_stp:"STP 兼容",
|
||||||
@@ -368,15 +368,15 @@ th_sel_light:"Selenized claro",th_sel_dark:"Selenized oscuro",
|
|||||||
c_port:"Puerto",c_name:"Nombre",c_link:"Enlace",c_apply:"Aplicar",c_cancel:"Cancelar",c_confirm:"Confirmar",
|
c_port:"Puerto",c_name:"Nombre",c_link:"Enlace",c_apply:"Aplicar",c_cancel:"Cancelar",c_confirm:"Confirmar",
|
||||||
c_close:"Cerrar",c_refresh:"Actualizar",c_off:"apagado",c_offc:"Apagado",c_down:"caído",c_on:"Encendido",c_auto:"Auto",c_delete:"Eliminar",
|
c_close:"Cerrar",c_refresh:"Actualizar",c_off:"apagado",c_offc:"Apagado",c_down:"caído",c_on:"Encendido",c_auto:"Auto",c_delete:"Eliminar",
|
||||||
c_type:"Tipo",c_state:"Estado",c_enabled:"Habilitado",c_load:"Cargar",c_disable:"Deshabilitar",c_sfp:"SFP",
|
c_type:"Tipo",c_state:"Estado",c_enabled:"Habilitado",c_load:"Cargar",c_disable:"Deshabilitar",c_sfp:"SFP",
|
||||||
c_full:"dúplex completo",c_half:"semidúplex",c_devices:"dispositivos",c_yes:"sí",c_no:"no",
|
c_full:"dúplex completo",c_half:"semidúplex",c_yes:"sí",c_no:"no",
|
||||||
d_ports:"Puertos",d_ports_h:"pulsa un puerto para ver detalles",d_system:"Sistema",d_traffic:"Tráfico",
|
d_system:"Sistema",d_traffic:"Tráfico",
|
||||||
d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos",
|
d_traffic_h:"paquetes/s, en vivo",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX erróneos",d_rxbad:"RX erróneos",
|
||||||
i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware",
|
i_host:"Nombre de host",i_ip:"Dirección IP",i_mask:"Máscara de red",i_gw:"Puerta de enlace",i_mac:"MAC",i_fw:"Firmware",
|
||||||
i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog",
|
i_built:"Compilado",i_hw:"Hardware",i_flash:"Flash",i_syslog:"Syslog",
|
||||||
p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos",
|
p_state:"Estado",p_disabled:"deshabilitado",p_up:"activo",p_txgb:"TX correctos / erróneos",p_rxgb:"RX correctos / erróneos",
|
||||||
p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX",
|
p_pkts:"paquetes",p_module:"Módulo",p_temp:"Temperatura",p_vcc:"Vcc",p_txbias:"Polarización TX",p_txpower:"Potencia TX",
|
||||||
p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado",
|
p_rxpower:"Potencia RX",p_txfault:"Fallo TX",p_txdis:"TX deshabilitado",p_rxlos:"Pérdida RX (LOS)",p_adv:"Anunciado",
|
||||||
pt_title:"Configuración de puerto",pt_conn:"Conectado",pt_speed:"Velocidad",pt_mtu:"MTU",
|
pt_title:"Configuración de puerto",pt_conn:"Dispositivos aprendidos",pt_speed:"Velocidad",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"La velocidad del SFP se ajusta por ranura y no se guarda en la configuración de inicio.",
|
pt_sfp_note:"La velocidad del SFP se ajusta por ranura y no se guarda en la configuración de inicio.",
|
||||||
pt_name_err:"Nombre de puerto: 1-15 caracteres, sin espacios",pt_mtu_err:"El MTU debe estar entre 64 y 16383",
|
pt_name_err:"Nombre de puerto: 1-15 caracteres, sin espacios",pt_mtu_err:"El MTU debe estar entre 64 y 16383",
|
||||||
stp_title:"Árbol de expansión",stp_h:"RSTP, 802.1w",stp_version:"Versión",stp_v_stp:"STP compatible",
|
stp_title:"Árbol de expansión",stp_h:"RSTP, 802.1w",stp_version:"Versión",stp_v_stp:"STP compatible",
|
||||||
@@ -480,15 +480,15 @@ th_sel_light:"Clair (sélénisé)",th_sel_dark:"Sombre (sélénisé)",
|
|||||||
c_port:"Port",c_name:"Nom",c_link:"Lien",c_apply:"Appliquer",c_cancel:"Annuler",c_confirm:"Confirmer",
|
c_port:"Port",c_name:"Nom",c_link:"Lien",c_apply:"Appliquer",c_cancel:"Annuler",c_confirm:"Confirmer",
|
||||||
c_close:"Fermer",c_refresh:"Raffraichir",c_off:"arrêt",c_offc:"Arrêt",c_down:"arrêt",c_on:"Marche",c_auto:"Auto",c_delete:"Supprimer",
|
c_close:"Fermer",c_refresh:"Raffraichir",c_off:"arrêt",c_offc:"Arrêt",c_down:"arrêt",c_on:"Marche",c_auto:"Auto",c_delete:"Supprimer",
|
||||||
c_type:"Type",c_state:"Etat",c_enabled:"Activé",c_load:"Charger",c_disable:"Désactivé",c_sfp:"SFP",
|
c_type:"Type",c_state:"Etat",c_enabled:"Activé",c_load:"Charger",c_disable:"Désactivé",c_sfp:"SFP",
|
||||||
c_full:"full",c_half:"half",c_devices:"Equipements",c_yes:"oui",c_no:"non",
|
c_full:"full",c_half:"half",c_yes:"oui",c_no:"non",
|
||||||
d_ports:"Ports",d_ports_h:"Cliquez ou survollez pour plus de détails",d_system:"Système",d_traffic:"Trafic",
|
d_system:"Système",d_traffic:"Trafic",
|
||||||
d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO",
|
d_traffic_h:"paquets/s (en direct)",d_txpps:"TX pps",d_rxpps:"RX pps",d_txbad:"TX KO",d_rxbad:"RX KO",
|
||||||
i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel",
|
i_host:"Nom d'hote",i_ip:"Adresse IP",i_mask:"Masque réseau",i_gw:"Passerelle",i_mac:"Adresse MAC",i_fw:"Micro logiciel",
|
||||||
i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Flash",i_syslog:"Journal système",
|
i_built:"Compilé le",i_hw:"Matériel",i_temp:"Température",i_flash:"Taille Flash",i_syslog:"Journal système",
|
||||||
p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais",
|
p_state:"Etat",p_disabled:"Inactif",p_up:"Actif",p_txgb:"TX bon / mauvais",p_rxgb:"RX bon / mauvais",
|
||||||
p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance",
|
p_pkts:"paquets",p_module:"Module",p_temp:"Température",p_vcc:"Vcc",p_txbias:"TX biais",p_txpower:"TX puissance",
|
||||||
p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités",
|
p_rxpower:"RX puissance",p_txfault:"TX erreur",p_txdis:"TX désactivé",p_rxlos:"RX pertes de signaux",p_adv:"Capacités",
|
||||||
pt_title:"Configuration du port",pt_conn:"Connecté à",pt_speed:"Vitesse",pt_mtu:"MTU",
|
pt_title:"Configuration du port",pt_conn:"Appareils appris",pt_speed:"Vitesse",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"La vitesse SFP est paramétrée pour le port et n'est pas enregistrée dans la configuration de démarrage.",
|
pt_sfp_note:"La vitesse SFP est paramétrée pour le port et n'est pas enregistrée dans la configuration de démarrage.",
|
||||||
pt_name_err:"Nom du port: 1 à 15 caractères, sans espaces",pt_mtu_err:"MTU doit être comrpis entre 64 et 16383",
|
pt_name_err:"Nom du port: 1 à 15 caractères, sans espaces",pt_mtu_err:"MTU doit être comrpis entre 64 et 16383",
|
||||||
stp_title:"Arborescence",stp_h:"RSTP, 802.1w",stp_version:"Protocole",stp_v_stp:"Compatible STP",
|
stp_title:"Arborescence",stp_h:"RSTP, 802.1w",stp_version:"Protocole",stp_v_stp:"Compatible STP",
|
||||||
@@ -588,7 +588,7 @@ fw_timeout:"Le commutateur n'est plus joignable depuis 150 s: verifiez l'aliment
|
|||||||
},
|
},
|
||||||
de:{
|
de:{
|
||||||
nav_dash:"Übersicht",nav_ports:"Ports",nav_stp:"Spanning Tree",nav_stats:"Statistik",
|
nav_dash:"Übersicht",nav_ports:"Ports",nav_stp:"Spanning Tree",nav_stats:"Statistik",
|
||||||
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_lag:"LAG",nav_eee:"EEE",
|
nav_vlan:"VLANs",nav_l2:"MAC-Tabelle",nav_mirror:"Spiegelung",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
|
||||||
nav_bw:"Bandbreite",nav_system:"System",nav_fw:"Firmware",
|
nav_bw:"Bandbreite",nav_system:"System",nav_fw:"Firmware",
|
||||||
hdr_dirty:"ungespeicherte Änderungen",hdr_dirty_t:"Laufende Konfiguration weicht von der Startkonfiguration ab",
|
hdr_dirty:"ungespeicherte Änderungen",hdr_dirty_t:"Laufende Konfiguration weicht von der Startkonfiguration ab",
|
||||||
hdr_save:"Im Flash speichern",hdr_save_t:"Laufende Konfiguration dauerhaft im Flash speichern",
|
hdr_save:"Im Flash speichern",hdr_save_t:"Laufende Konfiguration dauerhaft im Flash speichern",
|
||||||
@@ -597,15 +597,15 @@ th_sel_light:"Selenized Hell",th_sel_dark:"Selenized Dunkel",
|
|||||||
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Übernehmen",c_cancel:"Abbrechen",c_confirm:"Bestätigen",
|
c_port:"Port",c_name:"Name",c_link:"Link",c_apply:"Übernehmen",c_cancel:"Abbrechen",c_confirm:"Bestätigen",
|
||||||
c_close:"Schliessen",c_refresh:"Aktualisieren",c_off:"aus",c_offc:"Aus",c_down:"getrennt",c_on:"Ein",c_auto:"Auto",c_delete:"Löschen",
|
c_close:"Schliessen",c_refresh:"Aktualisieren",c_off:"aus",c_offc:"Aus",c_down:"getrennt",c_on:"Ein",c_auto:"Auto",c_delete:"Löschen",
|
||||||
c_type:"Typ",c_state:"Zustand",c_enabled:"Aktiviert",c_load:"Laden",c_disable:"Deaktivieren",c_sfp:"SFP",
|
c_type:"Typ",c_state:"Zustand",c_enabled:"Aktiviert",c_load:"Laden",c_disable:"Deaktivieren",c_sfp:"SFP",
|
||||||
c_full:"voll",c_half:"halb",c_devices:"Geräte",c_yes:"ja",c_no:"nein",
|
c_full:"voll",c_half:"halb",c_yes:"ja",c_no:"nein",
|
||||||
d_ports:"Ports",d_ports_h:"Port anklicken für Details",d_system:"System",d_traffic:"Datenverkehr",
|
d_system:"System",d_traffic:"Datenverkehr",
|
||||||
d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft",
|
d_traffic_h:"Pakete/s, live",d_txpps:"TX Pakete/s",d_rxpps:"RX Pakete/s",d_txbad:"TX fehlerhaft",d_rxbad:"RX fehlerhaft",
|
||||||
i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
i_host:"Hostname",i_ip:"IP-Adresse",i_mask:"Netzmaske",i_gw:"Gateway",i_mac:"MAC",i_fw:"Firmware",
|
||||||
i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog:"Syslog",
|
i_built:"Erstellt",i_hw:"Hardware",i_temp:"Temperatur",i_flash:"Flash",i_syslog:"Syslog",
|
||||||
p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft",
|
p_state:"Zustand",p_disabled:"deaktiviert",p_up:"verbunden",p_txgb:"TX gut / fehlerhaft",p_rxgb:"RX gut / fehlerhaft",
|
||||||
p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung",
|
p_pkts:"Pakete",p_module:"Modul",p_temp:"Temperatur",p_vcc:"Vcc",p_txbias:"TX-Bias",p_txpower:"Sendeleistung",
|
||||||
p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten",
|
p_rxpower:"Empfangsleistung",p_txfault:"TX-Fehler",p_txdis:"TX deaktiviert",p_rxlos:"RX LOS",p_adv:"Angeboten",
|
||||||
pt_title:"Port-Konfiguration",pt_conn:"Verbunden",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
|
pt_title:"Port-Konfiguration",pt_conn:"Gelernte Geräte",pt_speed:"Geschwindigkeit",pt_mtu:"MTU",
|
||||||
pt_sfp_note:"Die SFP-Geschwindigkeit wird pro Steckplatz gesetzt und nicht in der Startkonfiguration gespeichert.",
|
pt_sfp_note:"Die SFP-Geschwindigkeit wird pro Steckplatz gesetzt und nicht in der Startkonfiguration gespeichert.",
|
||||||
pt_name_err:"Port-Name: 1-15 Zeichen, keine Leerzeichen",pt_mtu_err:"MTU muss zwischen 64 und 16383 liegen",
|
pt_name_err:"Port-Name: 1-15 Zeichen, keine Leerzeichen",pt_mtu_err:"MTU muss zwischen 64 und 16383 liegen",
|
||||||
stp_title:"Spanning Tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP-kompatibel",
|
stp_title:"Spanning Tree",stp_h:"RSTP, 802.1w",stp_version:"Version",stp_v_stp:"STP-kompatibel",
|
||||||
@@ -626,6 +626,7 @@ stp_en_q:"Spanning Tree aktivieren?",
|
|||||||
stp_en_d:"Die Ports starten blockiert und brauchen bis zum doppelten Forward Delay, bis sie weiterleiten; Edge-Ports sind sofort wieder aktiv.",
|
stp_en_d:"Die Ports starten blockiert und brauchen bis zum doppelten Forward Delay, bis sie weiterleiten; Edge-Ports sind sofort wieder aktiv.",
|
||||||
stp_dis_q:"Spanning Tree deaktivieren?",stp_dis_d:"Alle Ports leiten sofort weiter; der Schutz vor Netzwerkschleifen entfällt.",
|
stp_dis_q:"Spanning Tree deaktivieren?",stp_dis_d:"Alle Ports leiten sofort weiter; der Schutz vor Netzwerkschleifen entfällt.",
|
||||||
stp_cost_err:"Pfadkosten müssen zwischen 0 und 200000000 liegen",
|
stp_cost_err:"Pfadkosten müssen zwischen 0 und 200000000 liegen",
|
||||||
|
nav_lldp:"LLDP",lldp_enabled:"LLDP aktiv",lldp_title:"Dienststatus",lldp_portname:"Name",lldp_enable:"Pakete senden",
|
||||||
st_title:"Port-Statistik",st_h:"Summen seit dem Start",st_txg:"TX gut",st_txb:"TX fehlerhaft",st_rxg:"RX gut",
|
st_title:"Port-Statistik",st_h:"Summen seit dem Start",st_txg:"TX gut",st_txb:"TX fehlerhaft",st_rxg:"RX gut",
|
||||||
st_rxb:"RX fehlerhaft",st_details:"Details",st_counters:"MIB-Zähler",st_nonzero:"nur ungleich null",
|
st_rxb:"RX fehlerhaft",st_details:"Details",st_counters:"MIB-Zähler",st_nonzero:"nur ungleich null",
|
||||||
st_autoref:"automatisch aktualisieren",st_counter:"Zähler",st_value:"Wert",st_fail:"Zähler konnten nicht geladen werden",
|
st_autoref:"automatisch aktualisieren",st_counter:"Zähler",st_value:"Wert",st_fail:"Zähler konnten nicht geladen werden",
|
||||||
@@ -648,8 +649,12 @@ l2_learned:"gelernt",l2_loading:"lädt...",l2_failed:"Laden fehlgeschlagen",l2_e
|
|||||||
l2_del_t:"Eintrag löschen",l2_flush_q:"Alle gelernten MAC-Einträge löschen?",
|
l2_del_t:"Eintrag löschen",l2_flush_q:"Alle gelernten MAC-Einträge löschen?",
|
||||||
m_title:"Port-Spiegelung",m_active:"aktiv",m_monitor:"Monitor-Port",m_mirror:"Spiegeln",m_both:"Beide",
|
m_title:"Port-Spiegelung",m_active:"aktiv",m_monitor:"Monitor-Port",m_mirror:"Spiegeln",m_both:"Beide",
|
||||||
m_note:"Beide = RX und TX des Ports auf den Monitor-Port spiegeln.",m_none:"Mindestens einen zu spiegelnden Port wählen",
|
m_note:"Beide = RX und TX des Ports auf den Monitor-Port spiegeln.",m_none:"Mindestens einen zu spiegelnden Port wählen",
|
||||||
|
iso_title:"Port-Isolation",iso_from:"Von Port",iso_to:"Zu Port",iso_all:"Alle erlauben",
|
||||||
|
iso_intro:"Ein Paket, das über einen Port hereinkommt, darf den Switch nur über die Ports verlassen, die in seiner Zeile angehakt sind. Die Isolation wirkt vor der Weiterleitung: Ein nicht angehakter Port ist direkt nicht erreichbar, egal was in der MAC-Tabelle steht.",
|
||||||
|
iso_legend:"Das Feld des Ports selbst ist immer erlaubt. Eine rote Portnummer markiert einen Port, der nicht ganz offen ist.",
|
||||||
lag_hash:"Hash:",lag_note:"Eine LAG braucht mindestens ein Mitglied, um in der Startkonfiguration gespeichert zu werden; eine leere Gruppe zu übernehmen löscht sie.",
|
lag_hash:"Hash:",lag_note:"Eine LAG braucht mindestens ein Mitglied, um in der Startkonfiguration gespeichert zu werden; eine leere Gruppe zu übernehmen löscht sie.",
|
||||||
lag_clear_q:"LAG {n} auflösen?",lag_clear_d:"Alle Mitglieds-Ports kehren in den Normalbetrieb zurück.",
|
lag_clear_q:"LAG {n} auflösen?",lag_clear_d:"Alle Mitglieds-Ports kehren in den Normalbetrieb zurück.",
|
||||||
|
lacp_heading:"LACP (802.3ad)",lag_mode:"Modus",lag_static:"Statisch",lacp_neg:"wird ausgehandelt",lacp_agg:"Aggregator",lacp_members:"aktive Mitglieder",lacp_hint:"LACP: Ports auswählen und Übernehmen drücken, um die Aushandlung zu starten",lacp_actor:"Lokal",lacp_partner:"Partner",lacp_rxstate:"Empfangsstatus",lacp_rx:"Empfangene LACPDUs",lacp_psys:"Partner-System",
|
||||||
e_title:"Energy Efficient Ethernet",e_adv:"Angeboten",e_lp:"Gegenstelle",e_active:"Aktiv",e_enable:"Aktivieren",
|
e_title:"Energy Efficient Ethernet",e_adv:"Angeboten",e_lp:"Gegenstelle",e_active:"Aktiv",e_enable:"Aktivieren",
|
||||||
e_note:"Angebotene und von der Gegenstelle unterstützte Stufen je Geschwindigkeit: 100M, 1G, 2.5G. SFP-Ports unterstützen kein EEE.",
|
e_note:"Angebotene und von der Gegenstelle unterstützte Stufen je Geschwindigkeit: 100M, 1G, 2.5G. SFP-Ports unterstützen kein EEE.",
|
||||||
e_idle:"inaktiv",e_na:"k. A.",
|
e_idle:"inaktiv",e_na:"k. A.",
|
||||||
@@ -672,7 +677,8 @@ sy_ip_err:"Ungültige IP / Netzmaske / Gateway",sy_host_err:"Hostname: 1-23 druc
|
|||||||
sy_net_q:"Netzwerkeinstellungen übernehmen?",sy_net_d:"Die Management-IP ändert sich auf {ip}: Diese Seite muss dort neu geöffnet werden.",
|
sy_net_q:"Netzwerkeinstellungen übernehmen?",sy_net_d:"Die Management-IP ändert sich auf {ip}: Diese Seite muss dort neu geöffnet werden.",
|
||||||
sy_ip_changed:"IP geändert, neu verbinden unter http://{ip}/",sy_dhcp_q:"Auf DHCP umstellen?",
|
sy_ip_changed:"IP geändert, neu verbinden unter http://{ip}/",sy_dhcp_q:"Auf DHCP umstellen?",
|
||||||
sy_dhcp_d:"Der Switch bezieht seine Adresse per DHCP. Du musst seine neue IP herausfinden, um dich wieder zu verbinden.",
|
sy_dhcp_d:"Der Switch bezieht seine Adresse per DHCP. Du musst seine neue IP herausfinden, um dich wieder zu verbinden.",
|
||||||
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
|
sy_sysip_err:"Ungültige IP des Syslog-Servers",sy_dns1:"DNS-Server",sy_dns2:"Zweiter DNS-Server",sy_dns_err:"Ungültige IP des DNS-Servers",sy_dns_dhcp:"von DHCP: {ip}",sy_sysport_err:"Syslog-Port muss zwischen 1 und 65535 liegen",
|
||||||
|
sy_time:"Uhrzeit",sy_ntp:"NTP",sy_ntpsrv:"NTP-Server",sy_ntpsrv_p:"Hostname oder IPv4-Adresse",sy_ntpint:"Abfrageintervall [min]",sy_tz:"Zeitzone",sy_dst:"Sommerzeit",sy_dst_eu:"Europa",sy_dst_us:"USA",sy_now:"Lokale Zeit",sy_sync:"Letzte Synchronisation",sy_ntpaddr:"Server-Adresse",sy_nosync:"nicht synchronisiert",sy_waiting:"warte auf den Server",sy_ago:"vor {n} min",sy_ntp_err:"Hostname oder IPv4-Adresse des NTP-Servers eingeben",sy_ntpint_err:"Abfrageintervall muss zwischen 1 und 1440 liegen",sy_time_note:"Der Switch hat keine batteriegepufferte Uhr: Die Zeit geht bei jedem Neustart verloren und wird neu vom NTP-Server bezogen, sobald das Netzwerk bereit ist. Im Flash speichern, damit die Einstellungen erhalten bleiben.",
|
||||||
sy_pw_len:"Passwort: 1-20 Zeichen",sy_pw_space:"Das Passwort darf keine Leerzeichen enthalten",sy_pw_match:"Die Passwörter stimmen nicht überein",
|
sy_pw_len:"Passwort: 1-20 Zeichen",sy_pw_space:"Das Passwort darf keine Leerzeichen enthalten",sy_pw_match:"Die Passwörter stimmen nicht überein",
|
||||||
sy_pw_q:"Admin-Passwort ändern?",sy_pw_d:"Gilt sofort für neue Anmeldungen. Im Flash speichern, damit es erhalten bleibt.",
|
sy_pw_q:"Admin-Passwort ändern?",sy_pw_d:"Gilt sofort für neue Anmeldungen. Im Flash speichern, damit es erhalten bleibt.",
|
||||||
sy_reboot_q:"Switch neu starten?",sy_reboot_d:"Es gibt UNGESPEICHERTE Änderungen, sie gehen verloren. Zuerst im Flash speichern, wenn du sie behalten willst.",
|
sy_reboot_q:"Switch neu starten?",sy_reboot_d:"Es gibt UNGESPEICHERTE Änderungen, sie gehen verloren. Zuerst im Flash speichern, wenn du sie behalten willst.",
|
||||||
@@ -958,6 +964,7 @@ function pollStatus(){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
var statusPoller=new Poller(pollStatus,2500);
|
var statusPoller=new Poller(pollStatus,2500);
|
||||||
|
statusPoller.start();
|
||||||
function needPorts(fn){
|
function needPorts(fn){
|
||||||
if(S.n)return fn();
|
if(S.n)return fn();
|
||||||
pollStatus().then(fn).catch(function(){});
|
pollStatus().then(fn).catch(function(){});
|
||||||
@@ -1102,8 +1109,7 @@ function dashStatus(){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
tabHooks.dash={
|
tabHooks.dash={
|
||||||
enter:function(){statusPoller.start();pollInfo().catch(function(){})},
|
enter:function(){pollInfo().catch(function(){})},
|
||||||
leave:function(){statusPoller.stop()},
|
|
||||||
status:dashStatus,
|
status:dashStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1147,31 +1153,12 @@ function loadMtu(){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/* One learned MAC is the attached device; several means a switch or AP
|
|
||||||
* sits behind the port, so only the count is shown. */
|
|
||||||
function portsMacs(){
|
|
||||||
l2Load().then(function(all){
|
|
||||||
var by={};
|
|
||||||
all.forEach(function(e){
|
|
||||||
if(e.pport==="CPU")return;
|
|
||||||
var l=by[e.pport]=by[e.pport]||[];
|
|
||||||
if(l.indexOf(e.mac)<0)l.push(e.mac);
|
|
||||||
});
|
|
||||||
S.ports.forEach(function(p){
|
|
||||||
var el=$("pmac"+(p.portNum-1));
|
|
||||||
if(!el)return;
|
|
||||||
var m=by[p.portNum]||[];
|
|
||||||
el.textContent=!m.length?"-":(m.length===1?m[0]:m.length+" "+t("c_devices"));
|
|
||||||
el.title=m.join("\n");
|
|
||||||
});
|
|
||||||
}).catch(function(){});
|
|
||||||
}
|
|
||||||
var _macTick=0;
|
|
||||||
function portsStatus(){
|
function portsStatus(){
|
||||||
buildPorts();
|
buildPorts();
|
||||||
if(++_macTick%10===0)portsMacs();
|
|
||||||
S.ports.forEach(function(p){
|
S.ports.forEach(function(p){
|
||||||
var i=p.portNum-1,el=$("plink"+i);
|
var i=p.portNum-1,el=$("plink"+i);
|
||||||
|
var mc=$("pmac"+i);
|
||||||
|
if(mc)mc.textContent=parseInt(p.macs,16)&0x1fff;
|
||||||
if(el)el.innerHTML=linkBadge(p);
|
if(el)el.innerHTML=linkBadge(p);
|
||||||
var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)];
|
var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)];
|
||||||
if(sel&&v&&document.activeElement!==sel)sel.value=v;
|
if(sel&&v&&document.activeElement!==sel)sel.value=v;
|
||||||
@@ -1199,8 +1186,7 @@ function applyPort(i){
|
|||||||
postCmds(cmds).then(loadMtu).catch(function(){});
|
postCmds(cmds).then(loadMtu).catch(function(){});
|
||||||
}
|
}
|
||||||
tabHooks.ports={
|
tabHooks.ports={
|
||||||
enter:function(){statusPoller.start();needPorts(function(){buildPorts();portsMacs()})},
|
enter:function(){needPorts(buildPorts)},
|
||||||
leave:function(){statusPoller.stop();l2Gen++},
|
|
||||||
status:portsStatus,
|
status:portsStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1456,8 +1442,7 @@ function statsStatus(){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
tabHooks.stats={
|
tabHooks.stats={
|
||||||
enter:function(){statusPoller.start()},
|
leave:function(){if(ctrPoll)ctrPoll.stop()},
|
||||||
leave:function(){statusPoller.stop();if(ctrPoll)ctrPoll.stop()},
|
|
||||||
status:statsStatus,
|
status:statsStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+18
-14
@@ -55,11 +55,11 @@ a{color:var(--ac);text-decoration:none}
|
|||||||
#navfoot{padding:10px 16px;border-top:1px solid var(--bd);font-size:12px;color:var(--fg2)}
|
#navfoot{padding:10px 16px;border-top:1px solid var(--bd);font-size:12px;color:var(--fg2)}
|
||||||
#wrap{flex:1;min-width:0;display:flex;flex-direction:column}
|
#wrap{flex:1;min-width:0;display:flex;flex-direction:column}
|
||||||
#top{
|
#top{
|
||||||
display:flex;align-items:center;gap:10px;padding:10px 20px;
|
display:flex;align-items:center;flex-wrap:wrap;gap:10px;padding:8px 20px;
|
||||||
background:var(--panel);border-bottom:1px solid var(--bd);position:sticky;top:0;z-index:5;
|
background:var(--panel);border-bottom:1px solid var(--bd);position:sticky;top:0;z-index:5;
|
||||||
}
|
}
|
||||||
#burger{display:none;background:none;border:0;cursor:pointer;padding:4px}
|
#burger{display:none;background:none;border:0;cursor:pointer;padding:4px}
|
||||||
#ttitle{font-size:16px;font-weight:650;flex:1}
|
#ttitle{font-size:16px;font-weight:650;min-width:120px}
|
||||||
#dirty{
|
#dirty{
|
||||||
display:none;font-size:12px;font-weight:600;color:var(--warn);
|
display:none;font-size:12px;font-weight:600;color:var(--warn);
|
||||||
border:1px solid var(--warn);border-radius:20px;padding:2px 10px;
|
border:1px solid var(--warn);border-radius:20px;padding:2px 10px;
|
||||||
@@ -112,19 +112,21 @@ label.row span.lb{width:110px;flex:none;color:var(--fg2);font-size:13px}
|
|||||||
}
|
}
|
||||||
.switch input:checked+i{background:var(--ok)}
|
.switch input:checked+i{background:var(--ok)}
|
||||||
.switch input:checked+i:before{transform:translateX(15px)}
|
.switch input:checked+i:before{transform:translateX(15px)}
|
||||||
#strip{display:flex;gap:8px;flex-wrap:wrap;padding:4px 0 2px}
|
#strip{display:flex;gap:6px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}
|
||||||
|
.port:first-child{margin-left:auto}
|
||||||
|
.port:last-child{margin-right:auto}
|
||||||
.port{
|
.port{
|
||||||
width:46px;border:2px solid var(--bd);border-radius:7px;padding:5px 0 3px;
|
width:40px;border:2px solid var(--bd);border-radius:7px;padding:3px 0 2px;
|
||||||
text-align:center;cursor:pointer;background:var(--panel2);position:relative;
|
text-align:center;cursor:pointer;background:var(--panel2);position:relative;
|
||||||
}
|
}
|
||||||
.port.sfp{width:56px}
|
.port.sfp{width:50px}
|
||||||
.port .pn{font-weight:650;font-size:13px}
|
.port .pn{font-weight:650;font-size:12px}
|
||||||
.port .ps{font-size:10px;color:var(--fg2);display:block;line-height:1.2}
|
.port .ps{font-size:9px;color:var(--fg2);display:block;line-height:1.2}
|
||||||
.port .jack{
|
.port .jack{
|
||||||
display:block;width:18px;height:12px;margin:3px auto 2px;border-radius:2px;
|
display:block;width:16px;height:10px;margin:2px auto 1px;border-radius:2px;
|
||||||
border:2px solid var(--fg2);border-top-width:5px;opacity:.55;
|
border:2px solid var(--fg2);border-top-width:4px;opacity:.55;
|
||||||
}
|
}
|
||||||
.port.sfp .jack{width:28px;height:10px;border-top-width:3px}
|
.port.sfp .jack{width:24px;height:9px;border-top-width:3px}
|
||||||
.port.up{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
|
.port.up{border-color:var(--pc);background:color-mix(in srgb,var(--pc) 10%,var(--panel2))}
|
||||||
.port.up .jack{border-color:var(--pc);opacity:1}
|
.port.up .jack{border-color:var(--pc);opacity:1}
|
||||||
.port.up .ps{color:var(--pc);font-weight:600}
|
.port.up .ps{color:var(--pc);font-weight:600}
|
||||||
@@ -183,6 +185,10 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
|||||||
#ttitle{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
#ttitle{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||||
#dirty{padding:2px 7px}
|
#dirty{padding:2px 7px}
|
||||||
}
|
}
|
||||||
|
@media (max-width:720px){
|
||||||
|
#ttitle{flex:1}
|
||||||
|
#strip{order:3;flex-basis:100%}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
@@ -215,15 +221,13 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
|||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--fg)" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--fg)" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span id="ttitle"></span>
|
<span id="ttitle"></span>
|
||||||
|
<div id="strip"></div>
|
||||||
<span id="dirty" data-i18n="hdr_dirty" data-i18n-t="hdr_dirty_t">unsaved changes</span>
|
<span id="dirty" data-i18n="hdr_dirty" data-i18n-t="hdr_dirty_t">unsaved changes</span>
|
||||||
<button class="ctl pri" id="saveBtn" data-i18n="hdr_save" data-i18n-t="hdr_save_t">Save to flash</button>
|
<button class="ctl pri" id="saveBtn" data-i18n="hdr_save" data-i18n-t="hdr_save_t">Save to flash</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section class="tab act" id="tab-dash">
|
<section class="tab act" id="tab-dash">
|
||||||
<div class="card"><h2><span data-i18n="d_ports">Ports</span> <span class="hint" data-i18n="d_ports_h">click a port for details</span></h2>
|
|
||||||
<div id="strip"></div>
|
|
||||||
</div>
|
|
||||||
<div class="grid2">
|
<div class="grid2">
|
||||||
<div class="card"><h2 data-i18n="d_system">System</h2><table class="t" id="sysinfo"></table></div>
|
<div class="card"><h2 data-i18n="d_system">System</h2><table class="t" id="sysinfo"></table></div>
|
||||||
<div class="card"><h2><span data-i18n="d_traffic">Traffic</span> <span class="hint" data-i18n="d_traffic_h">packets/s, live</span></h2>
|
<div class="card"><h2><span data-i18n="d_traffic">Traffic</span> <span class="hint" data-i18n="d_traffic_h">packets/s, live</span></h2>
|
||||||
@@ -237,7 +241,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
|||||||
<section class="tab" id="tab-ports">
|
<section class="tab" id="tab-ports">
|
||||||
<div class="card"><h2 data-i18n="pt_title">Port configuration</h2>
|
<div class="card"><h2 data-i18n="pt_title">Port configuration</h2>
|
||||||
<div class="scrollx"><table class="t" id="ptable">
|
<div class="scrollx"><table class="t" id="ptable">
|
||||||
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Connected</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
|
<thead><tr><th data-i18n="c_port">Port</th><th data-i18n="c_name">Name</th><th data-i18n="c_link">Link</th><th data-i18n="pt_conn">Devices learned</th><th data-i18n="pt_speed">Speed</th><th data-i18n="c_enabled">Enabled</th><th data-i18n="pt_mtu">MTU</th><th></th></tr></thead>
|
||||||
<tbody></tbody></table></div>
|
<tbody></tbody></table></div>
|
||||||
<p class="small mut" style="margin-top:8px" data-i18n="pt_sfp_note">SFP speed is set per slot and is not saved in the startup config.</p>
|
<p class="small mut" style="margin-top:8px" data-i18n="pt_sfp_note">SFP speed is set per slot and is not saved in the startup config.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1111,6 +1111,9 @@ void send_status(void)
|
|||||||
slen += strtox(outbuf + slen, "\",\"rxB\":\"0x");
|
slen += strtox(outbuf + slen, "\",\"rxB\":\"0x");
|
||||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||||
reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors
|
reg_to_html(RTL837X_STAT_V_HIGH); // 32bit RX packet errors
|
||||||
|
|
||||||
|
slen += strtox(outbuf + slen, "\",\"macs\":\"0x");
|
||||||
|
reg_to_html(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2));
|
||||||
slen += strtox(outbuf + slen, "\"}");
|
slen += strtox(outbuf + slen, "\"}");
|
||||||
if (i < machine.max_port)
|
if (i < machine.max_port)
|
||||||
char_to_html(',');
|
char_to_html(',');
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
PCB_SWTG024AS_A_2_0_1.c
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _MACHINE_GT_ST024M_H_
|
||||||
|
#define _MACHINE_GT_ST024M_H_
|
||||||
|
|
||||||
|
#define MACHINE_MODEL "GoodTop GT-ST024M"
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -38,4 +38,5 @@ __code const struct machine machine = {
|
|||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.mac_flash_offset = 0x1FC000,
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "rtl837x_common.h"
|
||||||
|
#include "rtl837x_sfr.h"
|
||||||
|
#include "rtl837x_cabletest.h"
|
||||||
|
#include "rtl837x_phy.h"
|
||||||
|
#include "phy.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
|
#pragma codeseg BANK3
|
||||||
|
#pragma constseg BANK3
|
||||||
|
|
||||||
|
#define RTCT_CTRL 0xa422
|
||||||
|
#define RTCT_CTRL_START 0x00f1
|
||||||
|
#define RTCT_CTRL_DONE 0x8000
|
||||||
|
#define RTCT_SRAM_ADDR 0xa436
|
||||||
|
#define RTCT_SRAM_DATA 0xa438
|
||||||
|
#define RTCT_SRAM_STATUS 0x8026
|
||||||
|
#define RTCT_SRAM_LEN 0x8028
|
||||||
|
|
||||||
|
#define RTCT_ST_BUSY 0x01
|
||||||
|
#define RTCT_ST_MISMATCH 0x06
|
||||||
|
#define RTCT_ST_OPEN 0x08
|
||||||
|
#define RTCT_ST_SHORT 0x10
|
||||||
|
#define RTCT_ST_OK 0x20
|
||||||
|
#define RTCT_ST_DONE 0x40
|
||||||
|
#define RTCT_ST_CROSS_SHORT 0x80
|
||||||
|
|
||||||
|
#define RTCT_LEN_ZERO 150
|
||||||
|
#define RTCT_LEN_PER_50CM 43
|
||||||
|
|
||||||
|
#define PHY_POWER 0xa610
|
||||||
|
#define PHY_POWER_OFF 0x0800
|
||||||
|
|
||||||
|
#define BMCR_PDOWN_1G_FULL 0x0940
|
||||||
|
#define BMCR_1G_FULL 0x0140
|
||||||
|
#define BMCR_ANRESTART 0x0200
|
||||||
|
|
||||||
|
#define CT_IDLE 0
|
||||||
|
#define CT_SILENCE 1
|
||||||
|
#define CT_RUN 2
|
||||||
|
#define CT_POLL_TICKS (SYS_TICK_HZ / 20)
|
||||||
|
#define CT_POLLS 100
|
||||||
|
|
||||||
|
extern volatile __xdata uint32_t ticks;
|
||||||
|
extern __code const struct machine machine;
|
||||||
|
extern __xdata struct machine_runtime machine_detected;
|
||||||
|
|
||||||
|
__xdata uint8_t ct_state = CT_IDLE;
|
||||||
|
__xdata uint8_t ct_port;
|
||||||
|
__xdata uint8_t ct_last;
|
||||||
|
__xdata uint8_t ct_polls;
|
||||||
|
__xdata uint8_t ct_valid;
|
||||||
|
__xdata uint8_t ct_have = 0;
|
||||||
|
__xdata uint8_t ct_pair;
|
||||||
|
__xdata uint8_t ct_flags;
|
||||||
|
__xdata uint16_t ct_bmcr;
|
||||||
|
__xdata uint8_t ct_result[4];
|
||||||
|
__xdata uint16_t ct_len[4];
|
||||||
|
|
||||||
|
void rtl_phy_cable_test_start(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
phy_write(port, PHY_MMD31, PHY_MMD31_FEDCR, BMCR_1G_FULL);
|
||||||
|
phy_write(port, PHY_MMD31, RTCT_CTRL, RTCT_CTRL_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtl_phy_cable_test_get_status(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
phy_read(port, PHY_MMD31, RTCT_CTRL);
|
||||||
|
if (!(SFR_DATA_U16 & RTCT_CTRL_DONE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (ct_pair = 0; ct_pair < 4; ct_pair++) {
|
||||||
|
// The flags are the low byte of the word, not the high one.
|
||||||
|
phy_write(port, PHY_MMD31, RTCT_SRAM_ADDR, RTCT_SRAM_STATUS + (ct_pair << 2));
|
||||||
|
phy_read(port, PHY_MMD31, RTCT_SRAM_DATA);
|
||||||
|
ct_flags = SFR_DATA_U16;
|
||||||
|
if (!(ct_flags & RTCT_ST_DONE))
|
||||||
|
return false;
|
||||||
|
if (ct_flags & RTCT_ST_OK)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_OK;
|
||||||
|
else if (ct_flags & RTCT_ST_OPEN)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_OPEN;
|
||||||
|
else if (ct_flags & RTCT_ST_SHORT)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_SAME_SHORT;
|
||||||
|
else if (ct_flags & RTCT_ST_BUSY)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_UNSPEC;
|
||||||
|
else if (ct_flags & RTCT_ST_CROSS_SHORT)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_CROSS_SHORT;
|
||||||
|
else if (ct_flags & RTCT_ST_MISMATCH)
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_MISMATCH;
|
||||||
|
else
|
||||||
|
ct_result[ct_pair] = CABLE_RESULT_UNSPEC;
|
||||||
|
|
||||||
|
phy_write(port, PHY_MMD31, RTCT_SRAM_ADDR, RTCT_SRAM_LEN + (ct_pair << 2));
|
||||||
|
phy_read(port, PHY_MMD31, RTCT_SRAM_DATA);
|
||||||
|
ct_len[ct_pair] = SFR_DATA_U16;
|
||||||
|
ct_len[ct_pair] = ct_len[ct_pair] > RTCT_LEN_ZERO ? ct_len[ct_pair] - RTCT_LEN_ZERO : 0;
|
||||||
|
ct_len[ct_pair] = ct_len[ct_pair] * 5 / RTCT_LEN_PER_50CM;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cabletest_print(void)
|
||||||
|
{
|
||||||
|
print_string("Cable test port ");
|
||||||
|
print_phys_port(ct_port);
|
||||||
|
if (!ct_valid) {
|
||||||
|
print_string(": timed out\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_char('\n');
|
||||||
|
for (ct_pair = 0; ct_pair < 4; ct_pair++) {
|
||||||
|
print_string("Pair ");
|
||||||
|
write_char('A' + ct_pair);
|
||||||
|
switch (ct_result[ct_pair]) {
|
||||||
|
case CABLE_RESULT_OK:
|
||||||
|
print_string(": ok\n");
|
||||||
|
continue;
|
||||||
|
case CABLE_RESULT_OPEN:
|
||||||
|
print_string(": open at ");
|
||||||
|
break;
|
||||||
|
case CABLE_RESULT_SAME_SHORT:
|
||||||
|
print_string(": short at ");
|
||||||
|
break;
|
||||||
|
case CABLE_RESULT_CROSS_SHORT:
|
||||||
|
print_string(": short to another pair at ");
|
||||||
|
break;
|
||||||
|
case CABLE_RESULT_MISMATCH:
|
||||||
|
print_string(": impedance mismatch at ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print_string(": unknown\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
itoa_short(ct_len[ct_pair] / 10);
|
||||||
|
write_char('.');
|
||||||
|
write_char('0' + ct_len[ct_pair] % 10);
|
||||||
|
print_string(" m\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cabletest_run(void) __banked
|
||||||
|
{
|
||||||
|
if (ct_state) {
|
||||||
|
print_string("Cable test running on port ");
|
||||||
|
print_phys_port(ct_port);
|
||||||
|
write_char('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!machine_detected.isRTL8373 && (phy_settings.port < 4 || phy_settings.port > 7)) {
|
||||||
|
print_string("No cable test on this PHY\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A test started on a port that is off never ends and blocks the PHY until reset.
|
||||||
|
phy_read(phy_settings.port, PHY_MMD31, PHY_POWER);
|
||||||
|
if (SFR_DATA_U16 & PHY_POWER_OFF) {
|
||||||
|
print_string("Port is off\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ct_port = phy_settings.port;
|
||||||
|
phy_read(ct_port, PHY_MMD31, PHY_MMD31_FEDCR);
|
||||||
|
ct_bmcr = SFR_DATA_U16;
|
||||||
|
|
||||||
|
// Forcing the speed leaves the link up; only a power-down silences the partner.
|
||||||
|
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, BMCR_PDOWN_1G_FULL);
|
||||||
|
ct_last = ticks;
|
||||||
|
ct_have = 0;
|
||||||
|
ct_state = CT_SILENCE;
|
||||||
|
print_string("Cable test started\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cabletest_show(void) __banked
|
||||||
|
{
|
||||||
|
if (ct_state)
|
||||||
|
print_string("Cable test running\n");
|
||||||
|
else if (ct_port != phy_settings.port || !ct_have)
|
||||||
|
print_string("No cable test result\n");
|
||||||
|
else
|
||||||
|
cabletest_print();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cabletest_tick(void) __banked
|
||||||
|
{
|
||||||
|
if (ct_state == CT_SILENCE) {
|
||||||
|
if (!TICKS_DUE(ct_last, SYS_TICK_HZ))
|
||||||
|
return;
|
||||||
|
phy_read(ct_port, PHY_MMD31, PHY_POWER);
|
||||||
|
if (SFR_DATA_U16 & PHY_POWER_OFF) {
|
||||||
|
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, ct_bmcr);
|
||||||
|
ct_state = CT_IDLE;
|
||||||
|
print_string("Cable test aborted, port is off\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rtl_phy_cable_test_start(ct_port);
|
||||||
|
ct_polls = CT_POLLS;
|
||||||
|
ct_last = ticks;
|
||||||
|
ct_state = CT_RUN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ct_state != CT_RUN || !TICKS_DUE(ct_last, CT_POLL_TICKS))
|
||||||
|
return;
|
||||||
|
ct_last = ticks;
|
||||||
|
|
||||||
|
ct_valid = rtl_phy_cable_test_get_status(ct_port);
|
||||||
|
if (!ct_valid && --ct_polls)
|
||||||
|
return;
|
||||||
|
|
||||||
|
phy_write(ct_port, PHY_MMD31, RTCT_CTRL, 0);
|
||||||
|
phy_write(ct_port, PHY_MMD31, PHY_MMD31_FEDCR, ct_bmcr | BMCR_ANRESTART);
|
||||||
|
ct_have = 1;
|
||||||
|
ct_state = CT_IDLE;
|
||||||
|
cabletest_print();
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _RTL837X_CABLETEST_H_
|
||||||
|
#define _RTL837X_CABLETEST_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define CABLE_RESULT_UNSPEC 0
|
||||||
|
#define CABLE_RESULT_OK 1
|
||||||
|
#define CABLE_RESULT_OPEN 2
|
||||||
|
#define CABLE_RESULT_SAME_SHORT 3
|
||||||
|
#define CABLE_RESULT_CROSS_SHORT 4
|
||||||
|
#define CABLE_RESULT_MISMATCH 5
|
||||||
|
|
||||||
|
void rtl_phy_cable_test_start(uint8_t port) __banked;
|
||||||
|
bool rtl_phy_cable_test_get_status(uint8_t port) __banked;
|
||||||
|
|
||||||
|
void cabletest_run(void) __banked;
|
||||||
|
void cabletest_show(void) __banked;
|
||||||
|
void cabletest_tick(void) __banked;
|
||||||
|
|
||||||
|
#endif
|
||||||
+4
-1
@@ -510,7 +510,7 @@ void port_media_show(uint8_t port) __banked
|
|||||||
|
|
||||||
void port_stats_print(void) __banked
|
void port_stats_print(void) __banked
|
||||||
{
|
{
|
||||||
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\n");
|
print_string("\nPort\tState\tLink\tTxGood\t\tTxBad\t\tRxGood\t\tRxBad\t\tMACs\n");
|
||||||
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
|
||||||
print_phys_port(i); write_char('\t');
|
print_phys_port(i); write_char('\t');
|
||||||
|
|
||||||
@@ -584,6 +584,9 @@ void port_stats_print(void) __banked
|
|||||||
|
|
||||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||||
print_reg(RTL837X_STAT_V_HIGH); write_char('\t');
|
print_reg(RTL837X_STAT_V_HIGH); write_char('\t');
|
||||||
|
|
||||||
|
reg_read(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (i << 2));
|
||||||
|
itoa_short(SFR_DATA_U16 & L2_LRN_PORT_CNT_MASK);
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,6 +214,8 @@
|
|||||||
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
||||||
#define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384
|
#define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384
|
||||||
#define RTL837X_L2_LRN_PORT_CONSTRT_ACT 0x4f80
|
#define RTL837X_L2_LRN_PORT_CONSTRT_ACT 0x4f80
|
||||||
|
#define RTL837X_L2_LRN_PORT_CONSTRT_CNT 0x53ac
|
||||||
|
#define L2_LRN_PORT_CNT_MASK 0x1fff
|
||||||
#define RTL8373_REG_MAC_L2_PORT_MAX_LEN 0x1250
|
#define RTL8373_REG_MAC_L2_PORT_MAX_LEN 0x1250
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "rtl837x_bandwidth.h"
|
#include "rtl837x_bandwidth.h"
|
||||||
#include "rtl837x_init.h"
|
#include "rtl837x_init.h"
|
||||||
#include "rtl837x_lldp.h"
|
#include "rtl837x_lldp.h"
|
||||||
|
#include "rtl837x_cabletest.h"
|
||||||
#include "dhcp.h"
|
#include "dhcp.h"
|
||||||
#include "cmd_parser.h"
|
#include "cmd_parser.h"
|
||||||
#include "cmd_editor.h"
|
#include "cmd_editor.h"
|
||||||
@@ -1301,6 +1302,7 @@ static void handle_tick(void)
|
|||||||
health_phase(HEALTH_PH_STP);
|
health_phase(HEALTH_PH_STP);
|
||||||
lldp_tick();
|
lldp_tick();
|
||||||
health_phase(HEALTH_LLDP);
|
health_phase(HEALTH_LLDP);
|
||||||
|
cabletest_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,23 @@ static void t_l2_page(void)
|
|||||||
CHECK(balanced(), "every page is valid JSON");
|
CHECK(balanced(), "every page is valid JSON");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void t_status_macs(void)
|
||||||
|
{
|
||||||
|
const char *p1, *end, *mac;
|
||||||
|
|
||||||
|
printf("[test] /status.json reports the MAC addresses learned on each port\n");
|
||||||
|
hw_reset(); out_reset();
|
||||||
|
hw_reg_set(RTL837X_L2_LRN_PORT_CONSTRT_CNT + (1 << 2), 0x21);
|
||||||
|
send_status();
|
||||||
|
p1 = strstr(body(), "\"logPort\":1,");
|
||||||
|
end = p1 ? strchr(p1, '}') : NULL;
|
||||||
|
mac = p1 ? strstr(p1, "\"macs\":\"0x21\"") : NULL;
|
||||||
|
CHECK(mac && mac < end, "port 1 shows its learned count");
|
||||||
|
CHECK(has("\"macs\":\"0x0\""), "a port without learned addresses shows 0");
|
||||||
|
CHECK(slen <= TCP_OUTBUF_SIZE, "fits the buffer");
|
||||||
|
CHECK(balanced(), "valid JSON");
|
||||||
|
}
|
||||||
|
|
||||||
static void t_status_counters(void)
|
static void t_status_counters(void)
|
||||||
{
|
{
|
||||||
printf("[test] /status.json prints 64-bit packet counters in full\n");
|
printf("[test] /status.json prints 64-bit packet counters in full\n");
|
||||||
@@ -211,6 +228,7 @@ int main(void)
|
|||||||
t_l2();
|
t_l2();
|
||||||
t_l2_page();
|
t_l2_page();
|
||||||
t_status_counters();
|
t_status_counters();
|
||||||
|
t_status_macs();
|
||||||
printf("\n%d checks, %d failed\n", tests_run, tests_failed);
|
printf("\n%d checks, %d failed\n", tests_run, tests_failed);
|
||||||
return tests_failed ? 1 : 0;
|
return tests_failed ? 1 : 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Compile the current firmware execute_config() with mocked flash/tokenizer edges."""
|
||||||
|
import pathlib, subprocess
|
||||||
|
root=pathlib.Path(__file__).resolve().parent.parent
|
||||||
|
src=(root/'cmd_parser.c').read_text()
|
||||||
|
start=src.index('void execute_config(void) __banked')
|
||||||
|
end=src.index('// Execute multiple commands',start)
|
||||||
|
body=src[start:end]
|
||||||
|
out=root/'test/build';out.mkdir(exist_ok=True)
|
||||||
|
harness=r"""
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#define __xdata
|
||||||
|
#define __banked
|
||||||
|
#define CONFIG_START 0
|
||||||
|
#define CONFIG_LEN 1024
|
||||||
|
#define FLASH_READ_BURST_SIZE 256
|
||||||
|
#define CMD_BUF_SIZE 64
|
||||||
|
#define ERR_OK 0
|
||||||
|
#define NUL 0
|
||||||
|
#define PASSWORD "test-default"
|
||||||
|
uint8_t flash_buf[256],cmd_buffer[64],save_cmd,err_status;
|
||||||
|
char passwd[32],image[1024],seen[16][64];int count;
|
||||||
|
struct {uint32_t addr;uint16_t len;} flash_region;
|
||||||
|
void strtox(char*d,const char*s){strcpy(d,s);}
|
||||||
|
void flash_read_bulk(uint8_t*d){memcpy(d,image+flash_region.addr,256);}
|
||||||
|
void print_string(const char*s){(void)s;}
|
||||||
|
void print_string_x(uint8_t*s){(void)s;}
|
||||||
|
void write_char(char c){(void)c;}
|
||||||
|
void clear_command_history(void){}
|
||||||
|
void cmd_tokenize(void){err_status=cmd_buffer[0]=='#'?1:0;}
|
||||||
|
void cmd_parser(void){assert(count<16);strcpy(seen[count++],(char*)cmd_buffer);}
|
||||||
|
"""
|
||||||
|
tests=r"""
|
||||||
|
void run(const char*s){memset(image,0,sizeof image);strncpy(image,s,sizeof image-1);count=0;execute_config();assert(save_cmd==1);}
|
||||||
|
int main(void){
|
||||||
|
run("one\ntwo\n");assert(count==2&&!strcmp(seen[1],"two"));
|
||||||
|
run("one\rtwo\r");assert(count==2&&!strcmp(seen[0],"one"));
|
||||||
|
run("one\r\ntwo\r\n");assert(count==2&&!strcmp(seen[1],"two"));
|
||||||
|
run("\r\n# ignored\r\none\r\n\r\ntwo");assert(count==2&&!strcmp(seen[0],"one"));
|
||||||
|
run("one\0ignored");assert(count==1&&!strcmp(seen[0],"one"));
|
||||||
|
char longline[300];memset(longline,'x',sizeof longline);strcpy(longline+280,"\r\nok\r\n");run(longline);assert(count==1&&!strcmp(seen[0],"ok"));
|
||||||
|
/* CR at the end of a flash burst, LF at the start of the next. */
|
||||||
|
char boundary[300];memset(boundary,'\n',255);strcpy(boundary+255,"\r\nok\r\n");run(boundary);assert(count==1&&!strcmp(seen[0],"ok"));
|
||||||
|
puts("startup CR/LF/CRLF, comments, NUL, overlong and burst-boundary cases passed");return 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
(out/'startup_crlf.c').write_text(harness+body+tests)
|
||||||
|
subprocess.run(['gcc','-std=gnu11','-Wall','-Wextra','-Werror','-g','-fsanitize=address,undefined','-fno-omit-frame-pointer','-no-pie',str(out/'startup_crlf.c'),'-o',str(out/'test_startup_crlf')],check=True)
|
||||||
|
subprocess.run([str(out/'test_startup_crlf')],check=True)
|
||||||
@@ -56,6 +56,7 @@ time_t last_session_use;
|
|||||||
|
|
||||||
uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
|
uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
|
||||||
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20];
|
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20];
|
||||||
|
char macs_buff[8];
|
||||||
char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6];
|
char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6];
|
||||||
char num_buff[20];
|
char num_buff[20];
|
||||||
char l2_idx_buff[20];
|
char l2_idx_buff[20];
|
||||||
@@ -180,6 +181,12 @@ void send_status(int s)
|
|||||||
json_object_object_add(v, "txB", json_object_new_string(txB_buff));
|
json_object_object_add(v, "txB", json_object_new_string(txB_buff));
|
||||||
json_object_object_add(v, "rxG", json_object_new_string(rxG_buff));
|
json_object_object_add(v, "rxG", json_object_new_string(rxG_buff));
|
||||||
json_object_object_add(v, "rxB", json_object_new_string(rxB_buff));
|
json_object_object_add(v, "rxB", json_object_new_string(rxB_buff));
|
||||||
|
uint16_t macs = 0;
|
||||||
|
for (int e = 0; e < L2_ENTRY_NUM; e++)
|
||||||
|
if (l2_entries[e].port == physToLogPort[i-1] && l2_entries[e].type != 's')
|
||||||
|
macs++;
|
||||||
|
sprintf(macs_buff, "0x%04x", macs);
|
||||||
|
json_object_object_add(v, "macs", json_object_new_string(macs_buff));
|
||||||
if (i >= PORTS - NSFP) {
|
if (i >= PORTS - NSFP) {
|
||||||
uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100);
|
uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100);
|
||||||
uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100);
|
uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100);
|
||||||
|
|||||||
Reference in new issue
Block a user