New scheduler and cleanup

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2018-11-08 09:51:15 +00:00
parent ccaac70a04
commit ff55d6a173
2 changed files with 108 additions and 80 deletions

167
mud.c
View File

@@ -76,7 +76,7 @@
#define MUD_STAT_TIMEOUT (100 * MUD_ONE_MSEC) #define MUD_STAT_TIMEOUT (100 * MUD_ONE_MSEC)
#define MUD_KEYX_TIMEOUT (60 * MUD_ONE_MIN) #define MUD_KEYX_TIMEOUT (60 * MUD_ONE_MIN)
#define MUD_KEYX_RESET_TIMEOUT (120 * MUD_ONE_MSEC) #define MUD_KEYX_RESET_TIMEOUT (2 * MUD_STAT_TIMEOUT)
#define MUD_SEND_TIMEOUT (MUD_ONE_SEC) #define MUD_SEND_TIMEOUT (MUD_ONE_SEC)
#define MUD_TIME_TOLERANCE (10 * MUD_ONE_MIN) #define MUD_TIME_TOLERANCE (10 * MUD_ONE_MIN)
@@ -118,10 +118,12 @@ struct mud_packet {
struct mud_addr addr; struct mud_addr addr;
unsigned char pub[MUD_PUB_SIZE]; unsigned char pub[MUD_PUB_SIZE];
unsigned char aes; unsigned char aes;
unsigned char lat[MUD_U48_SIZE];
unsigned char latmin[MUD_U48_SIZE];
unsigned char rate[MUD_U48_SIZE]; unsigned char rate[MUD_U48_SIZE];
unsigned char ratemax[MUD_U48_SIZE]; unsigned char ratemax[MUD_U48_SIZE];
unsigned char rms[MUD_U48_SIZE]; unsigned char max[MUD_U48_SIZE];
unsigned char rmt[MUD_U48_SIZE]; unsigned char max_time[MUD_U48_SIZE];
}; };
struct mud { struct mud {
@@ -344,10 +346,30 @@ mud_select_path(struct mud *mud, unsigned k)
for (unsigned i = 0; i < mud->count; i++) { for (unsigned i = 0; i < mud->count; i++) {
struct mud_path *path = &mud->paths[i]; struct mud_path *path = &mud->paths[i];
if (path->state <= MUD_DOWN) path->prob = 0;
if (!path->ok || path->state <= MUD_DOWN)
continue; continue;
n += path->r_ratemax + path->ratevar; unsigned long long coef = 18;
uint64_t dt = (path->r_lat - path->r_latmin) / MUD_ONE_MSEC;
if (dt >= 300) {
coef = 0;
} else if (dt >= 50) {
coef = (16 - ((dt - 50) * 16)/(300 - 50)) + 1;
}
unsigned long long r = (path->r_ratemax * coef) / 16;
if (r == 0)
r = 10000;
if (path->send.bytes >= r)
continue;
path->prob = r - path->send.bytes;
n += path->prob;
} }
if (!n) if (!n)
@@ -359,10 +381,10 @@ mud_select_path(struct mud *mud, unsigned k)
for (unsigned i = 0; i < mud->count; i++) { for (unsigned i = 0; i < mud->count; i++) {
struct mud_path *path = &mud->paths[i]; struct mud_path *path = &mud->paths[i];
if (path->state <= MUD_DOWN) if (!path->prob)
continue; continue;
w += (((path->r_ratemax + path->ratevar) << 16) + (n >> 1)) / n; w += ((path->prob << 16) + (n >> 1)) / n;
last = path; last = path;
if (k <= w) if (k <= w)
@@ -447,9 +469,9 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now,
path->send.bytes += size; path->send.bytes += size;
path->send.time = now; path->send.time = now;
if (path->send_max <= size) { if (path->send.max <= size) {
path->send_max = size; path->send.max = size;
path->send_max_time = now; path->send.max_time = now;
} }
return ret; return ret;
@@ -568,6 +590,15 @@ mud_copy_port(struct sockaddr_storage *d, struct sockaddr_storage *s)
} }
} }
static void
mud_reset_path(struct mud *mud, struct mud_path *path)
{
path->state = MUD_UP;
path->mtu.ok = MUD_MTU;
path->mtu.probe = mud->mtu;
path->ok = 0;
}
static struct mud_path * static struct mud_path *
mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr, mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
struct sockaddr_storage *addr, int create) struct sockaddr_storage *addr, int create)
@@ -625,11 +656,7 @@ mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
memcpy(&path->local_addr, local_addr, sizeof(*local_addr)); memcpy(&path->local_addr, local_addr, sizeof(*local_addr));
memcpy(&path->addr, addr, sizeof(*addr)); memcpy(&path->addr, addr, sizeof(*addr));
path->state = MUD_UP; mud_reset_path(mud, path);
path->mtu.ok = MUD_MTU;
path->mtu.probe = mud->mtu;
path->ratevar = 10000000;
mud_update_mtu(mud); mud_update_mtu(mud);
return path; return path;
@@ -1139,8 +1166,10 @@ mud_packet_send(struct mud *mud, struct mud_path *path,
packet->aes = (unsigned char)mud->crypto.aes; packet->aes = (unsigned char)mud->crypto.aes;
mud_write48(packet->rms, path->recv_max); mud_write48(packet->lat, path->lat);
mud_write48(packet->rmt, path->recv_max_time); mud_write48(packet->latmin, path->latmin);
mud_write48(packet->max, path->recv.max);
mud_write48(packet->max_time, path->recv.max_time);
mud_write48(packet->rate, path->recv.rate); mud_write48(packet->rate, path->recv.rate);
mud_write48(packet->ratemax, path->recv.ratemax); mud_write48(packet->ratemax, path->recv.ratemax);
@@ -1266,21 +1295,18 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
mud->crypto.use_next = 1; mud->crypto.use_next = 1;
} }
path->r_rms = mud_read48(packet->rms); path->r_lat = mud_read48(packet->lat);
path->r_rmt = mud_read48(packet->rmt); path->r_latmin = mud_read48(packet->latmin);
path->r_max = mud_read48(packet->max);
path->r_max_time = mud_read48(packet->max_time);
path->r_rate = mud_read48(packet->rate); path->r_rate = mud_read48(packet->rate);
path->r_ratemax = mud_read48(packet->ratemax);
const uint64_t ratemax = mud_read48(packet->ratemax); if (path->mtu.ok < path->r_max)
path->mtu.ok = path->r_max;
path->ratevar = ((path->ratevar << 1) + path->ratevar +
mud_abs_diff(path->r_ratemax, ratemax)) >> 2;
path->r_ratemax = ratemax;
if (path->mtu.ok < path->r_rms)
path->mtu.ok = path->r_rms;
mud_update_mtu(mud); mud_update_mtu(mud);
path->ok = 1;
} }
int int
@@ -1350,11 +1376,11 @@ mud_recv(struct mud *mud, void *data, size_t size)
path->recv.time = now; path->recv.time = now;
mud->last_recv_time = now; mud->last_recv_time = now;
if (path->recv_max <= packet_size) { if (path->recv.max <= packet_size) {
path->recv_max = packet_size; path->recv.max = packet_size;
path->recv_max_time = send_time; path->recv.max_time = send_time;
if (path->mtu.ok < path->recv_max) { if (path->mtu.ok < path->recv.max) {
path->mtu.ok = path->recv_max; path->mtu.ok = path->recv.max;
mud_update_mtu(mud); mud_update_mtu(mud);
} }
} }
@@ -1362,35 +1388,38 @@ mud_recv(struct mud *mud, void *data, size_t size)
if (MUD_PACKET(send_time)) if (MUD_PACKET(send_time))
mud_packet_recv(mud, path, now, send_time, data, ret); mud_packet_recv(mud, path, now, send_time, data, ret);
if (mud_timeout(now, path->stat_time, MUD_STAT_TIMEOUT)) { if (mud_timeout(now, path->recv.stat_time, MUD_STAT_TIMEOUT)) {
const uint64_t rate = path->recv.bytes; const uint64_t rate = path->recv.bytes;
const uint64_t lat = MUD_TIME_MASK(now - send_time + mud->time_tolerance);
if (path->recv.ratemax < rate) path->lat = MUD_TIME_MASK(now - send_time + mud->time_tolerance);
path->recv.ratemax = rate;
if (path->latmin > lat || !path->latmin) if (path->latmin) {
path->latmin = lat; if (path->latmin > path->lat)
path->latmin = path->lat;
if (path->latmax < lat) if (path->latmax < path->lat)
path->latmax = lat; path->latmax = path->lat;
} else {
path->latmin = path->lat;
path->latmax = path->lat;
}
if (path->recv.ratemax > rate) { if (path->recv.ratemax > rate) {
const uint64_t latmin = path->latmin + (path->latmin >> 3); if (path->latmin < path->lat) {
const uint64_t latmax = path->latmax; const uint64_t a = path->lat - path->latmin;
if (latmin < lat) { const uint64_t b = path->latmax - path->lat;
const uint64_t a = lat - latmin; const uint64_t r = path->latmax - path->latmin;
const uint64_t b = latmax - lat;
const uint64_t r = latmax - latmin;
path->recv.ratemax = (a * rate + (b + r) * path->recv.ratemax) / (r << 1); path->recv.ratemax = (a * rate + (b + r) * path->recv.ratemax) / (r << 1);
} }
} else {
path->recv.ratemax = rate;
} }
path->recv.rate = rate; path->recv.rate = rate;
path->recv.bytes = packet_size; path->recv.bytes = packet_size;
mud_packet_send(mud, path, now, send_time, 0); mud_packet_send(mud, path, now, send_time, 0);
path->stat_time = now; path->recv.stat_time = now;
} else { } else {
path->recv.bytes += packet_size; path->recv.bytes += packet_size;
} }
@@ -1405,8 +1434,8 @@ mud_probe_mtu(struct mud *mud, struct mud_path *path, uint64_t now)
(!mud_timeout(now, path->mtu.time, path->rtt))) (!mud_timeout(now, path->mtu.time, path->rtt)))
return; return;
while ((path->mtu.probe != path->r_rms + 1) && while ((path->mtu.probe != path->r_max + 1) &&
(path->r_rms != MUD_PACKET_MAX_SIZE)) { (path->r_max != MUD_PACKET_MAX_SIZE)) {
if (path->mtu.probe > path->mtu.ok) { if (path->mtu.probe > path->mtu.ok) {
path->mtu.probe = (path->mtu.probe + path->mtu.ok) >> 1; path->mtu.probe = (path->mtu.probe + path->mtu.ok) >> 1;
@@ -1426,13 +1455,12 @@ mud_probe_mtu(struct mud *mud, struct mud_path *path, uint64_t now)
static void static void
mud_update(struct mud *mud, uint64_t now) mud_update(struct mud *mud, uint64_t now)
{ {
if (!mud->peer.set) if (mud->peer.set) {
return; mud_keyx_init(mud, now);
mud_keyx_init(mud, now); if (mud_timeout(now, mud->last_recv_time, MUD_KEYX_RESET_TIMEOUT))
mud_keyx_reset(mud);
if (mud_timeout(now, mud->last_recv_time, MUD_KEYX_RESET_TIMEOUT)) }
mud_keyx_reset(mud);
for (unsigned i = 0; i < mud->count; i++) { for (unsigned i = 0; i < mud->count; i++) {
struct mud_path *path = &mud->paths[i]; struct mud_path *path = &mud->paths[i];
@@ -1440,10 +1468,21 @@ mud_update(struct mud *mud, uint64_t now)
if (path->state < MUD_DOWN) if (path->state < MUD_DOWN)
continue; continue;
if (mud->crypto.ready) if (path->send.bytes && path->recv.time &&
mud_packet_send(mud, path, now, 0, 0); mud_timeout(now, path->recv.time, mud->send_timeout))
mud_reset_path(mud, path);
mud_probe_mtu(mud, path, now); if (mud->peer.set) {
if (mud->crypto.ready)
mud_packet_send(mud, path, now, 0, 0);
mud_probe_mtu(mud, path, now);
}
if (mud_timeout(now, path->send.stat_time, MUD_STAT_TIMEOUT)) {
path->send.bytes = 0;
path->send.stat_time = now;
}
} }
} }
@@ -1465,16 +1504,6 @@ mud_send(struct mud *mud, const void *data, size_t size, unsigned tc)
return -1; return -1;
} }
for (unsigned i = 0; i < mud->count; i++) {
struct mud_path *path = &mud->paths[i];
if (path->state <= MUD_DOWN)
continue;
if (!path->r_ratemax)
mud_send_path(mud, path, now, packet, packet_size, tc & 255, 0);
}
unsigned k = tc >> 8; unsigned k = tc >> 8;
if (!k) { if (!k) {

21
mud.h
View File

@@ -27,36 +27,35 @@ struct mud_path {
uint64_t send_time; uint64_t send_time;
int remote; int remote;
} conf; } conf;
uint64_t send_max;
uint64_t send_max_time;
uint64_t recv_max;
uint64_t recv_max_time;
uint64_t rtt; uint64_t rtt;
uint64_t rttvar; uint64_t rttvar;
uint64_t lat;
uint64_t latmin; uint64_t latmin;
uint64_t latmax; uint64_t latmax;
uint64_t rst; uint64_t r_lat;
uint64_t ratevar; uint64_t r_latmin;
uint64_t r_rate; uint64_t r_rate;
uint64_t r_ratemax; uint64_t r_ratemax;
uint64_t r_rst; uint64_t r_max;
uint64_t r_rms; uint64_t r_max_time;
uint64_t r_rmt; uint64_t prob;
uint64_t limit;
uint64_t stat_time;
struct { struct {
size_t ok; size_t ok;
size_t probe; size_t probe;
uint64_t time; uint64_t time;
} mtu; } mtu;
struct { struct {
uint64_t max;
uint64_t max_time;
uint64_t total; uint64_t total;
uint64_t rate; uint64_t rate;
uint64_t ratemax; uint64_t ratemax;
uint64_t bytes; uint64_t bytes;
uint64_t stat_time;
uint64_t time; uint64_t time;
} send, recv; } send, recv;
struct mud_public pub; struct mud_public pub;
unsigned char ok;
}; };
struct mud *mud_create (struct sockaddr *); struct mud *mud_create (struct sockaddr *);