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 available path count API #363

Merged
merged 15 commits into from
Nov 5, 2023
68 changes: 55 additions & 13 deletions demo/demo_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ typedef struct xqc_demo_cli_quic_config_s {

uint8_t mp_version;

uint8_t test_path_status;
uint8_t send_path_standby;
xqc_msec_t path_status_timer_threshold;

} xqc_demo_cli_quic_config_t;

Expand Down Expand Up @@ -397,7 +398,10 @@ typedef struct xqc_demo_cli_user_conn_s {
xqc_demo_cli_ctx_t *ctx;
xqc_demo_cli_task_t *task;

int send_path_available;
int send_path_standby;
int path_status; /* 0:available 1:standby */
xqc_msec_t path_status_time;
xqc_msec_t path_status_timer_threshold;
} xqc_demo_cli_user_conn_t;

static void
Expand Down Expand Up @@ -958,6 +962,40 @@ xqc_demo_cli_hq_req_write_notify(xqc_hq_request_t *hqr, void *req_user_data)
return 0;
}

void
xqc_demo_path_status_trigger(xqc_demo_cli_user_conn_t *user_conn)
{
xqc_msec_t ts_now = xqc_demo_now(), path_status_time = 0;

if (user_conn->send_path_standby) {

/* set initial path standby here */
if (user_conn->path_status == 0
&& xqc_conn_available_paths(user_conn->ctx->engine, &user_conn->cid) >= 2)
{
if (ts_now > user_conn->path_status_time + user_conn->path_status_timer_threshold) {
xqc_conn_mark_path_standby(user_conn->ctx->engine, &user_conn->cid, 0);
user_conn->path_status = 1; /* 1:standby */

user_conn->path_status_time = ts_now;
printf("mark_path_standby: path_id=0 path_status=%d now=%"PRIu64" pre=%"PRIu64" threshold=%"PRIu64"\n",
user_conn->path_status, ts_now, user_conn->path_status_time, user_conn->path_status_timer_threshold);
}

} else if (user_conn->path_status == 1) {

if (ts_now > user_conn->path_status_time + user_conn->path_status_timer_threshold) {
xqc_conn_mark_path_available(user_conn->ctx->engine, &user_conn->cid, 0);
user_conn->path_status = 0; /* 0:available */

user_conn->path_status_time = ts_now;
printf("mark_path_available: path_id=0 path_status=%d now=%"PRIu64" pre=%"PRIu64" threshold=%"PRIu64"\n",
user_conn->path_status, ts_now, user_conn->path_status_time, user_conn->path_status_timer_threshold);
}
}
}
}

int
xqc_demo_cli_hq_req_read_notify(xqc_hq_request_t *hqr, void *req_user_data)
{
Expand All @@ -967,6 +1005,8 @@ xqc_demo_cli_hq_req_read_notify(xqc_hq_request_t *hqr, void *req_user_data)
char buff[4096] = {0};
size_t buff_size = 4096;

xqc_demo_path_status_trigger(user_stream->user_conn);

ssize_t read = 0;
ssize_t read_sum = 0;
do {
Expand Down Expand Up @@ -1074,6 +1114,7 @@ xqc_demo_cli_h3_request_write_notify(xqc_h3_request_t *h3_request, void *user_da
return 0;
}


int
xqc_demo_cli_h3_request_read_notify(xqc_h3_request_t *h3_request, xqc_request_notify_flag_t flag,
void *user_data)
Expand All @@ -1084,6 +1125,9 @@ xqc_demo_cli_h3_request_read_notify(xqc_h3_request_t *h3_request, xqc_request_no
xqc_demo_cli_task_ctx_t *ctx = &user_stream->user_conn->ctx->task_ctx;
xqc_demo_cli_user_conn_t *user_conn = user_stream->user_conn;
uint32_t task_idx = user_conn->task->task_idx;

xqc_demo_path_status_trigger(user_conn);

// printf("xqc_demo_cli_h3_request_read_notify, h3_request: %p, user_stream: %p\n", h3_request, user_stream);
if (flag & XQC_REQ_NOTIFY_READ_HEADER) {
xqc_http_headers_t *headers;
Expand Down Expand Up @@ -1721,7 +1765,7 @@ xqc_demo_cli_usage(int argc, char *argv[])
" -T Throttle recving rate (Bps)\n"
" -R Reinjection (1,2,4) \n"
" -V Multipath Version (4,5,6)\n"
" -B Set path B standby after 600ms\n"
" -B Set initial path standby after recvd first application data, and set initial path available after X ms\n"
" -I Idle interval between requests (ms)\n"
" -n Throttling the {1,2,...}xn-th requests\n"
" -e NAT rebinding on path 0\n"
Expand Down Expand Up @@ -1936,8 +1980,9 @@ xqc_demo_cli_parse_args(int argc, char *argv[], xqc_demo_cli_client_args_t *args
break;

case 'B':
printf("option multipath set path status: %s\n", optarg);
args->quic_cfg.test_path_status = 1;
printf("option multipath set path status: %s ms\n", optarg);
args->quic_cfg.send_path_standby = 1;
args->quic_cfg.path_status_timer_threshold = atoi(optarg) * 1000;
break;

case 'I':
Expand Down Expand Up @@ -2199,12 +2244,6 @@ xqc_demo_cli_h3_conn_handshake_finished(xqc_h3_conn_t *h3_conn, void *user_data)
xqc_conn_stats_t stats = xqc_conn_get_stats(user_conn->ctx->engine, &user_conn->cid);
printf("0rtt_flag:%d\n", stats.early_data_flag);

if (user_conn->send_path_available) {
/* set initial path available here */
xqc_conn_mark_path_standby(user_conn->ctx->engine, &user_conn->cid, 0);
xqc_conn_mark_path_available(user_conn->ctx->engine, &user_conn->cid, 0);
}

}

void
Expand Down Expand Up @@ -2391,9 +2430,12 @@ xqc_demo_cli_init_xquic_connection(xqc_demo_cli_user_conn_t *user_conn,

if (conn_settings.enable_multipath
&& conn_settings.multipath_version >= XQC_MULTIPATH_06
&& args->quic_cfg.test_path_status == 1)
&& args->quic_cfg.send_path_standby == 1)
{
user_conn->send_path_available = 1;
user_conn->send_path_standby = 1;
user_conn->path_status = 0;
user_conn->path_status_timer_threshold = args->quic_cfg.path_status_timer_threshold;
user_conn->path_status_time = 0;
}

return 0;
Expand Down
9 changes: 9 additions & 0 deletions include/xquic/xquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,15 @@ XQC_EXPORT_PUBLIC_API
xqc_int_t xqc_conn_mark_path_frozen(xqc_engine_t *engine, const xqc_cid_t *cid, uint64_t path_id);


/**
* Calculate how many available paths on the current connection, i.e., paths which finished validation and is marked "available" status.
* @param engine xquic engine ctx
* @param cid scid for connection
* @return number of available paths when success, <0 for error
*/
XQC_EXPORT_PUBLIC_API xqc_int_t xqc_conn_available_paths(xqc_engine_t *engine, const xqc_cid_t *cid);


XQC_EXPORT_PUBLIC_API
xqc_conn_type_t xqc_conn_get_type(xqc_connection_t *conn);

Expand Down
1 change: 1 addition & 0 deletions scripts/xquic.lds
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ XQUIC_VERS_1.0 {
xqc_conn_mark_path_standby;
xqc_conn_mark_path_available;
xqc_conn_mark_path_frozen;
xqc_conn_available_paths;
xqc_dcid_str_by_scid;
xqc_h3_ctx_init;
xqc_h3_ctx_destroy;
Expand Down
28 changes: 28 additions & 0 deletions src/transport/xqc_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -5595,6 +5595,34 @@ xqc_conn_handle_stateless_reset(xqc_connection_t *conn,
}


xqc_int_t
xqc_conn_available_paths(xqc_engine_t *engine, const xqc_cid_t *cid)
{
xqc_int_t available_paths = 0;
xqc_connection_t *conn = xqc_engine_conns_hash_find(engine, cid, 's');
if (conn == NULL) {
/* no connection found */
return available_paths;
}

xqc_path_ctx_t *path;
xqc_list_head_t *path_pos, *path_next;

xqc_list_for_each_safe(path_pos, path_next, &conn->conn_paths_list) {
path = xqc_list_entry(path_pos, xqc_path_ctx_t, path_list);
if (path->path_state < XQC_PATH_STATE_VALIDATING) {
continue;
}
if (path->path_state == XQC_PATH_STATE_ACTIVE) {
available_paths++;
}
}

xqc_log(conn->log, XQC_LOG_DEBUG, "|xqc_conn_available_paths|%" PRId32 "|", available_paths);
return available_paths;
}


#ifdef XQC_COMPAT_GENERATE_SR_PKT

xqc_int_t
Expand Down
1 change: 1 addition & 0 deletions src/transport/xqc_conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,4 +666,5 @@ void xqc_conn_destroy_ping_notification_list(xqc_connection_t *conn);

xqc_int_t xqc_conn_send_ping_internal(xqc_connection_t *conn, void *ping_user_data, xqc_bool_t notify);


#endif /* _XQC_CONN_H_INCLUDED_ */
Loading