2022-05-06 16:49:46 +00:00
|
|
|
/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
|
2017-09-22 21:00:03 +00:00
|
|
|
/*
|
|
|
|
* This is not really a test: this program prints out cwnd histogram
|
|
|
|
* for visual inspection.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2018-03-12 22:25:01 +00:00
|
|
|
#ifndef WIN32
|
2017-09-22 21:00:03 +00:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
2018-03-12 22:25:01 +00:00
|
|
|
#else
|
|
|
|
#include <getopt.h>
|
|
|
|
#endif
|
2017-09-22 21:00:03 +00:00
|
|
|
|
|
|
|
#include "lsquic_types.h"
|
|
|
|
#include "lsquic_int_types.h"
|
2019-09-11 15:27:58 +00:00
|
|
|
#include "lsquic_cong_ctl.h"
|
|
|
|
#include "lsquic_packet_common.h"
|
|
|
|
#include "lsquic_packet_out.h"
|
2017-09-22 21:00:03 +00:00
|
|
|
#include "lsquic_cubic.h"
|
|
|
|
|
2019-09-11 15:27:58 +00:00
|
|
|
static const struct cong_ctl_if *const cci = &lsquic_cong_cubic_if;
|
2017-09-22 21:00:03 +00:00
|
|
|
|
|
|
|
#define MS(n) ((n) * 1000) /* MS: Milliseconds */
|
|
|
|
|
|
|
|
enum event { EV_ACK, EV_LOSS, EV_TIMEOUT, };
|
|
|
|
|
|
|
|
static const char *const evstr[] = {
|
|
|
|
[EV_ACK] = "ACK",
|
|
|
|
[EV_LOSS] = "LOSS",
|
|
|
|
[EV_TIMEOUT] = "TIMEOUT",
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rec
|
|
|
|
{
|
|
|
|
enum event event;
|
|
|
|
unsigned cwnd;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define REC(ev) do { \
|
|
|
|
if (i >= n_recs_alloc) \
|
|
|
|
{ \
|
|
|
|
if (n_recs_alloc) \
|
|
|
|
n_recs_alloc *= 2; \
|
|
|
|
else \
|
|
|
|
n_recs_alloc = 20; \
|
|
|
|
recs = realloc(recs, n_recs_alloc * \
|
|
|
|
sizeof(recs[0])); \
|
|
|
|
} \
|
|
|
|
recs[i].event = ev; \
|
2019-09-11 15:27:58 +00:00
|
|
|
recs[i].cwnd = cci->cci_get_cwnd(&cubic); \
|
2017-09-22 21:00:03 +00:00
|
|
|
if (max_cwnd < recs[i].cwnd) \
|
|
|
|
max_cwnd = recs[i].cwnd; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
|
|
|
{
|
|
|
|
int i, n, opt;
|
|
|
|
int n_recs_alloc = 0;
|
|
|
|
int app_limited = 0;
|
|
|
|
unsigned unit = 100; /* Default to 100 ms */
|
|
|
|
unsigned rtt_ms = 10; /* Default to 10 ms */
|
|
|
|
struct lsquic_cubic cubic;
|
|
|
|
struct rec *recs = NULL;
|
|
|
|
unsigned max_cwnd, width;
|
|
|
|
char *line;
|
2018-03-12 22:25:01 +00:00
|
|
|
#ifndef WIN32
|
2017-09-22 21:00:03 +00:00
|
|
|
struct winsize winsize;
|
2018-03-12 22:25:01 +00:00
|
|
|
#endif
|
2017-09-22 21:00:03 +00:00
|
|
|
enum cubic_flags flags;
|
2019-09-11 15:27:58 +00:00
|
|
|
struct lsquic_packet_out packet_out;
|
2017-09-22 21:00:03 +00:00
|
|
|
|
2019-09-11 15:27:58 +00:00
|
|
|
cci->cci_init(&cubic, 0, 0);
|
2017-09-22 21:00:03 +00:00
|
|
|
max_cwnd = 0;
|
|
|
|
i = 0;
|
2019-09-11 15:27:58 +00:00
|
|
|
memset(&packet_out, 0, sizeof(packet_out));
|
2017-09-22 21:00:03 +00:00
|
|
|
|
|
|
|
while (-1 != (opt = getopt(argc, argv, "s:u:r:f:l:A:L:T:")))
|
|
|
|
{
|
|
|
|
switch (opt)
|
|
|
|
{
|
|
|
|
case 's':
|
|
|
|
cubic.cu_ssthresh = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
rtt_ms = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
flags = atoi(optarg);
|
2019-09-11 15:27:58 +00:00
|
|
|
lsquic_cubic_set_flags(&cubic, flags);
|
2017-09-22 21:00:03 +00:00
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
app_limited = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
n = i + atoi(optarg);
|
|
|
|
for ( ; i < n; ++i)
|
|
|
|
{
|
2019-09-11 15:27:58 +00:00
|
|
|
packet_out.po_sent = MS(unit * i) - MS(rtt_ms);
|
|
|
|
cci->cci_ack(&cubic, &packet_out, 1370, MS(unit * i), app_limited);
|
2017-09-22 21:00:03 +00:00
|
|
|
REC(EV_ACK);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
n = i + atoi(optarg);
|
|
|
|
for ( ; i < n; ++i)
|
|
|
|
{
|
2019-09-11 15:27:58 +00:00
|
|
|
cci->cci_loss(&cubic);
|
2017-09-22 21:00:03 +00:00
|
|
|
REC(EV_LOSS);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
n = i + atoi(optarg);
|
|
|
|
for ( ; i < n; ++i)
|
|
|
|
{
|
2019-09-11 15:27:58 +00:00
|
|
|
cci->cci_timeout(&cubic);
|
2017-09-22 21:00:03 +00:00
|
|
|
REC(EV_TIMEOUT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
unit = atoi(optarg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-12 22:25:01 +00:00
|
|
|
#ifndef WIN32
|
2017-09-22 21:00:03 +00:00
|
|
|
if (isatty(STDIN_FILENO))
|
|
|
|
{
|
|
|
|
if (0 == ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
|
|
|
|
width = winsize.ws_col;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
perror("ioctl");
|
|
|
|
width = 80;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2018-03-12 22:25:01 +00:00
|
|
|
#endif
|
2017-09-22 21:00:03 +00:00
|
|
|
width = 80;
|
|
|
|
|
|
|
|
width -= 5 /* cwnd */ + 1 /* space */ + 1 /* event type */ +
|
|
|
|
1 /* space */ + 1 /* newline */;
|
|
|
|
line = malloc(width);
|
|
|
|
memset(line, '+', width);
|
|
|
|
|
|
|
|
for (n = i, i = 0; i < n; ++i)
|
|
|
|
printf("%c % 5d %.*s\n", *evstr[recs[i].event], recs[i].cwnd,
|
|
|
|
(int) ((float) recs[i].cwnd / max_cwnd * width), line);
|
|
|
|
|
|
|
|
free(recs);
|
|
|
|
free(line);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|