mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
Compare commits
31
Commits
| 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
@@ -66,7 +66,6 @@ create_build_dir:
|
||||
mkdir -p "$(BUILDDIR)/uip"
|
||||
mkdir -p "$(BUILDDIR)/httpd"
|
||||
mkdir -p "$(BUILDDIR)/machine"
|
||||
mkdir -p "$(BUILDDIR)/crypto"
|
||||
|
||||
# Every machine is a pair machine/<MACHINE>.c + machine/<MACHINE>.h. Selecting
|
||||
# them by name means no #if/#elif chain, so an unknown or empty $MACHINE is
|
||||
@@ -95,12 +94,12 @@ SRCS = \
|
||||
ntp.c \
|
||||
ntp_cli.c \
|
||||
syslog.c \
|
||||
udp_apps.c \
|
||||
crypto/chacha20.c
|
||||
udp_apps.c
|
||||
|
||||
# RTL837x
|
||||
SRCS += \
|
||||
rtl837x_bandwidth.c \
|
||||
rtl837x_cabletest.c \
|
||||
rtl837x_flash.c \
|
||||
rtl837x_igmp.c \
|
||||
rtl837x_init.c \
|
||||
@@ -185,8 +184,8 @@ $(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
|
||||
${ASM} ${AFLAGS} -o $@ $<
|
||||
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
|
||||
|
||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel $(BUILDDIR)/crypto/chacha_8051.rel
|
||||
$(CC) $(CC_FLAGS) --xram-size 48896 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
|
||||
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
|
||||
$(CC) $(CC_FLAGS) --xram-size 49151 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
|
||||
|
||||
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
|
||||
objcopy --input-target=ihex -O binary $< $@
|
||||
|
||||
@@ -103,24 +103,29 @@ docker run --rm -p 8080:8080 -v $(pwd):/workspace rtlplayground-dev \
|
||||
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
|
||||
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>
|
||||
|
||||
## (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]
|
||||
> 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.
|
||||
|
||||
Now, building the firmware image should work:
|
||||
```
|
||||
make
|
||||
```
|
||||
Now, building the firmware image should work.
|
||||
|
||||
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`
|
||||
@@ -353,6 +358,7 @@ Enjoy playing!
|
||||
## (11) Other documents
|
||||
|
||||
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)
|
||||
- [CPU Port](doc/CpuPort.md)
|
||||
- [L2 learning](doc/l2.md)
|
||||
|
||||
+14
-2
@@ -20,6 +20,7 @@
|
||||
#include "rtl837x_lldp.h"
|
||||
#include "rtl837x_storm.h"
|
||||
#include "rtl837x_trap.h"
|
||||
#include "rtl837x_cabletest.h"
|
||||
#include "sfp.h"
|
||||
#include "dhcp.h"
|
||||
#include "syslog.h"
|
||||
@@ -166,10 +167,15 @@ uint8_t atoi_hex(uint8_t idx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (h_idx == 8) {
|
||||
h_idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// swap hex nibbles
|
||||
val = (val >> 4) | (val << 4);
|
||||
|
||||
if (c - '0' < 10) {
|
||||
if ((uint8_t)(c - '0') < 10) {
|
||||
val |= c - '0';
|
||||
} else {
|
||||
c |= 0x20;
|
||||
@@ -903,6 +909,7 @@ void parse_port(void)
|
||||
"\nport <port> [show|on|off]" \
|
||||
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
|
||||
"\nport <port> lldp [block|permit]" \
|
||||
"\nport <port> cabletest [show]" \
|
||||
"\nport <port> name [custom port name]\n");
|
||||
return;
|
||||
}
|
||||
@@ -945,6 +952,11 @@ void parse_port(void)
|
||||
}
|
||||
} else if (machine.is_sfp[phy_settings.port]) {
|
||||
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")) {
|
||||
print_string(" 10M\n");
|
||||
phy_settings.speed = PHY_SPEED_10M;
|
||||
@@ -2143,7 +2155,7 @@ void execute_config(void) __banked
|
||||
skipping = 1;
|
||||
}
|
||||
c = flash_buf[cfg_idx++];
|
||||
if (c == 0 || c == '\n') {
|
||||
if (c == 0 || c == '\n' || c == '\r') {
|
||||
if (skipping) {
|
||||
skipping = 0;
|
||||
} else {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef _CHACHA_H_
|
||||
#define _CHACHA_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct chacha20_t {
|
||||
uint8_t wstate[64]; // 64 bytes written here
|
||||
uint8_t constant[16]; // 128 bit constant
|
||||
uint8_t key[32]; // 256-bit secret key
|
||||
uint32_t cnt; // 32-bit block counter 1, 2.. Big Endian!
|
||||
uint8_t nonce[12]; // 96-bit nonce
|
||||
__xdata uint8_t *plaintext;
|
||||
uint16_t length;
|
||||
__xdata uint8_t *cyphertext;
|
||||
};
|
||||
|
||||
// Encrypt a plaintext with ChaCha20 as per RFC7539
|
||||
void chacha20_encrypt(void);
|
||||
|
||||
// Test ChaCha20 using the example from RFC7539
|
||||
void chacha20_test(void);
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
#include "rtl837x_common.h"
|
||||
#include "chacha.h"
|
||||
|
||||
void chacha_20(void);
|
||||
void chacha_update(void);
|
||||
void chacha_count(void);
|
||||
|
||||
// generate a block of ChaCha20 keystream as per RFC7539
|
||||
|
||||
|
||||
__xdata struct chacha20_t __at(0xbf00) chacha20;
|
||||
|
||||
#ifdef CHACHA20_TEST
|
||||
__xdata uint8_t plaintext[256];
|
||||
__xdata uint8_t cyphertext[256];
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
void chacha20_print_block(void)
|
||||
{
|
||||
for (uint8_t i=0; i < 64; i++) {
|
||||
print_byte(*(uint8_t * __xdata)(chacha20.wstate + i));
|
||||
if (i%4 == 3)
|
||||
write_char(' ');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void chacha20_encrypt(void)
|
||||
{
|
||||
__xdata uint8_t *p = chacha20.plaintext;
|
||||
|
||||
while (chacha20.length) {
|
||||
register uint8_t i;
|
||||
chacha_count();
|
||||
memcpy(chacha20.wstate, chacha20.wstate + 64, 64);
|
||||
#ifdef DEBUG
|
||||
chacha20_print_block(); write_char('\n');
|
||||
#endif
|
||||
chacha_20();
|
||||
chacha_update();
|
||||
#ifdef DEBUG
|
||||
chacha20_print_block(); write_char('\n');
|
||||
#endif
|
||||
for (i = 0; i < ((chacha20.length > 64) ? 64 : chacha20.length); i++)
|
||||
*chacha20.cyphertext++ = *p++ ^ chacha20.wstate[i];
|
||||
chacha20.length -= chacha20.length > 64 ? 64 : chacha20.length;
|
||||
#ifdef DEBUG
|
||||
print_string("\n round done\n");
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef CHACHA20_TEST
|
||||
// Test the example of RFC 7539 Section 2.4.2
|
||||
void chacha20_test(void)
|
||||
{
|
||||
__code uint8_t chacha_c[16] =
|
||||
{ 0x61, 0x70, 0x78, 0x65, 0x33, 0x20, 0x64, 0x6e,
|
||||
0x79, 0x62, 0x2d, 0x32, 0x6b, 0x20, 0x65, 0x74 };
|
||||
|
||||
__code uint8_t key[32] =
|
||||
{ 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04,
|
||||
0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c,
|
||||
0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14,
|
||||
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c };
|
||||
|
||||
__code uint8_t nonce[12] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
__code uint8_t sunscreen[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for " \
|
||||
"the future, sunscreen would be it.";
|
||||
|
||||
/*
|
||||
Ciphertext Sunscreen (from RFC 7539 Section 2.4.2):
|
||||
000 6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 n.5.%h..A..(..i.
|
||||
016 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b .~z..C`..'......
|
||||
032 f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 ..e.RG3..Y=..b.W
|
||||
048 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 .9.$.QR..S.5..a.
|
||||
064 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e ....P.jaV....".^
|
||||
080 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 R.QM.........y76
|
||||
096 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 Z...t.[......x^B
|
||||
112 87 4d
|
||||
*/
|
||||
strcpy(plaintext, sunscreen);
|
||||
memcpyc(chacha20.constant, chacha_c, 16);
|
||||
memcpyc(chacha20.key, key, 32);
|
||||
chacha20.cnt = 0;
|
||||
memcpyc(chacha20.nonce, nonce, 12);
|
||||
chacha20.plaintext = plaintext;
|
||||
chacha20.length = strlen_x(plaintext);
|
||||
chacha20.cyphertext = cyphertext;
|
||||
|
||||
print_string("Encrypting...\n");
|
||||
chacha20_encrypt();
|
||||
print_string("Cypertext:\n");
|
||||
uint16_t len = strlen_x(plaintext);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
print_byte(cyphertext[i]); write_char(' ');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,455 +0,0 @@
|
||||
; ChaCha Quater-Round implementation in Assembler
|
||||
.module chacha_8051
|
||||
; Global variables:
|
||||
.globl _chacha_20
|
||||
.globl _chacha_update
|
||||
.globl _chacha_count
|
||||
|
||||
;#define CHACHA_QR(A, B, C, D) { \
|
||||
; A += B; D ^= A; D = ROTL32(D, 16); \
|
||||
; C += D; B ^= C; B = ROTL32(B, 12); \
|
||||
; A += B; D ^= A; D = ROTL32(D, 8); \
|
||||
; C += D; B ^= C; B = ROTL32(B, 7); \
|
||||
;}
|
||||
|
||||
; r0 r1 r2 r3
|
||||
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
|
||||
|
||||
.area HOME (CODE)
|
||||
|
||||
store_32:
|
||||
ar7 = 0x07
|
||||
ar6 = 0x06
|
||||
ar5 = 0x05
|
||||
ar4 = 0x04
|
||||
ar3 = 0x03
|
||||
ar2 = 0x02
|
||||
ar1 = 0x01
|
||||
ar0 = 0x00
|
||||
|
||||
mov a, r7
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r6
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r5
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r4
|
||||
movx @dptr, a
|
||||
ret
|
||||
|
||||
rol_b:
|
||||
clr c
|
||||
mov a, r7
|
||||
rlc a
|
||||
mov r7, a
|
||||
mov a, r6
|
||||
rlc a
|
||||
mov r6, a
|
||||
mov a, r5
|
||||
rlc a
|
||||
mov r5, a
|
||||
mov a, r4
|
||||
rlc a
|
||||
mov r4, a
|
||||
clr a
|
||||
addc a, r7
|
||||
mov r7, a
|
||||
djnz dpl, rol_b
|
||||
ret
|
||||
|
||||
|
||||
chacha_plus_xor:
|
||||
; Load A into registers r4-r7, A pointed to by r0
|
||||
mov dptr, #_chacha20
|
||||
mov dpl, r0
|
||||
movx a, @dptr
|
||||
mov r7, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r6, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r5, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r4, a
|
||||
|
||||
; A += B, B pointed to by r1
|
||||
mov dpl, r1
|
||||
movx a, @dptr
|
||||
add a, r7
|
||||
mov r7, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r6
|
||||
mov r6, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r5
|
||||
mov r5, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r4
|
||||
mov r4, a
|
||||
|
||||
mov dpl, r0 ; Store A back
|
||||
mov a, r7
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r6
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r5
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r4
|
||||
movx @dptr, a
|
||||
|
||||
; D ^= A
|
||||
mov dpl, r3
|
||||
movx a, @dptr
|
||||
xrl a, r7
|
||||
mov r7, a
|
||||
dec dpl
|
||||
|
||||
movx a, @dptr
|
||||
xrl a, r6
|
||||
mov r6, a
|
||||
dec dpl
|
||||
|
||||
movx a, @dptr
|
||||
xrl a, r5
|
||||
mov r5, a
|
||||
dec dpl
|
||||
|
||||
movx a, @dptr
|
||||
xrl a, r4
|
||||
mov r4, a
|
||||
dec dpl
|
||||
ret
|
||||
|
||||
chacha_qr:
|
||||
; QR Part: A += B; D ^= A; D = ROTL32(D, 16);
|
||||
acall chacha_plus_xor
|
||||
|
||||
; rotate left 16. D is r4, r5, r6, r7 -> r6, r7, r4, r5
|
||||
mov a, r6
|
||||
xch a, r4
|
||||
mov r6, a
|
||||
mov a, r7
|
||||
xch a, r5
|
||||
mov r7, a
|
||||
mov dpl, r3 ; Store D
|
||||
acall store_32
|
||||
|
||||
;QR Part: C += D; B ^= C; B = ROTL32(B, 12);
|
||||
; Swap A <-> C and D <-> B
|
||||
mov a, r0
|
||||
xch a, r2
|
||||
mov r0, a
|
||||
mov a, r1
|
||||
xch a, r3
|
||||
mov r1, a
|
||||
acall chacha_plus_xor
|
||||
|
||||
; rotate left 12. D is r4, r5, r6, r7 -> r5, r6, r7, r4
|
||||
mov a, r4
|
||||
xch a, r7
|
||||
xch a, r6
|
||||
xch a, r5
|
||||
mov r4, a
|
||||
|
||||
mov dpl, #4
|
||||
acall rol_b
|
||||
mov dpl, r3 ; Store D (being B)
|
||||
acall store_32
|
||||
|
||||
; Swap A <-> C and D <-> B
|
||||
mov a, r0
|
||||
xch a, r2
|
||||
mov r0, a
|
||||
mov a, r1
|
||||
xch a, r3
|
||||
mov r1, a
|
||||
|
||||
; QR Part A += B; D ^= A; D = ROTL32(D, 8);
|
||||
acall chacha_plus_xor
|
||||
mov a, r4
|
||||
xch a, r7
|
||||
xch a, r6
|
||||
xch a, r5
|
||||
mov r4, a
|
||||
mov dpl, r3 ; Store D
|
||||
acall store_32
|
||||
|
||||
; QR Part
|
||||
; C += D; B ^= C; B = ROTL32(B, 7);
|
||||
line4:
|
||||
; Swap A <-> C and D <-> B
|
||||
mov a, r0
|
||||
xch a, r2
|
||||
mov r0, a
|
||||
mov a, r1
|
||||
xch a, r3
|
||||
mov r1, a
|
||||
acall chacha_plus_xor
|
||||
|
||||
; Roll left 7 bits, start by rolling 8 bits left, then roll 1 to the right
|
||||
mov a, r4
|
||||
xch a, r7
|
||||
xch a, r6
|
||||
xch a, r5
|
||||
mov r4, a
|
||||
|
||||
clr c
|
||||
mov a, r4
|
||||
rrc a
|
||||
mov r4, a
|
||||
mov a, r5
|
||||
rrc a
|
||||
mov r5, a
|
||||
mov a, r6
|
||||
rrc a
|
||||
mov r6, a
|
||||
mov a, r7
|
||||
rrc a
|
||||
mov r7, a
|
||||
clr a
|
||||
rrc a
|
||||
add a, r4
|
||||
mov r4, a
|
||||
|
||||
; Swap A <-> C and D <-> B
|
||||
mov a, r0
|
||||
xch a, r2
|
||||
mov r0, a
|
||||
mov a, r1
|
||||
xch a, r3
|
||||
mov r1, a
|
||||
mov dpl, r1 ; Store B
|
||||
acall store_32
|
||||
ret
|
||||
|
||||
|
||||
;
|
||||
; Implementation of 20 ChaCha Rounds (10 Double Rounds)
|
||||
;
|
||||
_chacha_20:
|
||||
push acc
|
||||
push b
|
||||
push dpl
|
||||
push dph
|
||||
push ar7
|
||||
push ar6
|
||||
push ar5
|
||||
push ar4
|
||||
push ar3
|
||||
push ar2
|
||||
push ar1
|
||||
push ar0
|
||||
push psw
|
||||
|
||||
mov b, #10 ; 10 Double rounds
|
||||
chacha_20_loop:
|
||||
; CHACHA_QR( v[ 0], v[ 4], v[ 8], v[12] );
|
||||
mov r0, #3
|
||||
mov r1, #19
|
||||
mov r2, #35
|
||||
mov r3, #51
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 1], v[ 5], v[ 9], v[13] ); 7 23 39 55
|
||||
mov r0, #7
|
||||
mov r1, #23
|
||||
mov r2, #39
|
||||
mov r3, #55
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 2], v[ 6], v[10], v[14] ); 11 27 43 59
|
||||
mov r0, #11
|
||||
mov r1, #27
|
||||
mov r2, #43
|
||||
mov r3, #59
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 3], v[ 7], v[11], v[15] ); 15 31 47 63
|
||||
mov r0, #15
|
||||
mov r1, #31
|
||||
mov r2, #47
|
||||
mov r3, #63
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 0], v[ 5], v[10], v[15] ); 3 23 43 63
|
||||
mov r0, #3
|
||||
mov r1, #23
|
||||
mov r2, #43
|
||||
mov r3, #63
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 1], v[ 6], v[11], v[12] ); 7 27 47 51
|
||||
mov r0, #7
|
||||
mov r1, #27
|
||||
mov r2, #47
|
||||
mov r3, #51
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 2], v[ 7], v[ 8], v[13] ); 11 31 35 55
|
||||
mov r0, #11
|
||||
mov r1, #31
|
||||
mov r2, #35
|
||||
mov r3, #55
|
||||
acall chacha_qr
|
||||
|
||||
; CHACHA_QR( v[ 3], v[ 4], v[ 9], v[14] ); 15 19 39 59
|
||||
mov r0, #15
|
||||
mov r1, #19
|
||||
mov r2, #39
|
||||
mov r3, #59
|
||||
acall chacha_qr
|
||||
djnz b, chacha_20_loop
|
||||
|
||||
pop psw
|
||||
pop ar0
|
||||
pop ar1
|
||||
pop ar2
|
||||
pop ar3
|
||||
pop ar4
|
||||
pop ar5
|
||||
pop ar6
|
||||
pop ar7
|
||||
pop dph
|
||||
pop dpl
|
||||
pop b
|
||||
pop acc
|
||||
ret
|
||||
|
||||
;
|
||||
; Update ChaCHa state
|
||||
;
|
||||
_chacha_update:
|
||||
push acc
|
||||
push b
|
||||
push dpl
|
||||
push dph
|
||||
push ar4
|
||||
push ar3
|
||||
push ar2
|
||||
push ar1
|
||||
push ar0
|
||||
push psw
|
||||
|
||||
mov dptr, #_chacha20
|
||||
mov b, #16 ; 16 uint32
|
||||
update_loop:
|
||||
mov a, b ; multiply by 4 and subtract 1
|
||||
rl a
|
||||
rl a
|
||||
dec a
|
||||
; Load Working State variable into registers r0-r3
|
||||
mov dpl, a
|
||||
|
||||
orl a, #64 ; Save pointer to state
|
||||
mov r4, a
|
||||
|
||||
movx a, @dptr
|
||||
mov r3, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r2, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r1, a
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
mov r0, a
|
||||
|
||||
; Add to State variable
|
||||
mov a, r4
|
||||
mov dpl, a
|
||||
movx a, @dptr
|
||||
add a, r3
|
||||
mov r3, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r2
|
||||
mov r2, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r1
|
||||
mov r1, a
|
||||
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
addc a, r0
|
||||
mov r0, a
|
||||
|
||||
; Store back state variable in LSB, first sequence (serialized)
|
||||
mov a, r4
|
||||
xrl a, #64 ; Save pointer to working state
|
||||
mov dpl, a
|
||||
mov a, r0
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r1
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r2
|
||||
movx @dptr, a
|
||||
dec dpl
|
||||
mov a, r3
|
||||
movx @dptr, a
|
||||
|
||||
djnz b, update_loop
|
||||
|
||||
pop psw
|
||||
pop ar0
|
||||
pop ar1
|
||||
pop ar2
|
||||
pop ar3
|
||||
pop ar4
|
||||
pop dph
|
||||
pop dpl
|
||||
pop b
|
||||
pop acc
|
||||
ret
|
||||
|
||||
;
|
||||
; Increase counter in state
|
||||
;
|
||||
_chacha_count:
|
||||
push acc
|
||||
push dpl
|
||||
push dph
|
||||
mov dptr, #_chacha20
|
||||
mov dpl, #112 + 3
|
||||
movx a, @dptr
|
||||
inc a
|
||||
movx @dptr, a
|
||||
jnz chacha_count_done
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
inc a
|
||||
movx @dptr, a
|
||||
jnz chacha_count_done
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
inc a
|
||||
movx @dptr, a
|
||||
jnz chacha_count_done
|
||||
dec dpl
|
||||
movx a, @dptr
|
||||
inc a
|
||||
movx @dptr, a
|
||||
chacha_count_done:
|
||||
pop dph
|
||||
pop dpl
|
||||
pop acc
|
||||
ret
|
||||
@@ -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
|
||||
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
|
||||
`MACHINE=KP_9000_9XHML_X_V3_2`, which uses the V3.1 machine definition and
|
||||
only differs in the reported name.
|
||||
`make MACHINE=KP_9000_9XHML_X_V3_2`, whose board file is a symlink to the V3.1
|
||||
definition and only differs in the reported name.
|
||||
|
||||
## Tested
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ and sold by Mokerlink.
|
||||
The device is fully supported:
|
||||
- All 4 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps
|
||||
- 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.
|
||||
|
||||
### 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|
|
||||
|---|---|---|---|---|---|
|
||||
| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? |
|
||||
| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | ??? |
|
||||
|
||||
### Label specifications
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## 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.
|
||||
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 |
|
||||
| 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-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 |
|
||||
| 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 |
|
||||
|
||||
+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_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_full:"full",c_half:"half",c_devices:"devices",c_yes:"yes",c_no:"no",
|
||||
d_ports:"Ports",d_ports_h:"click a port for details",d_system:"System",d_traffic:"Traffic",
|
||||
c_full:"full",c_half:"half",c_yes:"yes",c_no:"no",
|
||||
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",
|
||||
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",
|
||||
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_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_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",
|
||||
@@ -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_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_full:"全二重",c_half:"半二重",c_devices:"デバイス",c_yes:"はい",c_no:"いいえ",
|
||||
d_ports:"ポート",d_ports_h:"ポートをクリックすると詳細を表示",d_system:"システム",d_traffic:"トラフィック",
|
||||
c_full:"全二重",c_half:"半二重",c_yes:"はい",c_no:"いいえ",
|
||||
d_system:"システム",d_traffic:"トラフィック",
|
||||
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_built:"ビルド日",i_hw:"ハードウェア",i_temp:"温度",i_flash:"フラッシュ",i_syslog:"Syslog",
|
||||
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_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_name_err:"ポート名: 1〜15 文字、空白不可",pt_mtu_err:"MTU は 64〜16383 の範囲で指定してください",
|
||||
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_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_full:"全双工",c_half:"半双工",c_devices:"台设备",c_yes:"是",c_no:"否",
|
||||
d_ports:"端口",d_ports_h:"点击端口查看详情",d_system:"系统",d_traffic:"流量",
|
||||
c_full:"全双工",c_half:"半双工",c_yes:"是",c_no:"否",
|
||||
d_system:"系统",d_traffic:"流量",
|
||||
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_built:"构建日期",i_hw:"硬件",i_temp:"温度",i_flash:"Flash",i_syslog:"Syslog",
|
||||
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_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_name_err:"端口名称: 1-15 个字符,不能包含空格",pt_mtu_err:"MTU 范围为 64-16383",
|
||||
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_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_full:"dúplex completo",c_half:"semidúplex",c_devices:"dispositivos",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",
|
||||
c_full:"dúplex completo",c_half:"semidúplex",c_yes:"sí",c_no:"no",
|
||||
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",
|
||||
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",
|
||||
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_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_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",
|
||||
@@ -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_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_full:"full",c_half:"half",c_devices:"Equipements",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",
|
||||
c_full:"full",c_half:"half",c_yes:"oui",c_no:"non",
|
||||
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",
|
||||
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",
|
||||
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_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_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",
|
||||
@@ -588,7 +588,7 @@ fw_timeout:"Le commutateur n'est plus joignable depuis 150 s: verifiez l'aliment
|
||||
},
|
||||
de:{
|
||||
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",
|
||||
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",
|
||||
@@ -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_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_full:"voll",c_half:"halb",c_devices:"Geräte",c_yes:"ja",c_no:"nein",
|
||||
d_ports:"Ports",d_ports_h:"Port anklicken für Details",d_system:"System",d_traffic:"Datenverkehr",
|
||||
c_full:"voll",c_half:"halb",c_yes:"ja",c_no:"nein",
|
||||
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",
|
||||
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",
|
||||
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_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_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",
|
||||
@@ -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_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",
|
||||
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_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",
|
||||
@@ -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?",
|
||||
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",
|
||||
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_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_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.",
|
||||
@@ -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_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_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_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.",
|
||||
@@ -958,6 +964,7 @@ function pollStatus(){
|
||||
});
|
||||
}
|
||||
var statusPoller=new Poller(pollStatus,2500);
|
||||
statusPoller.start();
|
||||
function needPorts(fn){
|
||||
if(S.n)return fn();
|
||||
pollStatus().then(fn).catch(function(){});
|
||||
@@ -1102,8 +1109,7 @@ function dashStatus(){
|
||||
});
|
||||
}
|
||||
tabHooks.dash={
|
||||
enter:function(){statusPoller.start();pollInfo().catch(function(){})},
|
||||
leave:function(){statusPoller.stop()},
|
||||
enter:function(){pollInfo().catch(function(){})},
|
||||
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(){
|
||||
buildPorts();
|
||||
if(++_macTick%10===0)portsMacs();
|
||||
S.ports.forEach(function(p){
|
||||
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);
|
||||
var sel=$("pspd"+i),v=p.isSFP?0:ADVSEL[parseInt(p.adv,2)];
|
||||
if(sel&&v&&document.activeElement!==sel)sel.value=v;
|
||||
@@ -1199,8 +1186,7 @@ function applyPort(i){
|
||||
postCmds(cmds).then(loadMtu).catch(function(){});
|
||||
}
|
||||
tabHooks.ports={
|
||||
enter:function(){statusPoller.start();needPorts(function(){buildPorts();portsMacs()})},
|
||||
leave:function(){statusPoller.stop();l2Gen++},
|
||||
enter:function(){needPorts(buildPorts)},
|
||||
status:portsStatus,
|
||||
};
|
||||
|
||||
@@ -1456,8 +1442,7 @@ function statsStatus(){
|
||||
});
|
||||
}
|
||||
tabHooks.stats={
|
||||
enter:function(){statusPoller.start()},
|
||||
leave:function(){statusPoller.stop();if(ctrPoll)ctrPoll.stop()},
|
||||
leave:function(){if(ctrPoll)ctrPoll.stop()},
|
||||
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)}
|
||||
#wrap{flex:1;min-width:0;display:flex;flex-direction:column}
|
||||
#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;
|
||||
}
|
||||
#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{
|
||||
display:none;font-size:12px;font-weight:600;color:var(--warn);
|
||||
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: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{
|
||||
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;
|
||||
}
|
||||
.port.sfp{width:56px}
|
||||
.port .pn{font-weight:650;font-size:13px}
|
||||
.port .ps{font-size:10px;color:var(--fg2);display:block;line-height:1.2}
|
||||
.port.sfp{width:50px}
|
||||
.port .pn{font-weight:650;font-size:12px}
|
||||
.port .ps{font-size:9px;color:var(--fg2);display:block;line-height:1.2}
|
||||
.port .jack{
|
||||
display:block;width:18px;height:12px;margin:3px auto 2px;border-radius:2px;
|
||||
border:2px solid var(--fg2);border-top-width:5px;opacity:.55;
|
||||
display:block;width:16px;height:10px;margin:2px auto 1px;border-radius:2px;
|
||||
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 .jack{border-color:var(--pc);opacity:1}
|
||||
.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}
|
||||
#dirty{padding:2px 7px}
|
||||
}
|
||||
@media (max-width:720px){
|
||||
#ttitle{flex:1}
|
||||
#strip{order:3;flex-basis:100%}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
(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>
|
||||
</button>
|
||||
<span id="ttitle"></span>
|
||||
<div id="strip"></div>
|
||||
<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>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<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="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>
|
||||
@@ -237,7 +241,7 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
|
||||
<section class="tab" id="tab-ports">
|
||||
<div class="card"><h2 data-i18n="pt_title">Port configuration</h2>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
@@ -1111,6 +1111,9 @@ void send_status(void)
|
||||
slen += strtox(outbuf + slen, "\",\"rxB\":\"0x");
|
||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||
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, "\"}");
|
||||
if (i < machine.max_port)
|
||||
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,
|
||||
},
|
||||
},
|
||||
.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
|
||||
{
|
||||
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++) {
|
||||
print_phys_port(i); write_char('\t');
|
||||
|
||||
@@ -584,6 +584,9 @@ void port_stats_print(void) __banked
|
||||
|
||||
STAT_GET(STAT_COUNTER_ERR_PKTS, i);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +214,8 @@
|
||||
#define RTL837x_L2_TBL_FLUSH_CNF 0x53dc
|
||||
#define RTL837X_L2_LRN_PORT_CONSTRAINT 0x5384
|
||||
#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
|
||||
|
||||
/*
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@
|
||||
#include "rtl837x_bandwidth.h"
|
||||
#include "rtl837x_init.h"
|
||||
#include "rtl837x_lldp.h"
|
||||
#include "rtl837x_cabletest.h"
|
||||
#include "dhcp.h"
|
||||
#include "cmd_parser.h"
|
||||
#include "cmd_editor.h"
|
||||
@@ -33,7 +34,6 @@
|
||||
#include "httpd/page_impl.h"
|
||||
#include "boot.h"
|
||||
#include "sfp.h"
|
||||
#include "crypto/chacha.h"
|
||||
|
||||
extern __code const struct machine machine;
|
||||
extern __xdata uint32_t flash_size;
|
||||
@@ -1302,6 +1302,7 @@ static void handle_tick(void)
|
||||
health_phase(HEALTH_PH_STP);
|
||||
lldp_tick();
|
||||
health_phase(HEALTH_LLDP);
|
||||
cabletest_tick();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -185,6 +185,23 @@ static void t_l2_page(void)
|
||||
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)
|
||||
{
|
||||
printf("[test] /status.json prints 64-bit packet counters in full\n");
|
||||
@@ -211,6 +228,7 @@ int main(void)
|
||||
t_l2();
|
||||
t_l2_page();
|
||||
t_status_counters();
|
||||
t_status_macs();
|
||||
printf("\n%d checks, %d failed\n", tests_run, tests_failed);
|
||||
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];
|
||||
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 num_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, "rxG", json_object_new_string(rxG_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) {
|
||||
uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100);
|
||||
uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100);
|
||||
|
||||
Reference in new issue
Block a user