Add probabilistic use of TCP_FASTOPEN and close()

This commit is contained in:
Ian Gulliver
2016-03-05 15:27:11 -08:00
parent cef259f5c4
commit 46d67ca376
4 changed files with 54 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
COMP ?= clang
DISABLED_WARNINGS ?= -Wno-padded
DISABLED_WARNINGS ?= -Wno-padded -Wno-disabled-macro-expansion
CFLAGS ?= -Weverything -Werror -O3 -g --std=gnu11 --pedantic-errors -fPIE -fstack-protector-strong -D_GNU_SOURCE $(DISABLED_WARNINGS)
LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now -pie
LIBS ?=

9
rand.c
View File

@@ -50,3 +50,12 @@ void rand_fill(void *value, size_t size) {
rand_buf.start = 0;
rand_buf.length = BUF_LEN_MAX;
}
bool rand_yes_no(uint64_t mean_yes_period) {
if (!mean_yes_period) {
return false;
}
uint64_t val;
rand_fill(&val, sizeof(val));
return !(val % mean_yes_period);
}

2
rand.h
View File

@@ -1,7 +1,9 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
void rand_init(void);
void rand_cleanup(void);
void rand_fill(void *, size_t);
bool rand_yes_no(uint64_t);

View File

@@ -30,9 +30,13 @@ static struct {
char *service;
uint32_t num_conns;
uint32_t cycle_ms;
uint32_t fastopen_chance;
uint32_t close_chance;
} config = {
.num_conns = 100,
.cycle_ms = 150,
.fastopen_chance = 2,
.close_chance = 500,
};
struct file {
@@ -69,12 +73,14 @@ static void do_shutdown(int __attribute__((unused)) signal) {
static bool parse_opts(int argc, char *argv[]) {
static struct option long_options[] = {
{"blob-dir", required_argument, 0, 'b'},
{"host", required_argument, 0, 'h'},
{"port", required_argument, 0, 'p'},
{"cycle-ms", required_argument, 0, 'c'},
{"num-conns", required_argument, 0, 'n'},
{0, 0, 0, 0 },
{"blob-dir", required_argument, 0, 'b'},
{"host", required_argument, 0, 'h'},
{"port", required_argument, 0, 'p'},
{"cycle-ms", required_argument, 0, 'c'},
{"num-conns", required_argument, 0, 'n'},
{"fastopen-chance", required_argument, 0, 'f'},
{"close-chance", required_argument, 0, 'l'},
{0, 0, 0, 0 },
};
int opt;
@@ -101,6 +107,14 @@ static bool parse_opts(int argc, char *argv[]) {
assert(config.num_conns);
break;
case 'f':
config.fastopen_chance = (uint32_t) strtoul(optarg, NULL, 10);
break;
case 'l':
config.close_chance = (uint32_t) strtoul(optarg, NULL, 10);
break;
default:
return false;
}
@@ -238,12 +252,12 @@ static void conn_new() {
assert(conn);
conn->fd = socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK, 0);
assert(conn->fd >= 0);
// TODO: consider sending data here
char buf[1];
sendto(conn->fd, buf, 0, MSG_DONTWAIT | MSG_FASTOPEN, addrs[0].ai_addr, addrs[0].ai_addrlen);
conn->file = file_next();
conn->start_cycle = cycle;
conn->offset = 0;
conn->offset = rand_yes_no(config.fastopen_chance) ? conn_get_split(conn) : 0;
sendto(conn->fd, conn->file->buf, conn->offset, MSG_DONTWAIT | MSG_FASTOPEN, addrs[0].ai_addr, addrs[0].ai_addrlen);
conn->start_cycle = cycle;
list_add(&conn->conn_list, &conn_pending_head);
struct epoll_event ev = {
.events = EPOLLOUT,
@@ -292,14 +306,27 @@ static void conn_send_message(struct conn *conn) {
conn_send_not_ready++;
return;
}
size_t remaining = conn->file->len - conn->offset;
if (conn->offset == conn->file->len) {
conn_del(conn);
return;
}
if (rand_yes_no(config.close_chance)) {
conn_del(conn);
return;
}
size_t to_send = conn_get_split(conn);
if (send(conn->fd, conn->file->buf + conn->offset, to_send, MSG_DONTWAIT | MSG_NOSIGNAL) != (ssize_t) to_send ||
to_send == remaining) {
if (send(conn->fd, conn->file->buf + conn->offset, to_send, MSG_DONTWAIT | MSG_NOSIGNAL) != (ssize_t) to_send) {
conn_del(conn);
return;
}
conn->offset += to_send;
if (conn->offset == conn->file->len) {
conn_del(conn);
return;
}
}
static void conn_check(struct conn *conn) {
@@ -352,6 +379,8 @@ int main(int argc, char *argv[]) {
"\t--port=PORT [required]\n"
"\t--cycle-ms=CYCLE_MILLSECONDS [default 150]\n"
"\t--num-conns=PARALLEL_CONNECTIONS [default 100]\n"
"\t--fastopen-chance=CHANCE [default 2]\n"
"\t--close-chance=CHANCE [default 500]\n"
, argv[0]);
exit(EXIT_FAILURE);
}