From ba9bef62682f02f7414f8d6f4ccc96fd988beeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Gallou=C3=ABt?= Date: Mon, 23 Apr 2018 20:52:31 +0000 Subject: [PATCH] Add a new rate based scheduler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Adrien Gallouët --- README.md | 8 +---- mud.c | 93 +++++++++++++++++++++++++++++++------------------------ mud.h | 2 +- 3 files changed, 54 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index eff87a3..06f55b2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # MUD -MUD is a secure, connectionless network protocol over UDP. -It enables the distribution of packets on multiple paths while maintaining a low latency (the bandwidth is sacrificed in favor of latency). +MUD is a secure, multipath network protocol over UDP. ### Compatibility @@ -13,11 +12,6 @@ MUD uses [libsodium](https://github.com/jedisct1/libsodium) for all cryptographi Encryption (and authentication) is done with AES256-GCM when aesni is available otherwise ChaCha20-Poly1305 is used. The Diffie-Hellman function X25519 is used for key exchange. -### Performance - -The scheduler is still in development but you will find some measurements to give you an idea of the performance [here](https://github.com/angt/mud/wiki/Perf). - - ### Issues For feature requests and bug reports, please create an [issue](https://github.com/angt/mud/issues). diff --git a/mud.c b/mud.c index 6ee3aa7..29e106b 100644 --- a/mud.c +++ b/mud.c @@ -187,6 +187,8 @@ struct mud { struct { unsigned char kiss[MUD_KISS_SIZE]; } remote, local; + unsigned char map[1024]; + unsigned long long ratemax; }; static int @@ -611,6 +613,37 @@ mud_update_mtu(struct mud *mud) mud->mtu = count ? mtu : MUD_MTU; } +static int +mud_update_map(struct mud *mud) +{ + unsigned long long n = 0; + + for (unsigned i = 0; i < mud->count; i++) { + struct mud_path *path = &mud->paths[i]; + + if (path->state <= MUD_DOWN) + continue; + + n += mud->paths[i].r_ratemax; + } + + mud->ratemax = n; + + if (!n) + return 0; + + unsigned w = 0; + + for (unsigned i = 0; i < mud->count; i++) { + if (w < sizeof(mud->map)) + memset(&mud->map[w], i, sizeof(mud->map) - w); + + w += ((mud->paths[i].r_ratemax << 10) + (n >> 1)) / n; + } + + return 0; +} + int mud_get_key(struct mud *mud, unsigned char *key, size_t *size) { @@ -726,6 +759,7 @@ mud_set_state(struct mud *mud, struct sockaddr *addr, enum mud_state state) path->state = state; mud_update_mtu(mud); + mud_update_map(mud); return 0; } @@ -1269,6 +1303,7 @@ mud_packet_recv(struct mud *mud, struct mud_path *path, } mud_update_mtu(mud); + mud_update_map(mud); } int @@ -1438,7 +1473,7 @@ mud_update(struct mud *mud, uint64_t now) } int -mud_send(struct mud *mud, const void *data, size_t size, int tc) +mud_send(struct mud *mud, const void *data, size_t size, unsigned tc) { unsigned char packet[MUD_PACKET_MAX_SIZE]; const uint64_t now = mud_now(); @@ -1453,61 +1488,37 @@ mud_send(struct mud *mud, const void *data, size_t size, int tc) return -1; } - int packet_size = mud_encrypt(mud, now, packet, sizeof(packet), data, size); + const int packet_size = mud_encrypt(mud, now, packet, sizeof(packet), data, size); if (!packet_size) { errno = EINVAL; return -1; } - struct mud_path *path_min = NULL; - struct mud_path *path_backup = NULL; - - int64_t limit_min = INT64_MAX; - for (unsigned i = 0; i < mud->count; i++) { struct mud_path *path = &mud->paths[i]; - if (path->state <= MUD_DOWN) { - if (path->state == MUD_BACKUP) - path_backup = path; + if (path->state < MUD_DOWN) continue; - } - int64_t limit = path->limit; - uint64_t elapsed = MUD_TIME_MASK(now - path->send.time); - - if (limit > elapsed) { - limit += path->rtt / 2 - elapsed; - } else { - limit = path->rtt / 2; - } - - if (mud_timeout(now, path->recv.time, mud->send_timeout + MUD_ONE_SEC)) { - if (mud_timeout(now, path->send.time, mud->send_timeout)) { - mud_send_path(mud, path, now, packet, packet_size, tc, 0); - path->limit = limit; - } - continue; - } - - if (limit_min > limit) { - limit_min = limit; - path_min = path; - } + if (!path->r_ratemax) + mud_send_path(mud, path, now, packet, packet_size, tc & 255, 0); } - if (!path_min) { - if (!path_backup) - return 0; + if (!mud->ratemax) + return 0; - path_min = path_backup; + unsigned k = tc >> 8; + + if (!k) { + const unsigned a = packet[packet_size - 1]; + const unsigned b = packet[packet_size - 2]; + k = (a << 8) | b; + } else { + k--; } - ssize_t ret = mud_send_path(mud, path_min, now, packet, packet_size, tc, 0); + struct mud_path *path = &mud->paths[mud->map[k % sizeof(mud->map)]]; - if (ret == packet_size) - path_min->limit = limit_min; - - return (int)ret; + return mud_send_path(mud, path, now, packet, packet_size, tc & 255, 0); } diff --git a/mud.h b/mud.h index 1b55045..250f7b6 100644 --- a/mud.h +++ b/mud.h @@ -75,6 +75,6 @@ int mud_set_state (struct mud *, struct sockaddr *, enum mud_state); int mud_peer (struct mud *, struct sockaddr *); int mud_recv (struct mud *, void *, size_t); -int mud_send (struct mud *, const void *, size_t, int); +int mud_send (struct mud *, const void *, size_t, unsigned); struct mud_path *mud_get_paths(struct mud *, unsigned *);