Skip to content

Commit 834db2e

Browse files
committed
Option for user defined varylink
1 parent 24c8097 commit 834db2e

File tree

6 files changed

+135
-67
lines changed

6 files changed

+135
-67
lines changed

UnitTest1/unittest1.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,13 @@ namespace UnitTest1
20702070
Assert::AreEqual(ret, 0);
20712071
}
20722072

2073+
TEST_METHOD(cc_ns_varylink)
2074+
{
2075+
int ret = cc_ns_varylink_test();
2076+
2077+
Assert::AreEqual(ret, 0);
2078+
}
2079+
20732080
TEST_METHOD(fastcc)
20742081
{
20752082
int ret = fastcc_test();

picohttp_t/picohttp_t.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ static const picoquic_test_def_t test_table[] = {
116116
{ "cc_ns_drop_and_back", cc_ns_drop_and_back_test },
117117
{ "cc_ns_low_and_up", cc_ns_low_and_up_test },
118118
{ "cc_ns_wifi_fade", cc_ns_wifi_fade_test },
119-
{ "cc_ns_wifi_suspension", cc_ns_wifi_suspension_test }
119+
{ "cc_ns_wifi_suspension", cc_ns_wifi_suspension_test },
120+
{ "cc_ns_varylink", cc_ns_varylink_test }
120121
};
121122

122123
static size_t const nb_tests = sizeof(test_table) / sizeof(picoquic_test_def_t);

picoquictest/cc_compete_test.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ int cc_ns_low_and_up_test()
219219
return picoquic_ns(&spec);
220220
}
221221

222-
223222
/* Check that the picoquic_ns simulations can correctly test the low_and_up scenario.
224223
*/
225224
int cc_ns_wifi_fade_test()
@@ -267,4 +266,39 @@ int cc_ns_wifi_suspension_test()
267266
spec.link_scenario = link_scenario_wifi_suspension;
268267

269268
return picoquic_ns(&spec);
270-
}
269+
}
270+
271+
272+
/* Check that the picoquic_ns simulations can correctly test the low_and_up scenario.
273+
* The simple scenario merely duplicates the "wifi fade" scenario, the only difference
274+
* being that the "varylink" structure is user specified.
275+
*/
276+
picoquic_ns_link_spec_t cc_varylink_test_spec[] = {
277+
{ 1000000, 0.01, 0.01, 5000, 0, 15000, 0 },
278+
{ 2000000, 0.001, 0.001, 5000, 0, 15000, 0 },
279+
{ UINT64_MAX, 0.01, 0.01, 5000, 0, 15000, 0 }
280+
};
281+
282+
int cc_ns_varylink_test()
283+
{
284+
picoquic_ns_spec_t spec = { 0 };
285+
picoquic_connection_id_t icid = { { 0xcc, 0x11, 0xbb, 0, 0, 0, 0, 0}, 8 };
286+
spec.main_cc_algo = picoquic_bbr_algorithm;
287+
spec.main_start_time = 0;
288+
spec.main_scenario_text = cc_compete_batch_scenario_4M;
289+
spec.background_cc_algo = picoquic_bbr_algorithm;
290+
spec.background_start_time = 0;
291+
spec.background_scenario_text = cc_compete_batch_scenario_10M;
292+
spec.nb_connections = 1;
293+
spec.data_rate_in_gbps = 0.01;
294+
spec.latency = 5000;
295+
spec.main_target_time = 7000000;
296+
spec.queue_delay_max = 15000;
297+
spec.icid = icid;
298+
spec.qlog_dir = ".";
299+
spec.link_scenario = link_scenario_none;
300+
spec.vary_link_nb = sizeof(cc_varylink_test_spec) / sizeof(picoquic_ns_link_spec_t);
301+
spec.vary_link_spec = cc_varylink_test_spec;
302+
303+
return picoquic_ns(&spec);
304+
}

picoquictest/picoquic_ns.c

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,18 @@
6262
* default callback function for the server context. When a new connection
6363
* arrives, the server uses the "cc_compete" context to find the matching
6464
* client connection, discover the desired congestion algorithm, and
65-
* program it in the server side connection context
65+
* program it in the server side connection context.
6666
*
6767
* The main advantages of this simulation are:
6868
* - Running the actual picoquic code.
6969
* - Operating in "virtual time", much faster than "real time".
7070
*
71+
* We can simulate a link with a capacity and a latency varies over time. The
72+
* API provides two ways to do that:
73+
*
74+
* - either pick one of the predefines variation scenarios, such as `blackhole`
75+
* - or provide an array of
76+
*
7177
* There are limits to this setup:
7278
* - we set a maximum number of nodes, links, connections. This is not strictly
7379
* necessary. We could dynamically allocate arrays.
@@ -100,24 +106,14 @@ typedef struct st_picoquic_ns_client_t {
100106
picoquic_connection_id_t icid;
101107
} picoquic_ns_client_t;
102108

103-
typedef struct st_picoquic_ns_link_spec_t {
104-
uint64_t duration;
105-
double data_rate_in_gbps_up; /* datarate, server to clients, defaults to 10 mbps */
106-
double data_rate_in_gbps_down; /* datarate, server to clients, defaults to 10 mbps */
107-
uint64_t latency; /* one way latency, microseconds, both directions */
108-
uint64_t jitter; /* delay jitter, microseconds, both directions */
109-
uint64_t queue_delay_max; /* if specified, specify the max buffer queuing for the link, in microseconds */
110-
uint64_t l4s_max; /* if specified, specify the max buffer queuing for the link, in microseconds */
111-
} picoquic_ns_link_spec_t;
112-
113-
114109
typedef struct st_picoquic_ns_ctx_t {
115110
picoquic_quic_t* q_ctx[PICOQUIC_NS_NB_NODES];
116111
struct sockaddr_in addr[PICOQUIC_NS_NB_NODES];
117112
picoquictest_sim_link_t* link[PICOQUIC_NS_NB_LINKS];
118113
uint64_t simulated_time;
119114
int nb_connections;
120115
picoquic_ns_link_spec_t* vary_link_spec;
116+
int vary_link_is_user_provided;
121117
size_t vary_link_nb;
122118
uint64_t next_vary_link_time;
123119
size_t vary_link_index;
@@ -267,58 +263,65 @@ int picoquic_ns_create_default_link_spec(picoquic_ns_ctx_t* cc_ctx, picoquic_ns_
267263

268264
int picoquic_ns_create_link_spec(picoquic_ns_ctx_t* cc_ctx, picoquic_ns_spec_t* spec)
269265
{
270-
int ret;
266+
int ret = 0;
271267

272-
switch (spec->link_scenario) {
273-
case link_scenario_none:
274-
ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 1);
275-
break;
276-
case link_scenario_black_hole:
277-
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
278-
cc_ctx->vary_link_spec[0].duration = 2000000;
279-
cc_ctx->vary_link_spec[1].duration = 2000000;
280-
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
281-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down = 0;
282-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up = 0;
283-
}
284-
break;
285-
case link_scenario_drop_and_back:
286-
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
287-
cc_ctx->vary_link_spec[0].duration = 1500000;
288-
cc_ctx->vary_link_spec[1].duration = 2000000;
289-
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
290-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down *= 0.5;
291-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up *= 0.5;
292-
}
293-
break;
294-
case link_scenario_low_and_up:
295-
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 2)) == 0) {
296-
cc_ctx->vary_link_spec[0].duration = 2500000;
297-
cc_ctx->vary_link_spec[0].data_rate_in_gbps_down *= 0.5;
298-
cc_ctx->vary_link_spec[0].data_rate_in_gbps_up *= 0.5;
299-
cc_ctx->vary_link_spec[1].duration = UINT64_MAX;
300-
}
301-
break;
302-
case link_scenario_wifi_fade:
303-
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
304-
cc_ctx->vary_link_spec[0].duration = 1000000;
305-
cc_ctx->vary_link_spec[1].duration = 2000000;
306-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down *= 0.1;
307-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up *= 0.1;
308-
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
309-
}
310-
break;
311-
case link_scenario_wifi_suspension:
312-
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 2)) == 0) {
313-
cc_ctx->vary_link_spec[0].duration = 1800000;
314-
cc_ctx->vary_link_spec[1].duration = 200000;
315-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down = 0;
316-
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up = 0;
268+
if (spec->vary_link_nb > 0) {
269+
cc_ctx->vary_link_is_user_provided = 1;
270+
cc_ctx->vary_link_nb = spec->vary_link_nb;
271+
cc_ctx->vary_link_spec = spec->vary_link_spec;
272+
}
273+
else {
274+
switch (spec->link_scenario) {
275+
case link_scenario_none:
276+
ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 1);
277+
break;
278+
case link_scenario_black_hole:
279+
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
280+
cc_ctx->vary_link_spec[0].duration = 2000000;
281+
cc_ctx->vary_link_spec[1].duration = 2000000;
282+
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
283+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down = 0;
284+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up = 0;
285+
}
286+
break;
287+
case link_scenario_drop_and_back:
288+
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
289+
cc_ctx->vary_link_spec[0].duration = 1500000;
290+
cc_ctx->vary_link_spec[1].duration = 2000000;
291+
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
292+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down *= 0.5;
293+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up *= 0.5;
294+
}
295+
break;
296+
case link_scenario_low_and_up:
297+
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 2)) == 0) {
298+
cc_ctx->vary_link_spec[0].duration = 2500000;
299+
cc_ctx->vary_link_spec[0].data_rate_in_gbps_down *= 0.5;
300+
cc_ctx->vary_link_spec[0].data_rate_in_gbps_up *= 0.5;
301+
cc_ctx->vary_link_spec[1].duration = UINT64_MAX;
302+
}
303+
break;
304+
case link_scenario_wifi_fade:
305+
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 3)) == 0) {
306+
cc_ctx->vary_link_spec[0].duration = 1000000;
307+
cc_ctx->vary_link_spec[1].duration = 2000000;
308+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down *= 0.1;
309+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up *= 0.1;
310+
cc_ctx->vary_link_spec[2].duration = UINT64_MAX;
311+
}
312+
break;
313+
case link_scenario_wifi_suspension:
314+
if ((ret = picoquic_ns_create_default_link_spec(cc_ctx, spec, 2)) == 0) {
315+
cc_ctx->vary_link_spec[0].duration = 1800000;
316+
cc_ctx->vary_link_spec[1].duration = 200000;
317+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_down = 0;
318+
cc_ctx->vary_link_spec[1].data_rate_in_gbps_up = 0;
319+
}
320+
break;
321+
default:
322+
ret = -1;
323+
break;
317324
}
318-
break;
319-
default:
320-
ret = -1;
321-
break;
322325
}
323326
return ret;
324327
}
@@ -357,7 +360,8 @@ int picoquic_ns_create_links(picoquic_ns_ctx_t* cc_ctx, picoquic_ns_spec_t* spec
357360
}
358361
}
359362

360-
/* program the first transition if needed -- but this should be automatic */
363+
/* The simulation will automatically execute the transition to
364+
* the first "vary_link_spec" value. */
361365

362366
return ret;
363367
}
@@ -389,8 +393,11 @@ void picoquic_ns_delete_ctx(picoquic_ns_ctx_t* cc_ctx)
389393

390394
/* delete the link specifications */
391395
if (cc_ctx->vary_link_spec != NULL) {
392-
free(cc_ctx->vary_link_spec);
396+
if (!cc_ctx->vary_link_is_user_provided) {
397+
free(cc_ctx->vary_link_spec);
398+
}
393399
cc_ctx->vary_link_spec = NULL;
400+
cc_ctx->vary_link_nb = 0;
394401
}
395402
/* and then free the context itself */
396403
free(cc_ctx);

picoquictest/picoquic_ns.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ typedef enum {
4545
link_scenario_wifi_suspension
4646
} picoquic_ns_link_scenario_enum;
4747

48+
typedef struct st_picoquic_ns_link_spec_t {
49+
uint64_t duration;
50+
double data_rate_in_gbps_up; /* datarate, server to clients, defaults to 10 mbps */
51+
double data_rate_in_gbps_down; /* datarate, server to clients, defaults to 10 mbps */
52+
uint64_t latency; /* one way latency, microseconds, both directions */
53+
uint64_t jitter; /* delay jitter, microseconds, both directions */
54+
uint64_t queue_delay_max; /* if specified, specify the max buffer queuing for the link, in microseconds */
55+
uint64_t l4s_max; /* if specified, specify the max buffer queuing for the link, in microseconds */
56+
} picoquic_ns_link_spec_t;
57+
4858
typedef struct st_picoquic_ns_spec_t {
4959
uint64_t main_start_time;
5060
uint64_t main_target_time;
@@ -62,7 +72,15 @@ typedef struct st_picoquic_ns_spec_t {
6272
uint64_t l4s_max; /* if specified, specify the max buffer queuing for the link, in microseconds */
6373
picoquic_connection_id_t icid; /* if specified, set the ICID of connections. Last byte will be overwriten by connection number */
6474
char const* qlog_dir; /* if specified, set the qlog directory, and request qlog traces. */
75+
/* The specification can either specify one of the preprogrammed link scenarios,
76+
* or provide an array of varylink items specifying the variations of the link.
77+
* If "vary_link==0", the simulation will use the specified scenario.
78+
* If "vary_link_nb" is larger than zero, the simulation will use the provided
79+
* array "vary_link_spec" and ignore the "link_scenario" value.
80+
*/
6581
picoquic_ns_link_scenario_enum link_scenario; /* specify link transition scenario if needed */
82+
size_t vary_link_nb; /* Number of "vary_link" items */
83+
picoquic_ns_link_spec_t* vary_link_spec; /* one item for each of the successive states of the link. */
6684
} picoquic_ns_spec_t;
6785

6886
int picoquic_ns(picoquic_ns_spec_t* spec);

picoquictest/picoquictest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ int cc_ns_drop_and_back_test();
280280
int cc_ns_low_and_up_test();
281281
int cc_ns_wifi_fade_test();
282282
int cc_ns_wifi_suspension_test();
283+
int cc_ns_varylink_test();
283284
int satellite_basic_test();
284285
int satellite_seeded_test();
285286
int satellite_seeded_bbr1_test();

0 commit comments

Comments
 (0)