Repository navigation
colibri 0.11.0: BBRv3, PEM files and DNSSEC checks
colibri 0.11.0 runs BBRv3 on each QUIC connection by default, and CUBIC stays a choice. It reads the PEM files an operator holds, checks DNSSEC signatures in a new dnssec module, and sends more request content from the program's memory with no copy. It pins chapulin f59c7e3f and stdx 5fd03aa.
Breaking changes
- Each module's constants are grouped by who sets them (decision 137):
protocolfor what the RFCs fix,limitsfor the bounds colibri chose,policyfor the other values colibri chose, and one file for each algorithm.quic.constants.frame_ackbecomesquic.constants.protocol.frame_ack, and the same holds for every module. - A QUIC connection runs BBRv3 (draft-ietf-ccwg-bbr-06) by default, where 0.10.0 ran CUBIC (decision 143).
server.Config,client.Configandquic.Connection's options take.congestion_controller = .cubicto keep CUBIC. Under BBRv3 a connection draws its probe waits from the sourceinittakes (decision 136). - A program with its own
tls_provider.Providermust fillNegotiated.group(decision 140) and givewritable_lenandencrypt_parts(decision 139). - A response whose Content-Length is larger than its
bodyendstoo_largeat its head (decision 124 as amended). h11 closes the connection, and h2 and h3 reset the stream. Before, colibri read and dropped the whole content. - Each session and connection is larger:
tls.record.Clientgrows from 40,968 to 49,800 bytes,quic.Connectionfrom 176,888 to 208,304 bytes, andserver.Endpointat its default capacity from 51,310,368 to 52,422,080 bytes.tls.constants.limits.anchors_maxis 256. docs/performance.md lists each size.
What's new
quic.CongestionControllerselects BBRv3 or CUBIC. BBRv3 keeps its model of the path from delivery rate samples, moves through Startup, Drain, ProbeBW and ProbeRTT, and undoes a spurious loss episode. spec/lean proves its arithmetic, and spec/tla/bbr checks its states.tls.pemreads a certificate chain, a P-256 key and a CA bundle from PEM (RFC 7468, decision 141).tls.P256Keyholds the key.- The new
dnssecmodule checks DNSSEC signatures and DS digests through chapulin:dnssec.verify,dnssec.Hash,dnssec.Algorithmanddnssec.DigestType(decision 142). tls_provider.Negotiated.groupandtls.quic.Client.negotiated()report the key-exchange group beside the cipher suite (decision 140).quic.PeerAddress.scope_idcarries an IPv6 address's interface, so a pool dials a link-local address (RFC 9000 §9).h2.Connection.write_data_headerwrites a DATA frame's header for data the caller writes after it (decision 138).
Fixes
- A cancel during a handshake that then failed left the pool's attempt open, so the next request ended refused with no connection opened (#100).
Speed
The judge's bulk run downloads a file of 2 MiB over h3 through a bottleneck of 20 Mbit/s and 25 ms (design §8 steps 13k and 29c.2):
- At 1% loss from one connection, BBRv3 gives 14.5 to 14.8 Mbit/s, and CUBIC 1.7. From four connections, BBRv3 gives 17.1 Mbit/s, and CUBIC 8.1.
- With no loss and four connections, a small GET's p99 beside the download is 186 ms under BBRv3, and 509 to 718 ms under CUBIC.
- When the two share the bottleneck with no loss, CUBIC takes about 0.82 of it. #123 tracks CUBIC's goodput at 1% loss.
- The h11 client sends request content from the program's memory, and the h2 client seals each DATA frame from two slices over TLS and writes its data after the header in cleartext (decision 139).
Checked
GitHub's main workflow passed on 83c922b1 (run 41306132768), and tools/ci.sh passed all 38 sections on it.