Skip to content
Merged
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
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ else()
endif()

project(picoquic
VERSION 1.1.37.0
VERSION 1.1.37.1
DESCRIPTION "picoquic library"
LANGUAGES C CXX)

Expand Down Expand Up @@ -192,6 +192,7 @@ set(PICOQUIC_TEST_LIBRARY_FILES
picoquictest/pn2pn64test.c
picoquictest/qlog_test.c
picoquictest/quic_tester.c
picoquictest/red_aqm.c
picoquictest/sacktest.c
picoquictest/satellite_test.c
picoquictest/skip_frame_test.c
Expand Down
2 changes: 1 addition & 1 deletion picoquic/picoquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
extern "C" {
#endif

#define PICOQUIC_VERSION "1.1.37.0"
#define PICOQUIC_VERSION "1.1.37.1"
#define PICOQUIC_ERROR_CLASS 0x400
#define PICOQUIC_ERROR_DUPLICATE (PICOQUIC_ERROR_CLASS + 1)
#define PICOQUIC_ERROR_AEAD_CHECK (PICOQUIC_ERROR_CLASS + 3)
Expand Down
15 changes: 12 additions & 3 deletions picoquic/picoquic_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,16 @@ typedef struct st_picoquictest_sim_packet_t {
uint8_t bytes[PICOQUIC_MAX_PACKET_SIZE];
} picoquictest_sim_packet_t;


typedef struct st_picoquictest_sim_link_t picoquictest_sim_link_t;
typedef struct st_picoquictest_aqm_t picoquictest_aqm_t;

typedef struct st_picoquictest_aqm_t {
void (*submit) (picoquictest_aqm_t* self, picoquictest_sim_link_t* link,
picoquictest_sim_packet_t* packet, uint64_t current_time, int* should_drop, int* should_mark_ce);
void (*release) (picoquictest_aqm_t* self, struct st_picoquictest_sim_link_t* link);
} picoquctest_aqm_t;

typedef enum {
jitter_gauss = 0,
jitter_wifi
Expand Down Expand Up @@ -299,9 +309,8 @@ typedef struct st_picoquictest_sim_link_t {
uint64_t packets_sent_next_burst; /* Next burst starts when this many packets are sent. */
uint64_t nb_losses_this_burst; /* Number of packets still to lose in this burst */
uint64_t end_of_burst_time; /* Bursts are limited in time to avoid silly effects */
/* Variables for random early drop simulation */
uint64_t red_drop_mask;
uint64_t red_queue_max;
/* Active queue management */
struct st_picoquictest_aqm_t* aqm_state;
/* L4S MAX sets the ECN mark threshold if doing L4S or DCTCP style ECN marking. */
uint64_t l4s_max;
/* Variables for rate limiter simulation */
Expand Down
24 changes: 12 additions & 12 deletions picoquic/sim_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ picoquictest_sim_link_t* picoquictest_sim_link_create(double data_rate_in_gps,
link->jitter_seed = 0xDEADBEEFBABAC001ull;
link->jitter = 0;
link->path_mtu = PICOQUIC_MAX_PACKET_SIZE;
link->red_drop_mask = 0;
link->red_queue_max = 0;
link->bucket_increase_per_microsec = 0;
link->bucket_max = 0;
link->bucket_current = 0;
Expand All @@ -76,6 +74,10 @@ void picoquictest_sim_link_delete(picoquictest_sim_link_t* link)
free(packet);
}

if (link->aqm_state != NULL) {
link->aqm_state->release(link->aqm_state, link);
}

free(link);
}

Expand Down Expand Up @@ -230,7 +232,8 @@ void picoquictest_sim_link_submit(picoquictest_sim_link_t* link, picoquictest_si
{
uint64_t queue_delay = (current_time > link->queue_time) ? 0 : link->queue_time - current_time;
uint64_t transmit_time = ((link->picosec_per_byte * ((uint64_t)packet->length)) >> 20);
uint64_t should_drop = 0;
int should_drop = 0;
int should_mark_ce;

if (transmit_time <= 0)
transmit_time = 1;
Expand Down Expand Up @@ -261,15 +264,12 @@ void picoquictest_sim_link_submit(picoquictest_sim_link_t* link, picoquictest_si
else {
should_drop = 1;
}
} else if (link->queue_delay_max > 0 && queue_delay >= link->queue_delay_max) {
if (link->red_drop_mask == 0 || queue_delay >= link->red_queue_max) {
should_drop = 1;
}
else {
should_drop = link->red_drop_mask & 1;
link->red_drop_mask >>= 1;
link->red_drop_mask |= (should_drop << 63);
}
}
else if (link->aqm_state != NULL) {
link->aqm_state->submit(link->aqm_state, link, packet, current_time, &should_drop, &should_mark_ce);
}
else if (link->queue_delay_max > 0 && queue_delay >= link->queue_delay_max) {
should_drop = 1;
}

if (!should_drop) {
Expand Down
1 change: 1 addition & 0 deletions picoquictest/picoquictest.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
<ClCompile Include="qlog_test.c" />
<ClCompile Include="quicperf_test.c" />
<ClCompile Include="quic_tester.c" />
<ClCompile Include="red_aqm.c" />
<ClCompile Include="sacktest.c" />
<ClCompile Include="satellite_test.c" />
<ClCompile Include="skip_frame_test.c" />
Expand Down
3 changes: 3 additions & 0 deletions picoquictest/picoquictest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@
<ClCompile Include="flow_control_test.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="red_aqm.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="picoquictest.h">
Expand Down
37 changes: 37 additions & 0 deletions picoquictest/picoquictest_red.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Author: Christian Huitema
* Copyright (c) 2025, Private Octopus, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef PICOQUICTEST_RED_H
#define PICOQUICTEST_RED_H

#include "picoquic_utils.h"

#ifdef __cplusplus
extern "C" {
#endif

int red_aqm_configure(picoquictest_sim_link_t* link, uint64_t red_threshold, uint64_t red_queue_max);

#ifdef __cplusplus
}
#endif

#endif /* PICOQUICTEST_RED_H */
90 changes: 90 additions & 0 deletions picoquictest/red_aqm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Author: Christian Huitema
* Copyright (c) 2025, Private Octopus, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* Implementation of the RED algorithm as a basic active queue management
* for picoquic_ns.
*/

#include "picoquic_internal.h"
#include "picoquic_utils.h"
#include "picosocks.h"
#include <stdlib.h>
#include <string.h>

typedef struct st_red_aqm_state_t {
struct st_picoquictest_aqm_t super;
uint64_t red_threshold; /* threshold for starting to drop packets */
uint64_t red_queue_max; /* all packets above that are dropped. */
uint64_t red_drop_mask; /* kinda randomize the drops. */
} red_aqm_state_t;

void red_aqm_submit(picoquictest_aqm_t* self, picoquictest_sim_link_t* link,
picoquictest_sim_packet_t* packet, uint64_t current_time, int* should_drop, int* should_mark_ce)
{
red_aqm_state_t* red_state = (red_aqm_state_t*)self;
uint64_t queue_delay = (current_time > link->queue_time) ? 0 : link->queue_time - current_time;

*should_drop = 0;
*should_mark_ce = 0;

if (queue_delay >= red_state->red_threshold)
{
if (red_state->red_drop_mask == 0 || queue_delay >= red_state->red_queue_max) {
*should_drop = 1;
}
else {
/* (poor) simulation of a 50% random drop */
uint64_t mask_bit = red_state->red_drop_mask & 1;
red_state->red_drop_mask >>= 1;
red_state->red_drop_mask |= (mask_bit << 63);
*should_drop = (int)mask_bit;
}
}
}

void red_aqm_release(picoquictest_aqm_t* self, picoquictest_sim_link_t* link)
{
free(self);
link->aqm_state = NULL;
}

int red_aqm_configure(picoquictest_sim_link_t* link, uint64_t red_threshold, uint64_t red_queue_max)
{
int ret = 0;
/* Create a configuration */
red_aqm_state_t * red_state = (red_aqm_state_t*)malloc(sizeof(red_aqm_state_t));

if (red_state == NULL) {
ret = PICOQUIC_ERROR_MEMORY;
}
else {
memset(red_state, 0, sizeof(red_aqm_state_t));
red_state->super.submit = red_aqm_submit;
red_state->super.release = red_aqm_release;
red_state->red_threshold = red_threshold;
red_state->red_queue_max = red_queue_max;
red_state->red_drop_mask = 0x5555555555555555ull;

link->aqm_state = &red_state->super;
}
return ret;
}
10 changes: 5 additions & 5 deletions picoquictest/tls_api_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -10562,13 +10562,13 @@ int grease_quic_bit_one_way_test()

/* Test effects of random early drop active queue management
*/
#include "picoquictest_red.h"

static int red_cc_algotest(picoquic_congestion_algorithm_t* cc_algo, uint64_t target_time, uint64_t loss_target)
{
uint64_t simulated_time = 0;
uint64_t loss_mask = 0;
const uint64_t latency_target = 7500;
const uint64_t red_drop_mask = 0x5555555555555555ull;
const uint64_t queue_max_red = 40000;
const uint64_t picosec_per_byte = (1000000ull * 8) /100;
uint64_t observed_loss = 0;
Expand All @@ -10585,17 +10585,17 @@ static int red_cc_algotest(picoquic_congestion_algorithm_t* cc_algo, uint64_t ta
if (ret == 0) {
/* Set parameters to simulate random early drop */
test_ctx->c_to_s_link->microsec_latency = latency_target;
test_ctx->c_to_s_link->red_drop_mask = red_drop_mask;
test_ctx->c_to_s_link->red_queue_max = queue_max_red;
test_ctx->c_to_s_link->picosec_per_byte = picosec_per_byte;
test_ctx->s_to_c_link->microsec_latency = latency_target;
test_ctx->s_to_c_link->red_drop_mask = red_drop_mask;
test_ctx->s_to_c_link->red_queue_max = queue_max_red;
test_ctx->s_to_c_link->picosec_per_byte = picosec_per_byte;
/* Set the CC algorithm to selected value */
picoquic_set_default_congestion_algorithm(test_ctx->qserver, cc_algo);
picoquic_set_binlog(test_ctx->qserver, ".");
test_ctx->qserver->use_long_log = 1;
/* Setting the RED threshold to the latency target, for simplification. */
if ((ret = red_aqm_configure(test_ctx->c_to_s_link, latency_target, queue_max_red)) == 0) {
ret = red_aqm_configure(test_ctx->s_to_c_link, latency_target, queue_max_red);
}
}

if (ret == 0) {
Expand Down
Loading