litespeed-quic/tests/graph_cubic.c

161 lines
4.1 KiB
C

/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
/*
* This is not really a test: this program prints out cwnd histogram
* for visual inspection.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#else
#include <getopt.h>
#endif
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_cong_ctl.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_out.h"
#include "lsquic_cubic.h"
static const struct cong_ctl_if *const cci = &lsquic_cong_cubic_if;
#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; \
recs[i].cwnd = cci->cci_get_cwnd(&cubic); \
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;
#ifndef WIN32
struct winsize winsize;
#endif
enum cubic_flags flags;
struct lsquic_packet_out packet_out;
cci->cci_init(&cubic, 0, 0);
max_cwnd = 0;
i = 0;
memset(&packet_out, 0, sizeof(packet_out));
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);
lsquic_cubic_set_flags(&cubic, flags);
break;
case 'l':
app_limited = atoi(optarg);
break;
case 'A':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
packet_out.po_sent = MS(unit * i) - MS(rtt_ms);
cci->cci_ack(&cubic, &packet_out, 1370, MS(unit * i), app_limited);
REC(EV_ACK);
}
break;
case 'L':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
cci->cci_loss(&cubic);
REC(EV_LOSS);
}
break;
case 'T':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
cci->cci_timeout(&cubic);
REC(EV_TIMEOUT);
}
break;
case 'u':
unit = atoi(optarg);
break;
default:
exit(1);
}
}
#ifndef WIN32
if (isatty(STDIN_FILENO))
{
if (0 == ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
width = winsize.ws_col;
else
{
perror("ioctl");
width = 80;
}
}
else
#endif
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;
}