The port argument went through its own digit test and machine table
lookup; cmd_parse_port_separator() does both and also checks the port
exists on this board, which the open-coded test did not.
A port priority was masked to its top nibble, so "prio 17" quietly became
16. The bridge priority next to it refuses what it cannot represent, and
now the port priority does too.
Both only ever served stp_fdb_update(), so they belong there. Internal RAM
has room for them on this branch and on the one that carries the
aggregation module too.
stp_enabled is a flag, so say bool. cmpBytes() returns a comparison
result, so say int8_t. The three busy waits this branch adds read the
status straight out of the SFR instead of copying four bytes to xdata
first.
A port held out of forwarding because a loop was seen on it stops hearing
the frames that justified the hold, so its BPDU age climbs. The auto edge
branch lives inside the same countdown as the hold, reads that age, and
promotes the port back to forwarding after three seconds. The loop opens,
a BPDU comes back, the block is applied again, and the two take turns.
Measured on a looped pair present when the tree came up: twenty cycles in
one window and fifteen in the next, each block followed by a promotion,
still going when the capture ended.
The countdown alone cannot tell a loop hold from an ordinary listen, so
record the hold and leave the port alone while it stands.
make clean left tools/output in place, so the host tools were never
rebuilt after a clean. SUBDIRSCLEAN, which builds the per-directory
clean target names for exactly that purpose, was defined but nothing
consumed it. Give clean and distclean those targets as prerequisites
and add the rule that runs the subdirectory's own clean, which
tools/Makefile already provides.
tcpip_output() decides whether to splice in the 802.1Q tag, and that
decision also moves the frame: the header is shifted forward over its
padding, so a tagged frame starts at uip_buf with the q_frame layout,
while an untagged one keeps the padding and the nonq_frame layout.
nic_tx_packet() took that decision a second time, from management_vlan
alone. That agreed while the sender suppressed the management VLAN around
the transmission, but not since the tag is skipped per frame for a
CPU-tagged one: the descriptor then still sits behind the padding while
the transfer is set up for the shifted layout. The frame goes out four
bytes early and its length is read from the offset where tx_seq and
chksum_flags live, so a sixty byte BPDU is sent as around 1800 bytes of
whatever follows it. Looped back it is no longer a BPDU, the port hears
nothing, auto edge promotes it and the loop stays open.
Record the decision where it is taken and let the transfer follow it.
A variable rather than an argument because internal RAM is full once the
aggregation module shares the image: the overlay area ends at 0x7f, and
an argument or any temporary for the condition no longer fits.
The hand rolled loop was here because atoi_short() reported "no digits"
but not overflow, so 65540 would have wrapped to 4 and opened a
connection to a port nobody asked for. #326 gave it the same bound this
loop was carrying, so the reason is gone.
Zero still covers all three ways to be wrong, except that "no digits"
and overflow now come back as a zero return and port zero as a zero
value, so both are tested.
Three xdata scratch variables go with the loop.
The loop tested the digit range and the overflow bound with separate ifs,
on the strength of a comment saying the joined form makes sdcc park a
boolean in the bit area, and that an image carrying LACP and STP as well
is one bit short of needing a third byte of it. Measured on this branch
that is not what happens: the joined form links, the bit segment is
unchanged at fourteen bits overall and nine in cmd_parser, and BANK2
comes out ten bytes smaller.
The claim was about an image this branch does not build, and no branch
currently carries LACP, STP and this parser at once, so there is nothing
left to check it against. A justification nobody can verify, for a shape
nobody would otherwise write, is worse than no comment at all.
Behaviour is unchanged. The two forms agree on every input from 0 to
99999 and on the edges: empty, non digits, trailing junk, leading zeros,
65535 and 65536.
The note about atoi_short() stays, because that one still reports "no
digits" without reporting overflow. #326 replaces it with a version that
does both, and this should move onto it once that lands.
Saving the configuration drops the syslog server address whenever the log
of executed commands also contains "syslog on", which it almost always
does, since you have to enable the thing after pointing it somewhere.
parseConf() deduplicates by taking the matched text of a conf_overwrite
entry and removing every stored line that starts with it. For "syslog on"
the entry that matches is the catch-all ^syslog\b, so the matched text is
just "syslog" and the filter removes anything beginning with "syslog ",
including the "syslog ip ..." line saved a moment earlier. The address then
falls back to 0.0.0.0 on the next boot.
It fails quietly: nothing is reported, the running switch keeps logging
until it is restarted, and the loss looks like the firmware forgetting a
setting rather than the page dropping it.
Narrow the entry to the commands it is meant to collapse, so the address and
the port keep their own entries and are no longer collateral.
That alone would stop "syslog on" and "syslog off" from replacing each other,
because the list drops lines starting with the text it matched and "syslog off"
does not start with "syslog on". A separate list names the stem of such a pair
and collapses the two, which is what the catch-all used to do by accident.
The port was frozen at 514 in the call that opens the connection, so a
collector listening anywhere else was simply out of reach, and plenty do,
because 514 is privileged and containerised collectors usually get a high
port instead. Working around it meant putting a proxy in front, which then
rewrites the source address and hides which device actually sent the line.
Add `syslog port <n>`. The default stays 514, so nothing changes for an
existing configuration. Setting it tears the connection down and builds a
new one, the same dance the address already does, because uip_udp_new()
freezes the port into the connection.
The value is parsed here rather than through atoi_short(), which reports
"no digits" but not overflow: 65540 would quietly wrap to 4 and we would
open a connection to a port nobody asked for. Checking before each multiply
keeps it in 16-bit arithmetic. Zero then covers all three ways to be wrong -
no digits, past 65535, or an explicit "0", which is not a port either.
Whitelist the new command in config.js as well, next to `syslog ip`, or the
line is dropped without a word when the configuration is saved and the
setting quietly fails to survive a reboot. The dedup entry has to precede
the general `^syslog\b` one, otherwise it would deduplicate against
`syslog on`.
itoa_short() is new: itoa() only handles a byte and print_short() prints
hex, so there was no way to show a port as a decimal number. Kept separate
from itoa() rather than widening it, because every existing caller passes a
byte and would start paying for 16-bit divisions it does not need.
The scratch variables for the parser live in xdata. Locals there would take
internal RAM, and this image has none left: data ends at 0x77, the overlay
occupies 0x78-0x7f and the stack starts at 0x80. Measured: no module's DSEG
grew.
RFC 3164 has a hostname between the priority and the message text, and we
were sending nothing there. A receiver still has to fill that field, so it
takes the first word of the text instead, so every line arrives attributed to
"STP:", or "REGGET:", or whatever the log happens to start with. The sender
is then impossible to select on: the name changes with the content, and
anything in front of us on the path replaces the source address with its
own.
Observed on a collector behind a UDP proxy: the same switch showed up as two
different hosts depending on which subsystem had logged last.
Send the configured hostname. Skipped when it is empty, so we never emit a
lone separator.
The header length lives in xdata rather than on the stack. syslog_callback()
is __banked, so a local there cannot be overlaid, and while the variable
itself is only two bytes it costs more than that: it takes a register, which
pushes log_start out of one and into internal RAM. Those two bytes are
enough to stop an image carrying LACP and STP from linking at all.
Both conflicts are the register keyword removal meeting a change of ours,
so each takes main's signature and keeps what the branch was saying:
nic_rx_packet() still returns a bool, and port_ingress_filter_get() stays
declared.
main has since put its own copy of the STP module in BANK2, so the pragma
this branch carried is now duplicated. The one with main's comment stays.
Generate wrong address for `a4` location.
Both on read from and write to a __sfr32 variable.
Workaround:
Use two __sfr16 instead of one __sfr32.
We still get some optimalizations / better code gen.
The preamble scan cursor and the buffered-length parameter carry no
state between calls, so they do not need static xdata slots. As plain
locals the compiler places both in registers, trimming 64 bytes of
BANK1 code and two bytes of xdata.
The offsets shared by config_take() stay static: direct data space is
fully allocated on machines like the SWTGW218AS, so plain locals there
add overlay bytes that no longer link, and xdata-class locals spill
three temporaries into direct space while growing the code by roughly
120 bytes. Document pre_acc, whose accumulation across TCP segments is
why it must remain global.
A firmware upload previously ended in a silent connection close, leaving
the client unable to distinguish a verified upload from a failed one.
Send an explicit 200/400 verdict with the CRC result, with
Content-Length so the browser completes the response before the reset,
and only reset the chip once the verdict has been fully ACKed.
The unconditional close after a config upload is gone since the
buffered config path answers with its own response, so drop the
now-unreachable close hack from the streaming path.
A firmware image cannot be buffered whole, so the upload is streamed to
flash, and stream_upload() already resumes across TCP segments. The
multipart preamble did not: handle_post() walked the part headers from the
start of whichever segment it held, so a client that split inside the
octet-stream part header lost its place, never started streaming, and the
request hung. Firefox splits exactly there, right after filename=".
Buffer the multipart body only until the octet-stream part header is
complete, locate the payload, then stream from that point; later segments
stream as before. The header reuses the configuration buffer, which is idle
during a firmware upload, so no extra memory is needed.
This PCB appears only slightly different to the already supported and
documented PCB-SWTG115AS-V2.0. It works without any changes to the
machine definition.
While at it, also fix a typo (8272 instead of 8372), and include the
existing unused pictures on the device page.
cmd_parser.c conflicted twice: main rewrote the pvid command around the
new port-separator and atoi helpers, next to the line where this branch
delegates "stp" to stp_parse(). Both belong, so the STP delegation keeps
main's pvid body.
The linker caught what the merge could not see: main changed atoi_byte()
to return the digit count and leave the value in atoi_results_u8, where
it used to return non-zero on failure and write through a pointer. Note
the sense is inverted, so the three calls in rtl837x_stp.c are adjusted
rather than just re-arranged.
This branch moved rtl837x_pins to the common window in eaff953 to reclaim
BANK2 for the per-port status work, which was free at the time because the
module was only the I2C and GPIO pin helpers.
main has since put the SFP EEPROM transfer there, so the module now weighs
934 bytes and the common window is 156 bytes short. BANK2 has room for it
again, and that is where main keeps it.
Common segment +934 bytes, BANK2 -934.
Only httpd.c conflicted: main added the buffered configuration upload
next to the pointers this branch had moved into xdata to free internal
RAM. Both belong, so the new globals sit above declarations that keep
their storage class.
All entry points are already __banked and none of the code runs in
interrupt context, so the module can leave the resident bank. This
relieves pressure on bank 0, which no longer fits a machine with a
custom init table.