aboutsummaryrefslogtreecommitdiffstats
path: root/link/link-protocol.h
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-29 15:59:44 +0100
committereunhhu <[email protected]>2026-09-29 15:59:44 +0100
commitd0be140549b67708039f3c69d0b039440eb3a063 (patch)
treed2e383df098dda3d54a4760f65856166bb5e8f19 /link/link-protocol.h
parentccf35df074bcb450ebdc56eb27762a9096252a3f (diff)
downloadpure-d0be140549b67708039f3c69d0b039440eb3a063.tar.gz
pure-d0be140549b67708039f3c69d0b039440eb3a063.zip
Say LOST when a run's epoch is not known, and let its sender begin again at once
A receiver that started again without its memo could open none of its senders' packets (their epochs were gone), said nothing, and each sender waited 2 s and four probes, then offered with no records. Worse, those packets failed to open, so each cost a token (256 a second, the flood guard): ten thousand senders came back 256 a second. M2 without a memo stopped 0.8 s and caught up in 7.7 s. Now the receiver answers a packet of a run it does not know, in an epoch past 0, with LOST: sealed in epoch 0 under the nodes' keys, naming the packet. As QUIC's stateless reset, it is smaller than the packet and comes out of a bucket of its own (4,096 a second). A sender that has that packet out begins again as a run begins: epoch 0 with its records at once, epoch 1 offered. Only the receiver can say LOST, and one of the past names a packet no longer out; silence alone (an attacker's doing, maybe) still gets offers only. Such a packet costs no key token: no keys were made for it, and the secret made is remembered, once a sender. M2 without a memo (ten thousand devices, twice): no 100 ms step stopped, caught up in 0.4-0.5 s, p99 5.8-5.9 ms, the most 48-57 ms (was 4.1 and 7.8 s). test-link: a changed packet may get a LOST smaller than itself and nothing else; half of a flood in epoch 1 got 267 LOSTs, 12 KB for its 6 MB; a record goes under the nodes' keys after an epoch began only after the receiver forgot, until the next epoch.
Diffstat (limited to 'link/link-protocol.h')
-rw-r--r--link/link-protocol.h20
1 files changed, 14 insertions, 6 deletions
diff --git a/link/link-protocol.h b/link/link-protocol.h
index b2995e5..25ff12f 100644
--- a/link/link-protocol.h
+++ b/link/link-protocol.h
@@ -38,18 +38,24 @@
* go. The sender seals in it from the ACCEPT on; the receiver takes it once
* a packet of it opens, and opens the late ones of the epoch before. So what
* went in epoch 1 and on cannot be opened by one who later has both nodes'
- * keys: only a run's first packets, before its first answer, are sealed
+ * keys: only a run's first packets, before its first epoch, are sealed
* under the static keys. A new epoch every hour or GiB
* (pure_link_sender_epochs). A receiver that remembers (pure_link_remember)
* writes the epoch it accepted for each sender's run, and goes on in it after
- * it starts again; a sender that hears nothing for 2 s over 4 probes (the
- * receiver forgot) offers again in epoch 0, with no records, and the chain
- * begins again from the nodes' keys.
+ * it starts again. One that does not know a run's epoch (it forgot) answers
+ * its packet with LOST, under the nodes' keys, naming the packet: its
+ * sender, if the packet is one it has out, begins again as a run begins, in
+ * epoch 0 with records until an epoch is accepted. A sender that hears
+ * nothing for 2 s over 4 probes (an attacker may keep the answers from it)
+ * offers again in epoch 0 with no records, and the chain begins again from
+ * the nodes' keys.
*
* What an attacker on the path may do, and what it gets (link/test-link.c
* does each):
- * - change a packet: it does not open, and it is answered by nothing
- * (a packet is opened before it is looked at).
+ * - change a packet: it does not open, and it is answered by nothing but,
+ * when its run is one the receiver does not know in an epoch past 0, a
+ * LOST (as QUIC's stateless reset: smaller than the packet, LOSTS a
+ * second at most, telling nothing but that).
* - send a packet of the past again: its records are applied once (the
* heard numbers), its word is taken only as the most said (STORED's
* limit), and it moves nothing: answers go where the newest packet of
@@ -98,6 +104,8 @@
* same; one a second for a sender), then the first four
* bytes of the key offered it answers (a sender that took
* its epoch for lost offers epoch 1 again with another)
+ * 0x0b LOST u64 a packet's number: a receiver knows no epoch of its run
+ * (sealed in epoch 0, in a run of answers of its own)
* 0x00 PADDING to the end of the packet: a full packet sent in a burst is
* a whole datagram
* Losses are detected as RFC 9002 says, with RACK's patience for packets