Commit Graph

2554 Commits

Author SHA1 Message Date
Timon 08e26ce3fd Update docs/book/src/quinn/certificate.md
Co-authored-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
2021-01-18 09:30:32 +01:00
Timon ce456c3291 Apply suggestions from code review
Co-authored-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
2021-01-18 09:30:32 +01:00
Timon 58fb1721a7 Update docs/book/src/quinn/certificate.md
Co-authored-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
2021-01-18 09:30:32 +01:00
Timon Post b35df59298 round 2 2021-01-18 09:30:32 +01:00
Timon Post 70df232673 edit 2021-01-18 09:30:32 +01:00
Timon Post 386a2f24b0 Edit certbot section 2021-01-18 09:30:32 +01:00
Timon Post 0ea2a1bcab review round 1.0 2021-01-18 09:30:32 +01:00
Timon Post 82eb52ca5a merge introduction with this chapter 2021-01-18 09:30:32 +01:00
Timon Post 3fecf00890 Write certificate configuration chapter 2021-01-18 09:30:32 +01:00
Matthias Einwag 99649bf00f Congestion controller fixes
This change fixes 2 issues in the congestion controller:

Extra slow slow start
===

The congestion controller had an issue where it didn't ramp up by
doubling the window in the slow start phase as expected. The reason
here was the usage of the "congestion_blocked" field, which aims to
remove the avoid growing the window when there is no data to send.
The issue with the field was that the first incoming ACK for every batch
would increase the congestion window, which would let the next
call to `congestion_blocked()` return false, and thereby let the
congestion controller ignore all of the following ACKs in a received
batch up the point where the next `poll_transmit()` call is made and
the window is filled again. Since often all ACKs for one round-trip
arrive in a single batch that means only the first ACK had an effect
and the others where ignored -> which lead to increasing the
window by 1 MTU instead of doubling it in the slow start phase.

The new approach introduces a new `app_limited` field which
caches whether the last `poll_transmit` attempt couldn't produce
data because there was no application data available.

Numeric precision issue in congestion avoidance
===

The formula
```
self.window += self.config.max_datagram_size * bytes / self.window;
```
which is specified in the RFC requires floating point arithmetic.
If integer arithmetic is used, the multiplication of the first 2 values
yields about 1.7MB for 1300 byte packets. As soon as the window is
bigger than this value, the window won't change at all due the
division leading to 0.

The new implementation follow this guidance from the quic recovery
specification:

> In congestion avoidance, implementers that use an integer
> representation for congestion_window should be careful with division,
> and can use the alternative approach suggested in Section 2.1 of
> [RFC3465].
2021-01-14 20:23:12 -08:00
Matthias Einwag 1a544c37de Add recovery stats as part of ConnectionStats
This is an alternative version of #972, where we add the new stats
to ConnectionStats instead of exposing additional accessors.

The naming of `recovery` could probably be improved. `path` might
be an option. But where would we add something like packet loss?
That seems more like an overall stat.
2021-01-10 08:03:00 +01:00
Matthias Einwag 8722506c3b Rx frame stats
This adds frame stats for the receiving part, which had been
missing so far.
2021-01-09 08:01:09 +01:00
Dirkjan Ochtman 13f1169286 quinn-proto: generalize over read methods 2021-01-07 07:21:48 +01:00
Jean-Christophe BEGUE 69c620ac8f Read multiple chunks into a slice of Bytes 2021-01-06 21:51:17 +01:00
Jean-Christophe BEGUE 5754b3c67a Factorize proto read methods 2021-01-06 21:51:17 +01:00
Jean-Christophe BEGUE d19fee11fe Read ordered chunks from RecvStream 2021-01-06 21:51:17 +01:00
Timon Post a149c5d642 Logo update to static link. 2021-01-06 15:26:39 +01:00
Matthias Einwag 1ca7149de1 Allow to use the incoming IP address for sending outgoing packets
This is a follow-up for #943. When a socket is bound to a wildcard
IP address, sending the outgoing IP might use a different source IP
address than the one the packet was received on, since the OS might
not be able to identify the necessary route. This would lead packets
not allowing to reach the client.

This change adds a setting which will set an explicit source address
in all outgoing packets. The source address which will be used is
the local IP address which was used to receive the initial incoming
packet.
2021-01-06 09:57:13 +01:00
Benjamin Saunders 42fd00c20d Store MTU per-path 2021-01-06 06:58:43 +01:00
Benjamin Saunders af1effdedb Tweak naming/docs/signature 2021-01-06 06:58:43 +01:00
Benjamin Saunders 7436eb2d1b Replace inappropriate wrapping arithmetic 2021-01-06 06:58:43 +01:00
Benjamin Saunders a1223601ed Apply anti-amplification when peer migrates
Defends against amplification attacks where an existing connection is
hijacked by modifying the source address of a legitimate packet, as
required by the spec. Previously we only defended against similar
attacks involving brand new connections being created by an attacker.
2021-01-06 06:58:43 +01:00
Benjamin Saunders a01a4fa168 Check stream flow control correctness against issued credit
Previously, we checked against a quantity that might not have actually
been communicated to the peer yet, which would cause us to tolerate
illegally optimistic peers.
2021-01-05 13:52:11 +01:00
Benjamin Saunders a012a8829d More accurately track issued stream-level flow control credit 2021-01-05 13:52:11 +01:00
Benjamin Saunders bc3c07372a Improve robustness to large connection-level flow control 2021-01-05 13:52:11 +01:00
Benjamin Saunders a2e9dfc374 Validate flow control compliance of RESET_STREAM final offset 2021-01-05 13:52:11 +01:00
Benjamin Saunders 21b4988cd6 Factor out flow control validation from Recv::ingest 2021-01-05 13:52:11 +01:00
Benjamin Saunders 75634cce5d Represent reset final offset field with VarInt
Preserves constraints imposed by the wire encoding.
2021-01-05 13:52:11 +01:00
Benjamin Saunders c6cdbd2c46 Move final offset validation inside streams::Recv 2021-01-05 13:52:11 +01:00
Matthias Einwag 115fe2349c GSO platform support
This splits out the platform/socket parts for UDP GSO support
from #953 to reduce the amount of code to review.

This change mainly implements setting the segment size
socket option, and adds a runtime detection mechanism for
GSO support.
2021-01-05 13:42:23 +01:00
Jared Fowler 9b5d5b35a3 Fuzz packet decoding (#885) 2021-01-03 21:51:53 +01:00
Dirkjan Ochtman 9b19e23a68 Update link to native Gitter channel 2021-01-03 12:04:34 -08:00
Dirkjan Ochtman 79361e29b4 Tweak CidState::track_lifetime() style 2021-01-02 12:52:11 -08:00
Wenjie Li 6b3656630f Proactive CID rotation (#860) 2021-01-02 21:33:18 +01:00
Dirkjan Ochtman 17fe82b598 Apply clippy fixes for 1.49 2021-01-01 11:16:05 -08:00
Benjamin Saunders 70ba6b78a1 Add missing traits to UnknownStream errors 2021-01-01 14:25:50 +01:00
Benjamin Saunders 1717e9ad81 Return UnknownStream errors more consistently
Previously, these sometimes depended on whether the peer had
acknowledged an operation, which might lead users to incorrectly
believe that attempting to operate on a stream after stopping or
resetting it is sane.
2021-01-01 14:25:50 +01:00
Benjamin Saunders bd1c5b34d5 Tweak unknown stream error docs 2021-01-01 14:25:50 +01:00
Matthias Einwag 62ef3cc1f2 Allow to show connection stats in bulk benchmark
This allows to determine the impact of particular changes a
bit easier.

Example output:

```
Overall stats:

Sent 1073741824 bytes on 1 streams in 4.04s (253.61 MiB/s)

Stream metrics:

      │  Throughput   │ Duration
──────┼───────────────┼──────────
 AVG  │  253.56 MiB/s │     4.04s
 P0   │  253.50 MiB/s │     4.04s
 P10  │  253.62 MiB/s │     4.04s
 P50  │  253.62 MiB/s │     4.04s
 P90  │  253.62 MiB/s │     4.04s
 P100 │  253.62 MiB/s │     4.04s

Server connection stats:
ConnectionStats {
    udp_tx: UdpStats {
        datagrams: 26391,
        bytes: 1110961,
    },
    udp_rx: UdpStats {
        datagrams: 918524,
        bytes: 1116003172,
    },
    frame_tx: FrameStats {
        ACK: 26388,
        CRYPTO: 6,
        DATAGRAM: 0,
        HANDSHAKE_DONE: 4,
        MAX_DATA: 0,
        MAX_STREAM_DATA: 4984,
        MAX_STREAMS_BIDI: 0,
        MAX_STREAMS_UNI: 1,
        NEW_CONNECTION_ID: 16,
        PATH_CHALLENGE: 0,
        PATH_RESPONSE: 0,
        PING: 0,
        RESET_STREAM: 0,
        RETIRE_CONNECTION_ID: 3,
        STOP_SENDING: 0,
        STREAM: 0,
    },
}

Client connection stats:
ConnectionStats {
    udp_tx: UdpStats {
        datagrams: 918556,
        bytes: 1116042037,
    },
    udp_rx: UdpStats {
        datagrams: 26391,
        bytes: 1110961,
    },
    frame_tx: FrameStats {
        ACK: 918554,
        CRYPTO: 2,
        DATAGRAM: 0,
        HANDSHAKE_DONE: 0,
        MAX_DATA: 0,
        MAX_STREAM_DATA: 0,
        MAX_STREAMS_BIDI: 0,
        MAX_STREAMS_UNI: 0,
        NEW_CONNECTION_ID: 5,
        PATH_CHALLENGE: 0,
        PATH_RESPONSE: 0,
        PING: 0,
        RESET_STREAM: 0,
        RETIRE_CONNECTION_ID: 0,
        STOP_SENDING: 0,
        STREAM: 918552,
    },
}
```
2021-01-01 14:23:40 +01:00
Benjamin Saunders bc0648a518 Fix outdated docs 2021-01-01 08:22:52 +01:00
Benjamin Saunders 61a72a3836 Limit concurrent connections rather than accept queue size
Enables stronger latency guarantees, along the same lines as the
nearby change to streams.
2021-01-01 08:22:16 +01:00
Matthias Einwag 62a88008a7 Make connection stats public
So far those haven't been consumable by applications.
This makes the struct public, and adds an accessor
for `quinn_proto::Connection` and `quinn::Connection`.
2020-12-31 12:03:20 -08:00
Matthias Einwag de627437bc Don't assume that the send buffer capacity is exactly the MTU
Reserving capacity can provide more capacity than we asked for.
However we are not allowed to write more than MTU size. Therefore
the maximum allowed capacity is tracked separately.
2020-12-30 07:33:12 +01:00
Matthias Einwag 3c55123a9c Use initialized CMSG data on sending
The outgoing cmsgs can't be uninit because it breaks `CMSG_NXTHDR`.
The function will try to access the next cmsg in the buffer at
https://github.com/rust-lang/libc/blob/ae65df55fe2d0e1348fed575bfc8c0c3e4744c65/src/unix/linux_like/linux/mod.rs#L2585-L2589

This will yield an undefined result, and can let `CMSG_NEXT` return `None`.
This prevents more than 1 CMSG to be encoded. 0-initializing the
messages makes sure a length of 0 is read, and fixes the issue.

In addition this change improves an assert in the cmsg encoder, which
makes it easier to determine the required CMSG space.
2020-12-30 07:33:12 +01:00
Matthias Einwag 1aaff731ab Extend bulk benchmark
This change improves the bulk benchmark:
- The total amount of requests the benchmark performs can be configured
- The amount of concurrent requests on a given connection can be
  configured
- The amount of data to transfer per stream can be configured

E.g.

```
bulk --streams 300 --max_streams 100 --stream_size 10
```

will create 300 streams - with a maximum of 100 active streams at a time,
and send 10MB of data on each stream.

The "short" cli flags are taken form h2load where applicable.

The benchmark now also shows metrics which indicate the performance
of individual streams, which allows to judge fairness. Example output:

```
Overall stats:

Sent 3145728000 bytes on 300 streams in 12.11s (247.81 MiB/s)

Stream metrics:

      │  Throughput   │ Duration
──────┼───────────────┼──────────
 AVG  │  149.17 MiB/s │  396.00ms
 P0   │    0.83 MiB/s │   39.00ms
 P10  │   51.19 MiB/s │   40.00ms
 P50  │  129.75 MiB/s │   77.00ms
 P90  │  247.00 MiB/s │  195.00ms
 P100 │  254.75 MiB/s │    12.11s
```
2020-12-29 15:15:43 +01:00
Matthias Einwag 6d32b64d4c Extract data sending in bulk benchmark
This change moves establishing a stream and sending data into
a separate method.
2020-12-29 15:15:43 +01:00
Matthias Einwag 1bc75aa014 Allow to lookup the initial local IP address
When a listener is bound to multiple network interfaces (e.g. `::0`),
it is not obvious which IP the peer used to send a packet. We however
might need this information to send packets back to the peer with the
same source address.

This problem is described in #508.

This change makes the destination IP address which was used to send
the initial packet available in the `Conneting` and `Connection` types.

The information is far available only on Linux due to missing test on
other platforms.
2020-12-29 14:53:39 +01:00
Matthias Einwag 64c97b6af0 Extend benchmark for concurrent streams
This extends the "cargo bench" benchmark to test transmission of data
on multiple streams in parallel.

Ideally we would want all transmission to take a similar amount of time
(bandwidth shared fairly), and the overall throughput to stay the same
or increase (but never degrade) when multiple streams are in use.

The benchmark can not show the fairness aspect very well, since it only
prints an overall throughput. But it shows that performance with
multiple streams stays similar.

Output:

```
running 4 tests
test large_data_10_streams  ... bench: 180,761,260 ns/iter (+/- 12,090,679) = 58 MB/s
test large_data_1_stream    ... bench:  18,459,500 ns/iter (+/- 3,804,219) = 56 MB/s
test small_data_100_streams ... bench:   4,600,890 ns/iter (+/- 373,842)
test small_data_1_stream    ... bench:      71,019 ns/iter (+/- 34,298)
```

I also increased the size of the LARGE_DATA payload from 128kB to
1MB, since 128kB didn't show quinn peak performance.
2020-12-28 14:05:12 +01:00
Matthias Einwag c004ef0329 Improve fairness on stream transmissions
The current version of send multiplexing tries to send as much data from
a single stream as possible before switching over to the next stream.
The only situation where data from another stream than the original one
is sent is if there are no peer flow control credits available anymore,
or if the application didn't feed new data.
If none of this situations occur, other streams will be starved.

This is typically not what people expect, and can lead to high latencies
on streams which are queued behind earlier streams.

This change makes the send behavior "fairer" by enqueuing stream which
just have sent data **after** all other pending streams instead of in
front of them. This is simply achieved by switching to a `VecDeque` and
using the the right insert/remove orders.

Stats (obtained via #946), when running

```
./bulk --streams 300 --max_streams 10 --stream_size 10
```

```
Stream metrics:

AVG : Throughput:  172.38 MiB/s, Duration:  395.00ms
P0  : Throughput:    0.83 MiB/s, Duration:   39.00ms
P10 : Throughput:   49.19 MiB/s, Duration:   40.00ms
P50 : Throughput:  232.50 MiB/s, Duration:   42.00ms
P90 : Throughput:  245.87 MiB/s, Duration:  203.00ms
P100: Throughput:  251.25 MiB/s, Duration:    12.08s
```

```
Stream metrics:

AVG : Throughput:   24.20 MiB/s, Duration:  413.00ms
P0  : Throughput:   21.42 MiB/s, Duration:  279.00ms
P10 : Throughput:   23.25 MiB/s, Duration:  403.00ms
P50 : Throughput:   24.34 MiB/s, Duration:  410.00ms
P90 : Throughput:   24.81 MiB/s, Duration:  430.00ms
P100: Throughput:   35.78 MiB/s, Duration:  466.00ms
```

With this change throughput on streams is a lot more consistent than
before.
2020-12-28 13:59:36 +01:00
Benjamin Saunders e151a5236c Fix state leak when a stopped stream is reset 2020-12-27 14:14:00 -08:00