Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for multipath (draft-05) #559

Open
wants to merge 84 commits into
base: kazuho/path-migration
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
5551bf5
retain pn_space, loss detection, CC as a pointer member of st_quicly_…
kazuho Jun 14, 2023
486188e
use `num_sent.packets` to drive key updates rather than PN
kazuho Jun 15, 2023
9c5eeab
update `path_index` when promoted
kazuho Jun 15, 2023
551aef3
[multipath] TP, ACK_MP, per-path nonce and ack space
kazuho Jun 15, 2023
815920a
retain `send_ack_at` per ACK space rather than per 4-tuple
kazuho Jun 20, 2023
30be9db
fix leak
kazuho Jun 20, 2023
c1b0c0c
[editorial] send_ack_at being smaller than INT64_MAX implies non-zero…
kazuho Jun 20, 2023
45132c2
ack application data immediately until the handshake context is disca…
kazuho Jun 20, 2023
0f4ddc5
update expected completion times following changes to the loss recovo…
kazuho Jun 20, 2023
3e3c7bb
this can be a feature (for the time being)
kazuho Jun 22, 2023
49f501b
Merge branch 'kazuho/path-migration' into kazuho/multipath
kazuho Jun 22, 2023
d088e4a
check CID requirements only if both sides opt-in to MPQUIC
kazuho Jun 22, 2023
dd29772
[cli] `--multipath` option to negotiate use of multipath
kazuho Jun 22, 2023
ef459d9
Merge branch 'kazuho/path-migration' into kazuho/multipath
kazuho Jun 26, 2023
494fe79
simplify
kazuho Jun 26, 2023
f9a9104
DCID passed to encryptor is always zero with v1
kazuho Jun 26, 2023
31ed6a1
zero-clear
kazuho Jun 26, 2023
b2e93da
UAF
kazuho Jun 26, 2023
121411c
check the correct cid_set
kazuho Jun 26, 2023
851f211
retain path_id for ack-ack handling
kazuho Jun 26, 2023
8320478
make sure the struct is of intended size
kazuho Jun 26, 2023
328748b
Merge branch 'kazuho/path-migration' into kazuho/multipath
kazuho Jun 27, 2023
d5ef3cb
[cli] test migration with multipath enabled
kazuho Jun 27, 2023
169a21a
[refactor] define iterator as a function rather than a macro
kazuho Jun 27, 2023
0edfebf
use the iterator
kazuho Jun 27, 2023
d94e6ec
reduce ifs through the use of vtable
kazuho Jun 27, 2023
346098d
simplify
kazuho Jun 27, 2023
59d582d
[cli] wip
kazuho Jun 27, 2023
8118692
refine comment
kazuho Jun 27, 2023
c7adaaa
add API to open new path
kazuho Jun 27, 2023
50a2304
Merge branch 'kazuho/path-migration' into kazuho/multipath
kazuho Jun 28, 2023
602700f
API to add path
kazuho Jun 29, 2023
83da103
immediate means now, not 1 second later
kazuho Jul 19, 2023
2bea1cb
emit path_index in log
kazuho Aug 16, 2023
048ebb5
fix assert
kazuho Aug 17, 2023
7fe0442
do not overwrite v6 address
kazuho Aug 17, 2023
0cd0b6b
doc-comment the requirement
kazuho Aug 21, 2023
52c7e49
log local address of a new path
kazuho Aug 21, 2023
c788aaa
[cli] when running as a client bind to local port so that paths can b…
kazuho Aug 21, 2023
0770543
distinguish local adddress using only the port number if the address …
kazuho Aug 21, 2023
c47e83b
add assert
kazuho Aug 21, 2023
6149d85
[cli] supply local address, otherwise the client is impossible to det…
kazuho Aug 21, 2023
2ee3e24
fix hot loop when trying to send PATH_RESPONSE but not PATH_CHALLENGE
kazuho Aug 21, 2023
2677218
split ack-queue, loss recovery, cc
kazuho Aug 21, 2023
3dc40e9
[cli] replace the local port number retained by quicly, this is the o…
kazuho Aug 21, 2023
624f3c6
fix typo
kazuho Aug 22, 2023
2c21108
log dcid_sequence_number
kazuho Aug 22, 2023
ceade3f
oops
kazuho Aug 22, 2023
19a24f7
mark inflight packets as lost when retiring a path without killing th…
kazuho Aug 23, 2023
f772bd4
oops, remove debug log
kazuho Aug 23, 2023
c18880f
draft-05
kazuho Aug 23, 2023
7e60832
remove paths that are source of rebinding in a way that works with mu…
kazuho Aug 24, 2023
8c022ba
When multipath is used, prune paths source of NAT rebinding at the mo…
kazuho Aug 24, 2023
88f6b65
skipping the per-path loss recovery / CC logic can cause a hot loop
kazuho Aug 24, 2023
cf8a788
unify the packet emission logic (now data is sent on all the paths)
kazuho Sep 19, 2023
4432722
implement codec for PATH_ABANDON and PATH_STATUS though they are not …
kazuho Sep 19, 2023
ed364ea
fix compile errors on linux
kazuho Sep 19, 2023
f0c7a75
fix compile error on platforms lacking dtrace support
kazuho Sep 20, 2023
ca3e797
remove unused probe from definition, otherwise h2olog cannot be built
kazuho Sep 20, 2023
5febfc6
promote quicly_build_multipath_iv to an inline function; doing so hel…
kazuho Sep 20, 2023
023e97c
for the purpose of reporting, consider any non-initial path as "promo…
kazuho Sep 26, 2023
11f698e
record receive of ECN, send ACK_ECN
kazuho Oct 12, 2023
da0e57b
[cli] recognize ECN
kazuho Oct 12, 2023
5018f20
enable ECN on the send side
kazuho Oct 12, 2023
fe1bc35
[cli] enable ECN sender side
kazuho Oct 12, 2023
37d540b
update tests
kazuho Oct 13, 2023
d522c24
adjust comment
kazuho Oct 13, 2023
5f280da
ECN accounting is reported per-epoch
kazuho Oct 13, 2023
86df55a
retain counts for ECT(0), ECT(1) too, report per-connection metrics
kazuho Oct 13, 2023
addba2d
fix length check
kazuho Oct 13, 2023
fd2063c
[cli] report ack-ecn numbers
kazuho Oct 13, 2023
6501ed8
oopses
kazuho Oct 13, 2023
4bff19f
count and report loss episodes due to ECN (i.e., ones did not involve…
kazuho Oct 13, 2023
089ce4f
record and report ECN stats of received packets too
kazuho Oct 16, 2023
1c35a90
fast conversion as suggested by https://twitter.com/kamedo2/status/17…
kazuho Oct 16, 2023
4186233
report number of paths that were ECN-(in)capable; `quicly_stats_t::nu…
kazuho Oct 17, 2023
9f9f068
Merge pull request #557 from h2o/kazuho/examples-echo-zero-timeout
kazuho Oct 17, 2023
c55d375
Merge pull request #551 from h2o/kazuho/send_ack_at-is-unreliable-tim…
kazuho Oct 17, 2023
c5b954b
Merge pull request #561 from h2o/kazuho/ecn
kazuho Oct 18, 2023
460c90b
Merge branch 'master' into kazuho/multipath-05
kazuho Oct 18, 2023
bfca5de
Fix entering hot loop if app opens a stream before the handshake is c…
kazuho Oct 19, 2023
aae8e57
Merge pull request #562 from h2o/kazuho/amend-551
kazuho Oct 19, 2023
33354cd
Merge branch 'master' into kazuho/multipath-05
kazuho Oct 19, 2023
e4a48bc
oops
kazuho Oct 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static int run_loop(int fd, quicly_conn_t *client)
tv.tv_sec = delta / 1000;
tv.tv_usec = (delta % 1000) * 1000;
} else {
tv.tv_sec = 1000;
tv.tv_sec = 0;
tv.tv_usec = 0;
}
FD_ZERO(&readfds);
Expand Down
68 changes: 66 additions & 2 deletions include/quicly.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,11 @@ typedef struct st_quicly_crypto_engine_t {
* header protection using `header_protect_ctx`. Quicly does not read or write the content of the UDP datagram payload after
* this function is called. Therefore, an engine might retain the information provided by this function, and protect the packet
* and the header at a later moment (e.g., hardware crypto offload).
* @param dcid specifies the CID sequence number for encrypting Multipath QUIC packets; will always be zero in QUIC v1
*/
void (*encrypt_packet)(struct st_quicly_crypto_engine_t *engine, quicly_conn_t *conn, ptls_cipher_context_t *header_protect_ctx,
ptls_aead_context_t *packet_protect_ctx, ptls_iovec_t datagram, size_t first_byte_at,
size_t payload_from, uint64_t packet_number, int coalesced);
size_t payload_from, uint64_t dcid, uint64_t packet_number, int coalesced);
} quicly_crypto_engine_t;

/**
Expand Down Expand Up @@ -261,6 +262,10 @@ typedef struct st_quicly_transport_parameters_t {
*
*/
uint8_t disable_active_migration : 1;
/**
*
*/
uint8_t enable_multipath : 1;
/**
*
*/
Expand Down Expand Up @@ -338,6 +343,10 @@ struct st_quicly_context_t {
* expand client hello so that it does not fit into one datagram
*/
unsigned expand_client_hello : 1;
/**
* whether to use ECN on the send side; ECN is always on on the receive side
*/
unsigned enable_ecn : 1;
/**
*
*/
Expand Down Expand Up @@ -462,6 +471,14 @@ struct st_quicly_conn_streamgroup_state_t {
* Total number of packets received out of order. \
*/ \
uint64_t received_out_of_order; \
/** \
* connection-wide counters for ECT(0), ECT(1), CE \
*/ \
uint64_t received_ecn_counts[3]; \
/** \
* connection-wide ack-received counters for ECT(0), ECT(1), CE \
*/ \
uint64_t acked_ecn_counts[3]; \
/** \
* Total number of packets sent on promoted paths. \
*/ \
Expand Down Expand Up @@ -522,6 +539,14 @@ struct st_quicly_conn_streamgroup_state_t {
* number of alternate paths that were closed due to Connection ID being unavailable \
*/ \
uint64_t closed_no_dcid; \
/** \
* number of paths that were ECN-capable \
*/ \
uint64_t ecn_validated; \
/** \
* number of paths that were deemed as ECN black holes \
*/ \
uint64_t ecn_failed; \
} num_paths; \
/** \
* Total number of each frame being sent / received. \
Expand All @@ -530,7 +555,7 @@ struct st_quicly_conn_streamgroup_state_t {
uint64_t padding, ping, ack, reset_stream, stop_sending, crypto, new_token, stream, max_data, max_stream_data, \
max_streams_bidi, max_streams_uni, data_blocked, stream_data_blocked, streams_blocked, new_connection_id, \
retire_connection_id, path_challenge, path_response, transport_close, application_close, handshake_done, datagram, \
ack_frequency; \
ack_frequency, ack_mp, path_abandon, path_status; \
} num_frames_sent, num_frames_received; \
/** \
* Total number of PTOs observed during the connection. \
Expand Down Expand Up @@ -848,6 +873,10 @@ typedef struct st_quicly_decoded_packet_t {
uint64_t pn;
uint64_t key_phase;
} decrypted;
/**
* ECN bits
*/
uint8_t ecn : 2;
/**
*
*/
Expand Down Expand Up @@ -1065,6 +1094,10 @@ size_t quicly_send_retry(quicly_context_t *ctx, ptls_aead_context_t *token_encry
*/
int quicly_send(quicly_conn_t *conn, quicly_address_t *dest, quicly_address_t *src, struct iovec *datagrams, size_t *num_datagrams,
void *buf, size_t bufsize);
/**
* returns ECN bits to be set for the packets built by the last invocation of `quicly_send`
*/
uint8_t quicly_send_get_ecn_bits(quicly_conn_t *conn);
/**
*
*/
Expand Down Expand Up @@ -1128,10 +1161,20 @@ int quicly_connect(quicly_conn_t **conn, quicly_context_t *ctx, const char *serv
int quicly_accept(quicly_conn_t **conn, quicly_context_t *ctx, struct sockaddr *dest_addr, struct sockaddr *src_addr,
quicly_decoded_packet_t *packet, quicly_address_token_plaintext_t *address_token,
const quicly_cid_plaintext_t *new_cid, ptls_handshake_properties_t *handshake_properties, void *appdata);
/**
* Adds a new path. Only usable when running as a client. Local must contain sufficient information to distinguish between the paths
* being establisished; i.e, either the port number should be different or if one port is shared then the IP addresses of each
* local address must be different.
*/
int quicly_add_path(quicly_conn_t *conn, struct sockaddr *local);
/**
*
*/
ptls_t *quicly_get_tls(quicly_conn_t *conn);
/**
*
*/
int quicly_is_multipath(quicly_conn_t *conn);
/**
* Resumes an async TLS handshake, and returns a pointer to the QUIC connection or NULL if the corresponding QUIC connection has
* been discarded. See `quicly_async_handshake_t`.
Expand Down Expand Up @@ -1226,6 +1269,12 @@ int quicly_set_cc(quicly_conn_t *conn, quicly_cc_type_t *cc);
*
*/
void quicly_amend_ptls_context(ptls_context_t *ptls);
/**
* Builds the IV prefix of used to encrypt / decrypt Multipath QUIC packets. Size of the supplied buffer (`iv`) must be no less than
* `PTLS_MAX_IV_SIZE`. Once the IV is built, that should be applied to AEAD using `ptls_aead_xor_iv` prior to calling the encryption
* function. After that, `ptls_aead_xor_iv` should be called again with the same arguments to nagate the changes to IV.
*/
static size_t quicly_build_multipath_iv(ptls_aead_algorithm_t *algo, uint64_t sequence, void *iv);
/**
* Encrypts an address token by serializing the plaintext structure and appending an authentication tag.
*
Expand Down Expand Up @@ -1417,6 +1466,21 @@ inline void quicly_stream_set_receive_window(quicly_stream_t *stream, uint32_t w
stream->_recv_aux.window = window;
}

inline size_t quicly_build_multipath_iv(ptls_aead_algorithm_t *algo, uint64_t sequence, void *_iv)
{
size_t len = algo->iv_size - 8;
uint8_t *iv = (uint8_t *)_iv;

for (size_t i = 0; i + 4 < len; ++i)
*iv++ = 0;
*iv++ = (uint8_t)(sequence >> 24);
*iv++ = (uint8_t)(sequence >> 16);
*iv++ = (uint8_t)(sequence >> 8);
*iv++ = (uint8_t)sequence;

return len;
}

inline int quicly_stream_is_client_initiated(quicly_stream_id_t stream_id)
{
if (stream_id < 0)
Expand Down
36 changes: 33 additions & 3 deletions include/quicly/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ typedef struct st_quicly_cc_t {
* Packet number indicating end of recovery period, if in recovery.
*/
uint64_t recovery_end;
/**
* If the most recent loss episode was signalled by ECN only (i.e., no packet loss).
*/
unsigned episode_by_ecn : 1;
/**
* State information specific to the congestion controller implementation.
*/
Expand Down Expand Up @@ -130,9 +134,13 @@ typedef struct st_quicly_cc_t {
*/
uint32_t cwnd_maximum;
/**
* Total number of number of loss episodes (congestion window reductions).
* Total number of loss episodes (congestion window reductions).
*/
uint32_t num_loss_episodes;
/**
* Total number of loss episodes that was reported only by ECN (hence no packet loss).
*/
uint32_t num_ecn_loss_episodes;
} quicly_cc_t;

struct st_quicly_cc_type_t {
Expand All @@ -150,8 +158,9 @@ struct st_quicly_cc_type_t {
void (*cc_on_acked)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t largest_acked, uint32_t inflight,
uint64_t next_pn, int64_t now, uint32_t max_udp_payload_size);
/**
* Called when a packet is detected as lost. |next_pn| is the next unsent packet number,
* used for setting the recovery window.
* Called when a packet is detected as lost.
* @param bytes bytes declared lost, or zero iff ECN_CE is observed
* @param next_pn the next unsent packet number, used for setting the recovery window
*/
void (*cc_on_lost)(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, uint64_t lost_pn, uint64_t next_pn, int64_t now,
uint32_t max_udp_payload_size);
Expand Down Expand Up @@ -192,6 +201,27 @@ void quicly_cc_reno_on_lost(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t
int64_t now, uint32_t max_udp_payload_size);
void quicly_cc_reno_on_persistent_congestion(quicly_cc_t *cc, const quicly_loss_t *loss, int64_t now);
void quicly_cc_reno_on_sent(quicly_cc_t *cc, const quicly_loss_t *loss, uint32_t bytes, int64_t now);
/**
* Updates ECN counter when loss is observed.
*/
static void quicly_cc__update_ecn_episodes(quicly_cc_t *cc, uint32_t lost_bytes, uint64_t lost_pn);

/* inline definitions */

inline void quicly_cc__update_ecn_episodes(quicly_cc_t *cc, uint32_t lost_bytes, uint64_t lost_pn)
{
/* when it is a new loss episode, initially assume that all losses are due to ECN signalling ... */
if (lost_pn >= cc->recovery_end) {
++cc->num_ecn_loss_episodes;
cc->episode_by_ecn = 1;
}

/* ... but if a loss is observed, decrement the ECN loss episode counter */
if (lost_bytes != 0 && cc->episode_by_ecn) {
--cc->num_ecn_loss_episodes;
cc->episode_by_ecn = 0;
}
}

#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions include/quicly/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ extern "C" {
#define QUICLY_TRANSPORT_ERROR_KEY_UPDATE QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xe)
#define QUICLY_TRANSPORT_ERROR_AEAD_LIMIT_REACHED QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xf)
#define QUICLY_TRANSPORT_ERROR_TLS_ALERT_BASE QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0x100)
#define QUICLY_TRANSPORT_ERROR_MP_PROTOCOL_VIOLATION QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xba01)

/* internal error codes, used purely for signaling status to the application */
#define QUICLY_ERROR_PACKET_IGNORED 0xff01
Expand All @@ -108,6 +109,7 @@ extern "C" {
#define QUICLY_ERROR_STATE_EXHAUSTION 0xff07
#define QUICLY_ERROR_INVALID_INITIAL_VERSION 0xff08
#define QUICLY_ERROR_DECRYPTION_FAILED 0xff09
#define QUICLY_ERROR_INVALID_PARAMETERS 0xff0a

typedef int64_t quicly_stream_id_t;

Expand Down
Loading
Loading