Skip to content

Commit

Permalink
Limit pacing rate and quantum for CC bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
huitema committed May 3, 2024
1 parent 03b8e29 commit fc034ac
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 28 deletions.
4 changes: 4 additions & 0 deletions picoquic/picoquic_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ extern "C" {
#define PICOQUIC_CWIN_INITIAL (10 * PICOQUIC_MAX_PACKET_SIZE)
#define PICOQUIC_CWIN_MINIMUM (2 * PICOQUIC_MAX_PACKET_SIZE)

#define PICOQUIC_PRIORITY_BYPASS_MAX_RATE 125000
#define PICOQUIC_PRIORITY_BYPASS_QUANTUM 2560

#define PICOQUIC_DEFAULT_CRYPTO_EPOCH_LENGTH (1<<22)

#define PICOQUIC_DEFAULT_SIMULTANEOUS_LOGS 32
Expand Down Expand Up @@ -1453,6 +1456,7 @@ typedef struct st_picoquic_cnx_t {
uint64_t high_priority_stream_id;
uint64_t next_stream_id[4];
uint64_t priority_limit_for_bypass; /* Bypass CC if dtagram or stream priority lower than this, 0 means never */
picoquic_pacing_t priority_bypass_pacing;

/* Repeat queue contains packets with data frames that should be
* sent according to priority when congestion window opens. */
Expand Down
6 changes: 6 additions & 0 deletions picoquic/quicctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -3639,6 +3639,7 @@ picoquic_cnx_t* picoquic_create_cnx(picoquic_quic_t* quic,
for (int i = 0; i < 4; i++) {
cnx->next_stream_id[i] = i;
}
picoquic_pacing_init(&cnx->priority_bypass_pacing, start_time);
picoquic_register_path(cnx, cnx->path[0]);
}
}
Expand Down Expand Up @@ -4781,6 +4782,11 @@ void picoquic_set_default_bbr_quantum_ratio(picoquic_quic_t* quic, double quantu
void picoquic_set_priority_limit_for_bypass(picoquic_cnx_t* cnx, uint8_t priority_limit)
{
cnx->priority_limit_for_bypass = priority_limit;
if (priority_limit > 0) {
picoquic_update_pacing_parameters(&cnx->priority_bypass_pacing,
PICOQUIC_PRIORITY_BYPASS_MAX_RATE, PICOQUIC_PRIORITY_BYPASS_QUANTUM,
cnx->path[0]->send_mtu, cnx->path[0]->smoothed_rtt, NULL);
}
}

void picoquic_set_feedback_loss_notification(picoquic_cnx_t* cnx, unsigned int should_notify)
Expand Down
55 changes: 27 additions & 28 deletions picoquic/sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -2931,7 +2931,7 @@ static uint8_t* picoquic_prepare_datagram_ready(picoquic_cnx_t* cnx, picoquic_pa
*/

static uint8_t* picoquic_prepare_stream_and_datagrams(picoquic_cnx_t* cnx, picoquic_path_t* path_x, uint8_t* bytes_next, uint8_t* bytes_max,
uint64_t max_priority_allowed,
uint64_t max_priority_allowed, uint64_t current_time,
int* more_data, int* is_pure_ack, int* no_data_to_send, int* ret)
{
int datagram_sent = 0;
Expand All @@ -2950,6 +2950,7 @@ static uint8_t* picoquic_prepare_stream_and_datagrams(picoquic_cnx_t* cnx, picoq
picoquic_packet_t* first_repeat = picoquic_first_data_repeat_packet(cnx);
uint64_t current_priority = UINT64_MAX;
uint64_t stream_priority = UINT64_MAX;
uint8_t* bytes_before_iteration = bytes_next;
int something_sent = 0;
int conflict_found = 0;

Expand Down Expand Up @@ -3030,6 +3031,12 @@ static uint8_t* picoquic_prepare_stream_and_datagrams(picoquic_cnx_t* cnx, picoq
more_data, is_pure_ack, &datagram_tried_and_failed, &datagram_sent, ret);
something_sent = datagram_sent;
}

if (current_priority < cnx->priority_limit_for_bypass && bytes_next > bytes_before_iteration) {
picoquic_update_pacing_data_after_send(&cnx->priority_bypass_pacing, bytes_next - bytes_before_iteration,
cnx->path[0]->send_mtu, current_time);
}

if (is_first_round) {
*no_data_to_send = ((first_stream == NULL && first_repeat == NULL) || stream_tried_and_failed) &&
(!datagram_present || datagram_tried_and_failed);
Expand Down Expand Up @@ -3174,25 +3181,13 @@ int picoquic_prepare_packet_almost_ready(picoquic_cnx_t* cnx, picoquic_path_t* p

length = bytes_next - bytes;
if (path_x->cwin < path_x->bytes_in_transit) {
/* Implementation of experimental API, picoquic_set_priority_limit_for_bypass */
uint8_t* bytes_next_before_bypass = bytes_next;
if (cnx->priority_limit_for_bypass > 0 && cnx->nb_paths == 1) {
bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max,
cnx->priority_limit_for_bypass,
&more_data, &is_pure_ack, &no_data_to_send, &ret);
}
if (bytes_next != bytes_next_before_bypass) {
length = bytes_next - bytes;
}
else {
picoquic_per_ack_state_t ack_state = { 0 };
cnx->cwin_blocked = 1;
path_x->last_cwin_blocked_time = current_time;
if (cnx->congestion_alg != NULL) {
cnx->congestion_alg->alg_notify(cnx, path_x,
picoquic_congestion_notification_cwin_blocked,
&ack_state, current_time);
}
picoquic_per_ack_state_t ack_state = { 0 };
cnx->cwin_blocked = 1;
path_x->last_cwin_blocked_time = current_time;
if (cnx->congestion_alg != NULL) {
cnx->congestion_alg->alg_notify(cnx, path_x,
picoquic_congestion_notification_cwin_blocked,
&ack_state, current_time);
}
}
else {
Expand Down Expand Up @@ -3234,7 +3229,7 @@ int picoquic_prepare_packet_almost_ready(picoquic_cnx_t* cnx, picoquic_path_t* p
}
if (ret == 0) {
bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max,
UINT64_MAX,
UINT64_MAX, current_time,
&more_data, &is_pure_ack, &no_data_to_send, &ret);
}
/* TODO: replace this by posting of frame when CWIN estimated */
Expand Down Expand Up @@ -3533,9 +3528,11 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t* path_x,
/* Implementation of experimental API, picoquic_set_priority_limit_for_bypass */
uint8_t* bytes_next_before_bypass = bytes_next;
int no_data_to_send = 0;
if (cnx->priority_limit_for_bypass > 0 && cnx->nb_paths == 1) {
if (cnx->priority_limit_for_bypass > 0 && cnx->nb_paths == 1 &&
picoquic_is_authorized_by_pacing(&cnx->priority_bypass_pacing, current_time, next_wake_time,
cnx->quic->packet_train_mode, cnx->quic)) {
bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max,
cnx->priority_limit_for_bypass,
cnx->priority_limit_for_bypass, current_time,
&more_data, &is_pure_ack, &no_data_to_send, &ret);
}
if (bytes_next != bytes_next_before_bypass) {
Expand Down Expand Up @@ -3582,8 +3579,8 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t* path_x,
bytes_next = picoquic_format_ack_frequency_frame(cnx, bytes_next, bytes_max, &more_data);
}
if (ret == 0) {
bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max, UINT64_MAX,
&more_data, &is_pure_ack, &no_data_to_send, &ret);
bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max,
UINT64_MAX, current_time, &more_data, &is_pure_ack, &no_data_to_send, &ret);
}

/* TODO: replace this by scheduling of BDP frame when window has been estimated */
Expand Down Expand Up @@ -3659,12 +3656,14 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t* path_x,
}
} /* end of CC */
} /* End of pacing */
else if (cnx->priority_limit_for_bypass > 0 && cnx->nb_paths == 1) {
else if (cnx->priority_limit_for_bypass > 0 && cnx->nb_paths == 1 &&
picoquic_is_authorized_by_pacing(&cnx->priority_bypass_pacing, current_time, next_wake_time,
cnx->quic->packet_train_mode, cnx->quic)) {
/* If congestion bypass is implemented, also consider pacing bypass */
int no_data_to_send = 0;

if ((bytes_next = picoquic_prepare_stream_and_datagrams(cnx, path_x, bytes_next, bytes_max,
cnx->priority_limit_for_bypass,
cnx->priority_limit_for_bypass, current_time,
&more_data, &is_pure_ack, &no_data_to_send, &ret)) != NULL) {
length = bytes_next - bytes;
}
Expand Down

0 comments on commit fc034ac

Please sign in to comment.