mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
a96fdfe10c471cd04db86b76a53a57edd4c29684
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a96fdfe10c |
html: move the L2 table walk into a shared walkL2() helper
Both the L2 page and the ports page in #335 need to page through /l2.json and decode the same fields, and the second copy arrived carrying the two bugs the first one had only just been fixed for. Rather than keep two copies in step by hand, the transport and the decoding move to main.js, which every page already loads, and each page keeps only what is its own. walkL2(onDone) pages through the table once, parses idx and vlan out of hex, maps the port to a physical number or to 'CPU', and calls onDone(entries, ok). It stops on a wrapped index, an empty page or 4096 entries, all of which set ok. A page that comes back as anything other than 200, or with a body JSON.parse rejects, is asked for again at the same index up to three times; only once those run out does the walk end with ok clear, so a caller can tell a finished table from a partial one. l2.js keeps the s and l to label mapping, since that needs the page's own translations, redraws only when ok is set, and restarts the walk from its callback either way. Two things change while moving: The next request goes out from the previous reply rather than from a setInterval that fires whether or not the last one came back. The httpd serves one connection at a time, so a timer that outruns the responses only queues work it cannot use. A walk that reaches 4096 entries hands over what it collected. Before it threw the entries away and cleared its own interval, which left the page unable to refresh again until it was reloaded. The retry is not a new idea, it is the old behaviour written down. The previous code ignored anything that was not a 200 and let the interval ask for the same index again, so a blip never disturbed the table on screen. Dropping that on the way to a chained walk would have made every timeout redraw the page with a truncated table, which at one connection at a time is not a rare event. Driven with a scripted server in node, running the helper itself rather than a copy of it: an empty table gives 0 entries in 1 request; three pages ending in a repeated index give 61 entries in 3 requests, asking for 0, 30 and 60; an empty page ends the walk after 2; a 500 and a malformed body are each retried at the same index and then complete normally, asking 0, 30, 30 and 31; three failures in a row end the walk with ok clear and the 30 entries already collected; 4096 entries in one page end it with ok set; the CPU port decodes to 'CPU'; vlan and idx come back as numbers. main.js grows by 1331 bytes and l2.js loses 1039, so 292 bytes of flash. Worth stating where they land: main.js is loaded by every page, so pages that never walk the table now carry the helper too. That is the cost of having the decoding exist exactly once, which is the point of the move. |
||
|
|
3be6667789 |
httpd: emit valid JSON from send_l2
The MAC table listing wrote its separator once per iteration rather than once per object. An entry the table engine reports as invalid produces no object, so it contributed a bare comma, and two in a row give ",," which JSON.parse rejects. The whole table then fails to load, not just the row that was missing. The separator now goes before each object and the closing bracket after the loop, which is the shape send_vlanlist already uses further down the file. The next index for an invalid entry was computed as h | low + 1, and the addition binds tighter than the or. That agrees with (h | low) + 1 except when the low byte reads 0xff and bit 8 of the index is already set, eight of the 4096 combinations. There the result is the start of the current block of 256 rather than the start of the next one, so the walk repeats a block it has already covered. Reading the index once after the branch rather than once in each arm removes the second copy of that expression along with the bug. The VLAN now comes first in each object. It is taken from the same L2_DATA_OUT_B read that decides whether the entry is valid, which saves reading that register a second time. The page addresses the fields by name, so the order they arrive in does not matter to it. A bound check on the output buffer goes in for consistency with send_vlanlist. Thirty entries of at most 74 bytes plus the brackets fit in the 2500 byte buffer with 179 to spare, so nothing changes today, but the margin was nowhere stated and L2_MAX_TRANSFER is a tunable. 5 bytes of BANK1, nothing in BANK2, xdata or internal RAM. Built for SWTGW218AS and KP_9000_6XHML_X2 on sdcc 4.5.0. |
||
|
|
59c60504e7 |
crtbank: put the bank switching helpers in HOME
__sdcc_banked_call and __sdcc_banked_ret were assembled into GSFINAL, which sits in the startup path: GSINIT ends exactly where GSFINAL begins, so the processor falls into it rather than being sent there. It works today only because this object comes after every C object on the link line, so the LJMP to __sdcc_program_startup is laid down first and the helpers land behind it. Reordering that line, or moving main() into another module, would put the helper body at the fallthrough address instead, and the board would not come up out of a build that reports nothing wrong. SDCC's own crtbank.asm declares the area order and then puts both symbols in HOME, so the file takes that name and that preamble as well. GSFINAL now holds the three byte jump and nothing else. Of 401 symbols 17 change address, every one in the startup region, and between the reset vector and 0x0094 not a byte differs, so no interrupt vector is disturbed. Run on a SWTGW218AS: it came back after about 42 seconds reporting the new build, with its stored configuration byte identical and every link at the speed it had before. |
||
|
|
f2c6ac01d9 |
port: read a trunk's members through one function
The member mask of an aggregation group is decoded by hand in two places, the lag command and the JSON behind the aggregation page, and every branch that touches trunks adds another copy. port_lag_members_get() sits next to port_lag_members_set() and both readers call it. It answers from the hardware, so it covers a group configured with lag and one a protocol brought up, without either having to say so. It reads through reg_read() rather than reg_read_m(), so sfr_data is left alone. Neither caller looked at it afterwards; both read the hash register next. |
||
|
|
4ff009dbfc |
uip: cap TCP MSS to 1460 to survive jumbo-MTU clients (#298)
* uip: parenthesise UIP_LLH_LEN The macro expands to a bare sum, so wherever it is subtracted the second term gets added instead. UIP_TCP_MSS - and with it UIP_RECEIVE_WINDOW - therefore comes out 24 bytes above the buffer's real capacity. UIP_APPDATA_SIZE and UIP_REASS_BUFSIZE are wrong the same way, though neither is reachable today. The additions, uip_buf[UIP_LLH_LEN] and friends, were right by luck. * uip: keep the advertised MSS below the buffer edge Deriving the MSS straight from the buffer size makes the switch advertise exactly the segment that fills uip_buf to its last byte, and a peer that takes it literally corrupts every large upload: the firmware image arrives fully acknowledged, with no retransmissions on the wire, yet the CRC over the streamed body never matches and the flash write is abandoned. Isolated by changing nothing but the segment size, same buffer and same file: 1490-byte segments fail four times out of four, 1460-byte segments succeed, 745-byte segments succeed. Linux halves its segments against a window this small, so only macOS on a jumbo link ever produces a full-size segment - which is why the failure hides so well. Where exactly the full segment breaks the stream is not pinned down yet; until it is, the advertised MSS stays a step below the edge. * uip: size the buffer to the largest frame the CPU port accepts UIP_TCP_MSS derives from UIP_CONF_BUFFER_SIZE, and the buffer was large enough for frames the hardware will never deliver, so the switch advertised a segment size no peer could usefully reach. A client on a jumbo-MTU link took it at its word and the oversized replies went nowhere. Size the buffer to the ingress limit instead. ICMP bypasses MSS and so probes the hardware directly: on a SWTGW218AS a 1502-byte payload is answered and 1503 never arrives, which puts the largest frame the NIC hands us at 1556 bytes of uip_buf. UIP_TCP_MSS then derives to 1490, the same edge measured over TCP. Frames above the limit are dropped by the NIC rather than written to the buffer - an 8 kB ping leaves the switch untouched - so nothing overruns it. Frees 644 bytes of XDATA. * uip: trim these comments, one of which had stopped being true The note above UIP_CONF_BUFFER_SIZE claimed the MSS derives from it as 1490. It does not: the commit that follows pins the MSS at 1460 on purpose, a step below that ceiling, because a segment filling the buffer to its last byte corrupts large uploads. Left as it was, the file argued with itself. Both blocks are shorter now. What justifies the numbers stays, which is the ICMP measurement behind 1556 and the four-out-of-four failure behind 1460. What went is the storytelling around them, which belongs in this thread rather than in a config header. * uip: derive the MSS from the buffer again, minus explicit headroom The review asked why the buffer size and the MSS are both set by hand when one used to follow from the other. They answer different questions, but the gap between them is a number in its own right, so it gets a name now: UIP_CONF_BUFFER_EXTRA, and UIP_TCP_MSS goes back to being derived. The headroom is where the measurement lives. A segment that fills uip_buf to its last byte corrupts large uploads: with nothing but the segment size changing, 1490 fails four times out of four and 1460 succeeds. With the buffer sized to the frame the NIC accepts, an extra of 30 lands on 1460. Deriving it the other way round does not work. Sizing the buffer from a 1460 byte MSS gives 1526, which is 30 bytes under the frame the NIC actually delivers. A 1502 byte ICMP payload occupies 1556 bytes of uip_buf and is answered today, and it would stop fitting. The generated image is byte for byte the same as the one with 1460 written out, so the expression lands on the value that was measured. --------- Co-authored-by: d00f <tokyusho@chatik.pl> |