Summary:
There are many files in this diff, but the relevant ones are:
* quic/api/QuicSocket.h
* quic/api/QuicSocketLite.h
* quic/api/QuicTransportBase.h
* quic/api/QuicTransportBaseLite.cpp
* quic/observer/SocketObserverContainer.h
The purpose of this is to include the observer functionality within the Lite class. Ideally, we'd remove it from the Lite class, but that's going to require some more detailed changes to the interfaces we're using, because observers are used quite a lot within common code (for example, AckHandlers.cpp).
I'll make those changes some time after the QuicTransportBase split, as they're going to take a while.
Reviewed By: jbeshay, mjoras, kvtsoy
Differential Revision: D65685667
fbshipit-source-id: feb07bcf35d6af2e5c2b538ff463b01b67c6aff9
Summary: This diff provides access to the underlying socket in a quic network transport, which is used to update the network simulator configuration in a subsequent diff in this stack.
Reviewed By: kvtsoy
Differential Revision: D64691098
fbshipit-source-id: 349ee58038d232a8a454fa73e630872a26e73227
Summary: Presently updateWriteLooper will always schedule a loop callback to do the write loop. Add an option to inline trigger the writes after the read event.
Reviewed By: kvtsoy, sharmafb
Differential Revision: D62192192
fbshipit-source-id: 30991608f57fbfa097a7522c0731d25b8e528345
Summary: The prior `while (maxOffsetToDeliver.has_value()) {` was misleading because `maxOffsetToDeliver` doesn't change in the body of the while loop. I'm changing the structure so as to make it more intuitive as to what's happening here.
Reviewed By: hanidamlaj
Differential Revision: D61801508
fbshipit-source-id: fb91b183316b281cf74cbb33a67f7080e7d8a6f8
Summary: We have a lot of optionals that are either integral values or std::chrono::microseconds. These end up wasting memory, where we can instead store sentinel values to encode whether the value is there or not. This reduces the effective range of the type by one value, but that is an acceptable tradeoff.
Reviewed By: kvtsoy
Differential Revision: D57684368
fbshipit-source-id: b406b86011f9b8169b6e5e925265f4829928cc63
Summary:
The idea here is to make it so we can swap out the type we are using for optionality. In the near term we are going to try swapping towards one that more aggressively tries to save size.
For now there is no functional change and this is just a big aliasing diff.
Reviewed By: sharmafb
Differential Revision: D57633896
fbshipit-source-id: 6eae5953d47395b390016e59cf9d639f3b6c8cfe
Summary:
Adds a transport setting for the dscp value. The transport combines this value with the ECN flags to enable ECT0/ECT1 marking.
Previous use-cases that are setting dscp values by overriding the whole ToS field should still work, but they will override the ECN bits. This is still the default behavior. Applications willing to use ECN, should use the dscp transport setting instead of applying the tos socket option directly.
Reviewed By: mjoras
Differential Revision: D58203586
fbshipit-source-id: 7dd83ca82273fadd4ae03b015387143e02101b6c
Summary:
There are still some timestamps seen on dynamic content/connections and disabling timestamps per hostname doesn't scale well.
Instead, this diff will disable timestamps by default in Liger and enable only for static content connections based on a hostname filter (`scontent`, `video`, `cdninstagram`). The actual meat of the change is in `AdvancedHTTPSessionManager::shouldEnableQuicAckRxTimestamps` - everything else is mostly a replacement of disable to enable.
This is implemented for MNS in D58099124.
Reviewed By: jbeshay
Differential Revision: D58099125
fbshipit-source-id: 06118163fcc5d2e2ce90028810d6a9af5c7958a9
Summary: Use writable events on the socket (disabled by default)
Reviewed By: jbeshay
Differential Revision: D56305786
fbshipit-source-id: f04dea326587268c96915f7a39338ff21dee4aec
Summary: Adding another WriteCallback in the next diff
Reviewed By: jbeshay
Differential Revision: D56371737
fbshipit-source-id: 4918ca2af3e49968ca0822d7a99309a05021fd10
Summary:
This adds validation to verify that packets sent with an ECT(0/1) marks, are being echoed correctly by the client without any interference in the network path. If validation succeeds, the transport can use the ECN feedback in the congestion controller. If it fails, packet marking is disabled.
Ideally, the number of marks echoed by the peer in ACK_ECN frames should be equal to the number of packets sent with marks. However, that is not achievable with the current design due to the following restrictions:
- To be able to track the number of marks accurately, the sending transport needs to match incoming acks with the outstanding packets they are acking. However, the sending transport's list of outstanding packets only tracks retransmittable packets. Therefore, acks containing marks that refer to non-retranmittable packets cannot be verified.
- If the client is using GRO, we have one header for the whole batch. So echoed marking can be inflated.
To work around these limitations, the validation logic checks that:
- At least 10 retransmittable packets were sent with marks in the AppData packet number space.
- The number of echoed marks is greater than the number of retransmittable AppData packets sent with marks.
- The number of echoed marks is less than the total number of packets sent.
- No unexpected marks show up. I.e. No ECT0 when sending ECT1 or vv.
Reviewed By: kvtsoy
Differential Revision: D55618562
fbshipit-source-id: 8bc44b4f1b64725f51f63bb86d6c4bd573338e83
Summary:
Adds new transport settings for enabling quic sockets to read or write the tos/tclass field in the IP headers.
The new transport settings are: readEcnOnIngress, enableEcnOnEgress, useL4sEcn. All are defaulted to false.
readEcnOnIngress=true --> enabled reading the ToS field from incoming packets.
enableEcnOnEgress=false --> does not set marking
enableEcnOnEgress=true, useL4sEcn=false --> sets marking to ECT0
enableEcnOnEgress=true, useL4sEcn=true --> sets marking to ECT1
The next changes handle these packets in the rest of the stack.
Reviewed By: mjoras, kvtsoy
Differential Revision: D54877773
fbshipit-source-id: af6aefc714e2678f488d027583cf666200748782
Summary: So client conn can be queried
Reviewed By: mjoras
Differential Revision: D56787895
fbshipit-source-id: fbd76aed35910e36075739d3e6f1775d6600c225
Summary:
We currently do not make use of socket writeable events in mvfst (will be working on that soon), so we may end up in a situation where mvfst has pending data to write, but needs evb loop wake up to do so.
This change introduces a (immediate) timeout to wake up the loop right after it exits to write out the data we have left.
Alternative would be to make the packets per loop limit higher, but this _may_ be nicer given we do yield the loop for other things before waking it up again.
Reviewed By: jbeshay, mjoras
Differential Revision: D56224059
fbshipit-source-id: 2fc0f5000096def459c5d0cb98f6421d36ebbda4
Summary:
This is the major transition that updates mvfst code to use the new interfaces. The new Folly implementations of the interfaces maintain all the existing behavior of folly types so this should not introduce any functional change. The core changes are:
- Update the BatchWriters to use the new interfaces.
- Update the FunctionLooper to use the new interfaces.
- Change QuicServerTransport to take the folly types and wrap them in the new types for use in the QuicTransportBase.
The rest of the diff is for updating all the existing uses of the QuicTrasnport to initialize the necessary types and pass them to the QUIC transport instead of directly passing folly types.
Reviewed By: mjoras
Differential Revision: D51413481
fbshipit-source-id: 5ed607e12b9a52b96148ad9b4f8f43899655d936
Summary:
This diff renames `ReceivedPacket` to `ReceivedUdpPacket` to clarify that it maps to a UDP packet and not a QUIC packet. A single UDP packet can contain multiple QUIC packets due to coalescing.
--
This diff is part of a larger stack focused on the following:
- **Cleaning up client and server UDP packet receive paths while improving testability.** We currently have multiple receive paths for client and server. Capabilities vary significantly and there are few tests. For instance:
- The server receive path supports socket RX timestamps, abet incorrectly in that it does not store timestamp per packet. In comparison, the client receive path does not currently support socket RX timestamps, although the code in `QuicClientTransport::recvmsg` and `QuicClientTransport::recvmmsg` makes reference to socket RX timestamps, making it confusing to understand the capabilities available when tracing through the code. This complicates the tests in `QuicTypedTransportTests`, as we have to disable test logic that depends on socket RX timestamps for client tests.
- The client currently has three receive paths, and none of them are well tested.
- **Modularize and abstract components in the receive path.** This will make it easier to mock/fake the UDP socket and network layers.
- `QuicClientTransport` and `QuicServerTransport` currently contain UDP socket handling logic that operates over lower layer primitives such `cmsg` and `io_vec` (see `QuicClientTransport::recvmmsg` and `...::recvmsg` as examples).
- Because this UDP socket handling logic is inside of the mvfst transport implementations, it is difficult to test this logic in isolation and mock/fake the underlying socket and network layers. For instance, injecting a user space network emulator that operates at the socket layer would require faking `folly::AsyncUDPSocket`, which is non-trivial given that `AsyncUDPSocket` does not abstract away intricacies arising from the aforementioned lower layer primitives.
- By shifting this logic into an intermediate layer between the transport and the underlying UDP socket, it will be easier to mock out the UDP socket layer when testing functionality at higher layers, and inject fake components when we want to emulate the network between a mvfst client and server. It will also be easier for us to have unit tests focused on testing interactions between the UDP socket implementation and this intermediate layer.
- **Improving receive path timestamping.** We only record a single timestamp per `NetworkData` at the moment, but (1) it is possible for a `NetworkData` to have multiple packets, each with their own timestamps, and (2) we should be able to record both userspace and socket timestamps.
Reviewed By: silver23arrow
Differential Revision: D48788809
fbshipit-source-id: 3793c30212d545e226f3e5337289bc2601dfa553
Summary:
This diff drops `NetworkDataSingle` in favor of `ReceivedPacket`. The latter contains a `ReceivedPacket::Timings` field that has the same `receiveTimePoint` currently in `NetworkDataSingle`, while also providing other useful signals.
--
This diff is part of a larger stack focused on the following:
- **Cleaning up client and server UDP packet receive paths while improving testability.** We currently have multiple receive paths for client and server. Capabilities vary significantly and there are few tests. For instance:
- The server receive path supports socket RX timestamps, abet incorrectly in that it does not store timestamp per packet. In comparison, the client receive path does not currently support socket RX timestamps, although the code in `QuicClientTransport::recvmsg` and `QuicClientTransport::recvmmsg` makes reference to socket RX timestamps, making it confusing to understand the capabilities available when tracing through the code. This complicates the tests in `QuicTypedTransportTests`, as we have to disable test logic that depends on socket RX timestamps for client tests.
- The client currently has three receive paths, and none of them are well tested.
- **Modularize and abstract components in the receive path.** This will make it easier to mock/fake the UDP socket and network layers.
- `QuicClientTransport` and `QuicServerTransport` currently contain UDP socket handling logic that operates over lower layer primitives such `cmsg` and `io_vec` (see `QuicClientTransport::recvmmsg` and `...::recvmsg` as examples).
- Because this UDP socket handling logic is inside of the mvfst transport implementations, it is difficult to test this logic in isolation and mock/fake the underlying socket and network layers. For instance, injecting a user space network emulator that operates at the socket layer would require faking `folly::AsyncUDPSocket`, which is non-trivial given that `AsyncUDPSocket` does not abstract away intricacies arising from the aforementioned lower layer primitives.
- By shifting this logic into an intermediate layer between the transport and the underlying UDP socket, it will be easier to mock out the UDP socket layer when testing functionality at higher layers, and inject fake components when we want to emulate the network between a mvfst client and server. It will also be easier for us to have unit tests focused on testing interactions between the UDP socket implementation and this intermediate layer.
- **Improving receive path timestamping.** We only record a single timestamp per `NetworkData` at the moment, but (1) it is possible for a `NetworkData` to have multiple packets, each with their own timestamps, and (2) we should be able to record both userspace and socket timestamps
Reviewed By: silver23arrow
Differential Revision: D48739219
fbshipit-source-id: fc2cdb7b425d68c729dd3bec00b6c6ff3c4bf8ec
Summary:
`connSetupCallback_` and `connCallback_` in `QuicTransportBase.h` are raw pointers, which delegates the responsibility to keep these callbacks alive to the caller.
There are use cases where it would be convenient to be able to tie the lifetime of the callback to the Quic transport, e.g,. as long as the Quic transport is alive, it keeps the callbacks alive as well.
This diff uses MaybeManagedPtr to achieve this lifetime tie if desired. A MaybeManagedPtr intialized with a shared pointer manages lifetime of the contained object, whereas a MaybeManagedPtr initialized with a raw pointer does not manage lifetime of the contained object. This way caller can decide to pass in a shared ptr or raw pointer and achieve the desired behavior.
Note that we cannot simply use a shared_ptr for that. Using a shared_ptr would potentially mean that callbacks passed are destroyed when the transport is destroyed. Callbacks would not be destroyed if they were managed by a shared_ptr already, but this is something we cannot assume for every case. This would thus be a change in semantics to the current implementation, where the callbacks can outlive the transport.
Reviewed By: mjoras
Differential Revision: D49502381
fbshipit-source-id: 771a9328b99dc4f94f8e9679f9caf98af9180428
Summary:
This diff:
- Moves `NetworkData`, `NetworkDataSingle` and `ReceivedPacket` into separate header file
--
This diff is part of a larger stack focused on the following:
- **Cleaning up client and server UDP packet receive paths while improving testability.** We currently have multiple receive paths for client and server. Capabilities vary significantly and there are few tests. For instance:
- The server receive path supports socket RX timestamps, abet incorrectly in that it does not store timestamp per packet. In comparison, the client receive path does not currently support socket RX timestamps, although the code in `QuicClientTransport::recvmsg` and `QuicClientTransport::recvmmsg` makes reference to socket RX timestamps, making it confusing to understand the capabilities available when tracing through the code. This complicates the tests in `QuicTypedTransportTests`, as we have to disable test logic that depends on socket RX timestamps for client tests.
- The client currently has three receive paths, and none of them are well tested.
- **Modularize and abstract components in the receive path.** This will make it easier to mock/fake the UDP socket and network layers.
- `QuicClientTransport` and `QuicServerTransport` currently contain UDP socket handling logic that operates over lower layer primitives such `cmsg` and `io_vec` (see `QuicClientTransport::recvmmsg` and `...::recvmsg` as examples).
- Because this UDP socket handling logic is inside of the mvfst transport implementations, it is difficult to test this logic in isolation and mock/fake the underlying socket and network layers. For instance, injecting a user space network emulator that operates at the socket layer would require faking `folly::AsyncUDPSocket`, which is non-trivial given that `AsyncUDPSocket` does not abstract away intricacies arising from the aforementioned lower layer primitives.
- By shifting this logic into an intermediate layer between the transport and the underlying UDP socket, it will be easier to mock out the UDP socket layer when testing functionality at higher layers, and inject fake components when we want to emulate the network between a mvfst client and server. It will also be easier for us to have unit tests focused on testing interactions between the UDP socket implementation and this intermediate layer.
- **Improving receive path timestamping.** We only record a single timestamp per `NetworkData` at the moment, but (1) it is possible for a `NetworkData` to have multiple packets, each with their own timestamps, and (2) we should be able to record both userspace and socket timestamps.
Reviewed By: mjoras
Differential Revision: D48717564
fbshipit-source-id: 0947c73c12da79e8e3cc17e5296354d728c250d1
Summary:
This diff changes `QuicAsyncUDPSocketWrapper` so that it is an abstraction layer that inherits from `QuicAsyncUDPSocketType`, instead of simply being a container with aliases.
- Key changes in `QuicAsyncUDPSocketWrapper.h`, the rest of the updates switch us from using `QuicAsyncUDPSocketType` to `QuicAsyncUDPSocketWrapper`.
- It's difficult to mock the UDP socket today given that we expose the entire `folly::AsyncUDPSocket` type to the higher layers of the QUIC stack. This complicates testing and emulation because any mock / fake has to implement low level primitives like `recvmmsg`, and because the `folly::AsyncUDPSocket` interface can change over time.
- Pure virtual functions will be defined in `QuicAsyncUDPSocketWrapper` in a follow up diff to start creating an interface between the higher layers of the mvfst QUIC stack and the UDP socket, and this interface will abstract away lower layer details such as `cmsgs` and `io_vec`, and instead focus on populating higher layer structures such as `NetworkData` and `ReceivedPacket` (D48714615). This will make it easier for us to mock or fake the UDP socket.
This diff relies on changes to `folly::MockAsyncUDPSocket` introduced in D48717389.
--
This diff is part of a larger stack focused on the following:
- **Cleaning up client and server UDP packet receive paths while improving testability.** We currently have multiple receive paths for client and server. Capabilities vary significantly and there are few tests. For instance:
- The server receive path supports socket RX timestamps, abet incorrectly in that it does not store timestamp per packet. In comparison, the client receive path does not currently support socket RX timestamps, although the code in `QuicClientTransport::recvmsg` and `QuicClientTransport::recvmmsg` makes reference to socket RX timestamps, making it confusing to understand the capabilities available when tracing through the code. This complicates the tests in `QuicTypedTransportTests`, as we have to disable test logic that depends on socket RX timestamps for client tests.
- The client currently has three receive paths, and none of them are well tested.
- **Modularize and abstract components in the receive path.** This will make it easier to mock/fake the UDP socket and network layers.
- `QuicClientTransport` and `QuicServerTransport` currently contain UDP socket handling logic that operates over lower layer primitives such `cmsg` and `io_vec` (see `QuicClientTransport::recvmmsg` and `...::recvmsg` as examples).
- Because this UDP socket handling logic is inside of the mvfst transport implementations, it is difficult to test this logic in isolation and mock/fake the underlying socket and network layers. For instance, injecting a user space network emulator that operates at the socket layer would require faking `folly::AsyncUDPSocket`, which is non-trivial given that `AsyncUDPSocket` does not abstract away intricacies arising from the aforementioned lower layer primitives.
- By shifting this logic into an intermediate layer between the transport and the underlying UDP socket, it will be easier to mock out the UDP socket layer when testing functionality at higher layers, and inject fake components when we want to emulate the network between a mvfst client and server. It will also be easier for us to have unit tests focused on testing interactions between the UDP socket implementation and this intermediate layer.
- **Improving receive path timestamping.** We only record a single timestamp per `NetworkData` at the moment, but (1) it is possible for a `NetworkData` to have multiple packets, each with their own timestamps, and (2) we should be able to record both userspace and socket timestamps.
Reviewed By: jbeshay, hanidamlaj
Differential Revision: D48717388
fbshipit-source-id: 4f34182a69ab1e619e454da19e357a6a2ee2b9ab