litespeed-quic/test/unittests/graph_cubic.c
Dmitri Tikhonov bfc7bfd842 Latest changes
- [API Change] lsquic_engine_connect() returns pointer to the connection
  object.
- [API Change] Add lsquic_conn_get_engine() to get engine object from
  connection object.
- [API Change] Add lsquic_conn_status() to query connection status.
- [API Change] Add add lsquic_conn_set_ctx().
- [API Change] Add new timestamp format, e.g. 2017-03-21 13:43:46.671345
- [OPTIMIZATION] Process handshake STREAM frames as soon as packet
  arrives.
- [OPTIMIZATION] Do not compile expensive send controller sanity check
  by default.
- [OPTIMIZATION] Add fast path to gquic_be_gen_reg_pkt_header.
- [OPTIMIZATION] Only make squeeze function call if necessary.
- [OPTIMIZATION] Speed up Q039 ACK frame parsing.
- [OPTIMIZATION] Fit most used elements of packet_out into first 64 bytes.
- [OPTIMIZATION] Keep track of scheduled bytes instead of calculating.
- [OPTIMIZATION] Prefetch next unacked packet when processing ACK.
- [OPTIMIZATION] Leverage fact that ACK ranges and unacked list are.
  ordered.
- [OPTIMIZATION] Reduce function pointer use for STREAM frame generation
- Fix: reset incoming streams that arrive after we send GOAWAY.
- Fix: delay client on_new_conn() call until connection is fully set up.
- Fixes to buffered packets logic: splitting, STREAM frame elision.
- Fix: do not dispatch on_write callback if no packets are available.
- Fix WINDOW_UPDATE send and resend logic.
- Fix STREAM frame extension code.
- Fix: Drop unflushed data when stream is reset.
- Switch to tracking CWND using bytes rather than packets.
- Fix TCP friendly adjustment in cubic.
- Fix: do not generate invalid STOP_WAITING frames during high packet
  loss.
- Pacer fixes.
2018-02-26 16:01:16 -05:00

145 lines
3.8 KiB
C

/* Copyright (c) 2017 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>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_cubic.h"
#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 = lsquic_cubic_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;
struct winsize winsize;
enum cubic_flags flags;
lsquic_cubic_init(&cubic, 0);
max_cwnd = 0;
i = 0;
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_init_ext(&cubic, 0, flags);
break;
case 'l':
app_limited = atoi(optarg);
break;
case 'A':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
lsquic_cubic_ack(&cubic, MS(unit * i), MS(rtt_ms), app_limited, 1370);
REC(EV_ACK);
}
break;
case 'L':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
lsquic_cubic_loss(&cubic);
REC(EV_LOSS);
}
break;
case 'T':
n = i + atoi(optarg);
for ( ; i < n; ++i)
{
lsquic_cubic_timeout(&cubic);
REC(EV_TIMEOUT);
}
break;
case 'u':
unit = atoi(optarg);
break;
default:
exit(1);
}
}
if (isatty(STDIN_FILENO))
{
if (0 == ioctl(STDIN_FILENO, TIOCGWINSZ, &winsize))
width = winsize.ws_col;
else
{
perror("ioctl");
width = 80;
}
}
else
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;
}