aboutsummaryrefslogtreecommitdiffstats
path: root/research/experiments/019-idle-links/links.c
Commit message (Collapse)AuthorAgeFilesLines
* Move M2's node to another machine under load (M3's harness)eunhhu2026-09-291-5/+37
| | | | | | | | | | run.py --restart --move runs in namespaces of its own (unshare -rmn: a network and an /etc/hosts): the devices send to receiver.test, which names 127.0.0.2; at --kill-at the node is killed, its store, key and memo copied elsewhere, 127.0.0.2 made unreachable, the name pointed at 127.0.0.3, and the copy started there. The load generator's devices look for the node again as link/link.c does: after three probes in a row unanswered, or a send the system said had no way there.
* Move a link to a new epoch now and then, so keys that leak later open ↵eunhhu2026-09-291-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | nothing past A sender offers the public half of a pair made for the next epoch (OFFER) until the receiver accepts with a half of its own (ACCEPT); their X25519 and the epoch's secret make the next one's, and the private halves go. The header's low four bits say a packet's epoch; epoch 0 is the nodes' static secret, as the keys were. The first epoch is offered in the run's first packet (it begins with the first answer when the receiver is not busy), then one an hour or GiB. One who later has both nodes' keys opens only epoch 0, and no record went there after an epoch began: test-link tries every packet sent under the static keys, with epochs a second long, loss, reordering, restarts and replays. The receiver writes the epoch it accepted in its memo (a place is 256 bytes now), so it goes on without an X25519 when it starts again; one that forgot is not heard from, and its senders, after 2 s and four probes unanswered, offer again in epoch 0 with no records until an epoch begins. Keys of four epochs are tried (accepted, now, before, zero), as two may share the four bits. An accept costs an X25519 on each side, 220 µs on this Pi: one of a sender with records costs a token (256 a second, 8 at once) and the next packet offers again when there is none; one of a sender with nothing else to send waits for none, one a second for it. The X25519 is made after the turn's answers, never between a packet and its answer. serve's report and M2's generator count keys, X25519s and epochs.
* Give M2's devices a timer each, and say when the slow records were madeeunhhu2026-09-291-7/+34
| | | | | | | | | | | The load generator asked all ten thousand senders for their timers every 5 ms: 83 % of its CPU (47 ns a sender, mostly cache misses), and records were timed from the start of that pass, so the pass (0.75-0.94 ms, longer as the sender grew) was the floor of every latency it measured. A device now keeps its sender's next timer, asked again only when the sender is touched (the only time it changes), and the p50 of M2 falls from 0.8 to 0.4 ms for every version alike. It also says the p50 and p99 of the records made in each second, and the keys and X25519s its senders made.
* Find how large a packet the path carries: 1,452 bytes once a probe is ↵eunhhu2026-09-291-2/+2
| | | | | | | | | | | | | | | acknowledged A link starts at 1,200 bytes; once an RTT is known it sends a PING padded to 1,452 (DPLPMTUD, RFC 8899), alone and with the don't-fragment bit, and uses that size once it is acknowledged. A probe lost is no congestion; it is tried again a second on, three times, then ten minutes on. GSO is asked for each burst (a control message), not the socket, so a packet sent alone is never cut. CUBIC counts in the datagram. On loopback packets fall by 19-27%; the CPU a record falls 13% at 1 KiB and 7% at 16 KiB; in the simulator of a 50 Mbit/s path with 1% loss the goodput rises from 6.1 to 7.0 Mbit/s (5%: 2.3 to 3.0).
* Make the load generator's devices real link senders, many on one threadeunhhu2026-09-291-374/+146
| | | | | | | | | | links.c was a second implementation of the packet format; each device is now a PureLinkSender on a socket of its own, keyed with a secret made outside (pure_link_sender_shared: a key kept elsewhere, or a test's many). M1 (1k, 10k) and M2 (10k, kill -9) pass with it: no silent step, caught up in 0.2 s, every order applied once; the slowest store after the restart is now the sender's 1 s wait for a word of the save (STORED_WAIT), where the old devices tried again after 200 ms.
* Put the links and the crypto they use in link/, a part of their owneunhhu2026-09-291-2/+2
| | | | | libpure-link.a holds them; pure-serve and the M5 harness link it instead of naming its source files.
* Measure a link at rest: 132 bytes against a QUIC connection's 38,106 (094)eunhhu2026-09-281-0/+624
M1 of design 011. A Pure node allows 1,000 to 1,000,000 senders; each sends one order and, once told it is stored, rests. At rest a link costs the node 132 bytes (the sender allowed, 73; its number heard, about 60) and no transport state; with a million the node runs in 139 MB. A quinn 0.11 service holding the same exchange's clients connected at rest costs 38,106 bytes a connection: 289 times as much, past the design's 1/100. A link at rest takes its next record in 0.56 ms to stored, one X25519 on the node included; a new QUIC connection takes 1.06 ms and 2.8 times the receiver's CPU, without storing. research/experiments/019-idle-links: links.c, many senders written from serve/link.h's packet format alone (a second implementation), and the quinn service and clients (quic/, built offline); run.py makes both measurements.