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 0RTT-BDP extension #1073

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions loglib/qlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,27 @@ int qlog_transport_extensions(FILE* f, bytestream* s, size_t tp_length)
case picoquic_tp_grease_quic_bit:
qlog_boolean_transport_extension(f, "grease_quic_bit", s, extension_length);
break;
case picoquic_tp_recon_bytes_in_flight:
qlog_vint_transport_extension(f, "recon_bytes_in_flight", s, extension_length);
break;
case picoquic_tp_recon_min_rtt:
qlog_vint_transport_extension(f, "recon_bytes_min_rtt", s, extension_length);
break;
case picoquic_tp_recon_max_pkt_number:
qlog_vint_transport_extension(f, "recon_max_pkt_number", s, extension_length);
break;
case picoquic_tp_recon_cwin:
qlog_vint_transport_extension(f, "recon_cwin", s, extension_length);
break;
case picoquic_tp_recon_rtt_variant:
qlog_vint_transport_extension(f, "recon_rtt_variant", s, extension_length);
break;
case picoquic_tp_recon_smoothed_rtt:
qlog_vint_transport_extension(f, "recon_smoothed_rtt", s, extension_length);
break;
case picoquic_tp_recon_max_ack_delay:
qlog_vint_transport_extension(f, "recon_max_ack_delay", s, extension_length);
break;
default:
/* dump unknown extensions */
fprintf(f, "\"%" PRIx64 "\": ", extension_type);
Expand Down
21 changes: 21 additions & 0 deletions picoquic/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,27 @@ char const* picoquic_log_tp_name(uint64_t tp_number)
case picoquic_tp_grease_quic_bit:
tp_name = "grease_quic_bit";
break;
case picoquic_tp_recon_bytes_in_flight:
tp_name = "recon_bytes_in_flight";
break;
case picoquic_tp_recon_min_rtt:
tp_name = "recon_min_rtt";
break;
case picoquic_tp_recon_max_pkt_number:
tp_name = "recon_max_pkt_number";
break;
case picoquic_tp_recon_cwin:
tp_name = "recon_cwin";
break;
case picoquic_tp_recon_rtt_variant:
tp_name = "recon_rtt_variant";
break;
case picoquic_tp_recon_smoothed_rtt:
tp_name = "recon_smoothed_rtt";
break;
case picoquic_tp_recon_max_ack_delay:
tp_name = "recon_max_ack_delay";
break;
default:
break;
}
Expand Down
7 changes: 7 additions & 0 deletions picoquic/picoquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ typedef struct st_picoquic_tp_t {
int enable_time_stamp; /* (x&1) want, (x&2) can */
uint64_t min_ack_delay;
int do_grease_quic_bit;
uint64_t recon_bytes_in_flight;
uint64_t recon_min_rtt;
uint64_t recon_max_pkt_number;
uint64_t recon_cwin;
uint64_t recon_rtt_variant;
uint64_t recon_smoothed_rtt;
uint64_t recon_max_ack_delay;
} picoquic_tp_t;

/*
Expand Down
29 changes: 27 additions & 2 deletions picoquic/picoquic_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ extern "C" {

#define PICOQUIC_ALPN_NUMBER_MAX 8


/*
* Types of frames
*/
Expand Down Expand Up @@ -465,7 +466,15 @@ typedef enum {
picoquic_tp_enable_loss_bit = 0x1057,
picoquic_tp_min_ack_delay = 0xDE1A,
picoquic_tp_enable_time_stamp = 0x7158, /* x&1 = */
picoquic_tp_grease_quic_bit = 0x2ab2
picoquic_tp_grease_quic_bit = 0x2ab2,
picoquic_tp_recon_bytes_in_flight = 0x3ab1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_min_rtt = 0x3ba1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_max_pkt_number = 0x3bc1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_cwin = 0x3cb1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_rtt_variant = 0x3cd1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_smoothed_rtt = 0x3dc1, /* draft-kuhn-quic-0rtt-bdp-07 */
picoquic_tp_recon_max_ack_delay = 0x3de1, /* draft-kuhn-quic-0rtt-bdp-07 */

} picoquic_tp_enum;

/* Callback for converting binary log to quic log at the end of a connection.
Expand Down Expand Up @@ -522,6 +531,7 @@ typedef struct st_picoquic_quic_t {
unsigned int log_pn_dec : 1; /* Log key hashes on key changes to debug crypto */
unsigned int random_initial : 1; /* Randomize the initial PN number */
unsigned int packet_train_mode : 1; /* Tune pacing for sending packet trains */
unsigned int is_0RTT_BDP_enabled : 1; /* 0-RTT_BDP extension is negociated */

picoquic_stateless_packet_t* pending_stateless_packet;

Expand Down Expand Up @@ -560,6 +570,9 @@ typedef struct st_picoquic_quic_t {
void* fuzz_ctx;
int wake_file;
int wake_line;

int bdp_interval;
int bdp_limit;
} picoquic_quic_t;

picoquic_packet_context_enum picoquic_context_from_epoch(int epoch);
Expand Down Expand Up @@ -944,7 +957,6 @@ typedef struct st_picoquic_cnx_t {
unsigned int quic_bit_greased : 1; /* Indicate whether the quic bit was greased at least once */
unsigned int quic_bit_received_0 : 1; /* Indicate whether the quic bit was received as zero at least once */
unsigned int is_half_open : 1; /* for server side connections, created but not yet complete */

/* Spin bit policy */
picoquic_spinbit_version_enum spin_policy;
/* Idle timeout in microseconds */
Expand Down Expand Up @@ -1092,6 +1104,10 @@ typedef struct st_picoquic_cnx_t {
uint64_t ack_gap_remote;
uint64_t ack_delay_remote;

/* Management the sending of BDP */
uint64_t bdp_send_time;
uint64_t nb_bdp_sample_sent;

/* Copies of packets received too soon */
picoquic_stateless_packet_t* first_sooner;
picoquic_stateless_packet_t* last_sooner;
Expand Down Expand Up @@ -1452,6 +1468,15 @@ int picoquic_prepare_transport_extensions(picoquic_cnx_t* cnx, int extension_mod
int picoquic_receive_transport_extensions(picoquic_cnx_t* cnx, int extension_mode,
uint8_t* bytes, size_t bytes_max, size_t* consumed);

int picoquic_prepare_bdp_extensions(picoquic_cnx_t* cnx, int extension_mode,
uint8_t* bytes, size_t bytes_max, size_t* consumed);

int picoquic_receive_transport_extensions(picoquic_cnx_t* cnx, int extension_mode,
uint8_t* bytes, size_t bytes_max, size_t* consumed);

int picoquic_receive_bdp_extensions(picoquic_cnx_t* cnx, int extension_mode,
uint8_t* bytes, size_t bytes_max, size_t* consumed);

picoquic_misc_frame_header_t* picoquic_create_misc_frame(const uint8_t* bytes, size_t length, int is_pure_ack);

#ifdef __cplusplus
Expand Down
101 changes: 99 additions & 2 deletions picoquic/tls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
#define PICOQUIC_TRANSPORT_PARAMETERS_TLS_EXTENSION 0xFFA5
#define PICOQUIC_TRANSPORT_PARAMETERS_MAX_SIZE 2048

#define PICOQUIC_BDP_PARAMETERS_TLS_EXTENSION 0xFFA0
#define PICOQUIC_BDP_PARAMETERS_MAX_SIZE 2048

#ifdef PTLS_ESNI_NONCE_SIZE
#define PICOQUIC_ESNI_NONCE_SIZE PTLS_ESNI_NONCE_SIZE
#else
Expand All @@ -87,13 +90,18 @@ typedef struct st_picoquic_tls_ctx_t {
picoquic_cnx_t* cnx;
int client_mode;
ptls_raw_extension_t ext[2];
ptls_raw_extension_t bdp_ext[2];
ptls_handshake_properties_t handshake_properties;
ptls_iovec_t alpn_vec[PICOQUIC_ALPN_NUMBER_MAX];
int alpn_count;
uint8_t ext_data[PICOQUIC_TRANSPORT_PARAMETERS_MAX_SIZE];
uint8_t bdp_ext_data[PICOQUIC_BDP_PARAMETERS_MAX_SIZE];
uint8_t ext_received[PICOQUIC_TRANSPORT_PARAMETERS_MAX_SIZE];
size_t ext_received_length;
int ext_received_return;
uint8_t ext_bdp_received[PICOQUIC_BDP_PARAMETERS_MAX_SIZE];
size_t ext_bdp_received_length;
int ext_bdp_received_return;
uint16_t esni_version;
uint8_t esni_nonce[PICOQUIC_ESNI_NONCE_SIZE];
uint8_t app_secret_enc[PTLS_MAX_DIGEST_SIZE];
Expand Down Expand Up @@ -924,7 +932,7 @@ int picoquic_tls_collect_extensions_cb(ptls_t* tls, struct st_ptls_handshake_pro
UNREFERENCED_PARAMETER(tls);
UNREFERENCED_PARAMETER(properties);
#endif
return type == PICOQUIC_TRANSPORT_PARAMETERS_TLS_EXTENSION;
return type == PICOQUIC_TRANSPORT_PARAMETERS_TLS_EXTENSION || type == PICOQUIC_BDP_PARAMETERS_TLS_EXTENSION;
}

void picoquic_tls_set_extensions(picoquic_cnx_t* cnx, picoquic_tls_ctx_t* tls_ctx)
Expand All @@ -949,6 +957,29 @@ void picoquic_tls_set_extensions(picoquic_cnx_t* cnx, picoquic_tls_ctx_t* tls_ct
tls_ctx->handshake_properties.additional_extensions = tls_ctx->ext;
}

void picoquic_tls_set_bdp_extensions(picoquic_cnx_t* cnx, picoquic_tls_ctx_t* tls_ctx)
{
size_t consumed;
int ret = picoquic_prepare_bdp_extensions(cnx, (tls_ctx->client_mode) ? 0 : 1,
tls_ctx->bdp_ext_data, sizeof(tls_ctx->bdp_ext_data), &consumed);

if (ret == 0) {
tls_ctx->bdp_ext[0].type = PICOQUIC_BDP_PARAMETERS_TLS_EXTENSION;
tls_ctx->bdp_ext[0].data.base = tls_ctx->bdp_ext_data;
tls_ctx->bdp_ext[0].data.len = consumed;
tls_ctx->bdp_ext[1].type = 0xFFFF;
tls_ctx->bdp_ext[1].data.base = NULL;
tls_ctx->bdp_ext[1].data.len = 0;
} else {
tls_ctx->bdp_ext[0].type = 0xFFFF;
tls_ctx->bdp_ext[0].data.base = NULL;
tls_ctx->bdp_ext[0].data.len = 0;
}

tls_ctx->handshake_properties.nst_extensions = tls_ctx->bdp_ext;
}


/*
* The collected extensions call back is called by the stack upon
* reception of a handshake message containing supported extensions.
Expand Down Expand Up @@ -987,6 +1018,23 @@ int picoquic_tls_collected_extensions_cb(ptls_t* tls, ptls_handshake_properties_
picoquic_tls_set_extensions(ctx->cnx, ctx);
}
}
if (slots[i_slot].type == PICOQUIC_BDP_PARAMETERS_TLS_EXTENSION) {
size_t copied_length = sizeof(ctx->ext_bdp_received);

/* Retrieve the bdp metadata parameters from session ticket */
if (ctx->client_mode == 1 && ctx->cnx->quic->is_0RTT_BDP_enabled == 1) {
ret = picoquic_receive_bdp_extensions(ctx->cnx, 1,
slots[i_slot].data.base, slots[i_slot].data.len, &consumed);
}

/* Copy the extensions in the local context for further debugging */
ctx->ext_bdp_received_length = slots[i_slot].data.len;
if (copied_length > ctx->ext_bdp_received_length)
copied_length = ctx->ext_bdp_received_length;
memcpy(ctx->ext_bdp_received, slots[i_slot].data.base, copied_length);
ctx->ext_bdp_received_return = ret;
picoquic_tls_set_extensions(ctx->cnx, ctx);
}
}

return ret;
Expand Down Expand Up @@ -1262,7 +1310,6 @@ int picoquic_enable_custom_verify_certificate_callback(picoquic_quic_t* quic) {
}
}


void picoquic_dispose_verify_certificate_callback(picoquic_quic_t* quic, int custom) {
ptls_context_t* ctx = (ptls_context_t*)quic->tls_master_ctx;

Expand Down Expand Up @@ -2590,6 +2637,56 @@ int picoquic_tls_stream_process(picoquic_cnx_t* cnx)
ptls_buffer_dispose(&sendbuf);
}

// Send a new session ticket
{
uint64_t current_time = picoquic_get_quic_time(cnx->quic);
if (cnx->bdp_send_time == 0)
cnx->bdp_send_time = current_time;

if (!cnx->client_mode && ptls_handshake_is_complete(ctx->tls) && (current_time - cnx->bdp_send_time > cnx->quic->bdp_interval * 1000)
&& cnx->quic->bdp_limit > cnx->nb_bdp_sample_sent) {
picoquic_tls_set_bdp_extensions(cnx, ctx);
struct st_ptls_buffer_t sendbuf;
size_t send_offset[PICOQUIC_NUMBER_OF_EPOCH_OFFSETS] = { 0, 0, 0, 0, 0 };
ptls_buffer_init(&sendbuf, "", 0);

/* Clearing the global error state of openssl before calling handle message.
* This allows detection of errors during processing. */
picoquic_clear_crypto_errors();

ret = ptls_handle_message(ctx->tls, &sendbuf, send_offset, epoch, NULL, 0, &ctx->handshake_properties);

if ((ret == 0 || ret == PTLS_ERROR_IN_PROGRESS ||
ret == PTLS_ERROR_STATELESS_RETRY)) {
#ifdef PTLS_ESNI_NONCE_SIZE
/* Find the ESNI secret if any, and copy key values to picoquic tls context */
struct st_ptls_esni_secret_t* esni = ptls_get_esni_secret(ctx->tls);
if (esni != NULL) {
ctx->esni_version = esni->version;
memcpy(ctx->esni_nonce, esni->nonce, PTLS_ESNI_NONCE_SIZE);
}
#endif
if (sendbuf.off > 0) {
ret = picoquic_add_to_tls_stream(cnx, sendbuf.base, sendbuf.off, epoch);
if (ret == 0) {
cnx->bdp_send_time = current_time;
cnx->nb_bdp_sample_sent += 1;
}
}
else {
ret = 0;
}
}
else {
picoquic_log_crypto_errors(cnx, ret);
ret = -1;
}

ptls_buffer_dispose(&sendbuf);
}
}


if (processed > 0) {
if (ret == 0) {
switch (cnx->cnx_state) {
Expand Down
Loading