Probe MTU before sending real packets

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2019-12-21 20:47:46 +00:00
parent 8c033a12a1
commit 569e712248
2 changed files with 70 additions and 72 deletions

132
mud.c
View File

@@ -125,6 +125,7 @@ struct mud_msg {
struct mud_addr addr; struct mud_addr addr;
unsigned char pk[MUD_PUBKEY_SIZE]; unsigned char pk[MUD_PUBKEY_SIZE];
unsigned char aes; unsigned char aes;
unsigned char mtu[MUD_U48_SIZE];
unsigned char fwd_total[MUD_U48_SIZE]; unsigned char fwd_total[MUD_U48_SIZE];
unsigned char fwd_bytes[MUD_U48_SIZE]; unsigned char fwd_bytes[MUD_U48_SIZE];
unsigned char tx_bytes[MUD_U48_SIZE]; unsigned char tx_bytes[MUD_U48_SIZE];
@@ -571,8 +572,8 @@ static void
mud_reset_path(struct mud_path *path) mud_reset_path(struct mud_path *path)
{ {
path->window = 0; path->window = 0;
path->ok = 0; path->mtu.ok = 0;
memset(&path->msg, 0, sizeof(path->msg)); path->mtu.probe = 0;
} }
static void static void
@@ -640,12 +641,6 @@ mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
memcpy(&path->addr, addr, sizeof(*addr)); memcpy(&path->addr, addr, sizeof(*addr));
path->state = MUD_UP; path->state = MUD_UP;
path->mtu.ok = MUD_MTU_MIN;
path->mtu.min = MUD_MTU_MIN;
path->mtu.max = MUD_MTU_MAX;
path->mtu.probe = MUD_MTU_MAX;
path->conf.msg_timeout = MUD_MSG_TIMEOUT; path->conf.msg_timeout = MUD_MSG_TIMEOUT;
return path; return path;
@@ -802,13 +797,10 @@ mud_set_keyx_timeout(struct mud *mud, unsigned long msec)
size_t size_t
mud_get_mtu(struct mud *mud) mud_get_mtu(struct mud *mud)
{ {
return mud->mtu - MUD_PKT_MIN_SIZE; if (!mud->mtu)
} return 0;
void return mud->mtu - MUD_PKT_MIN_SIZE;
mud_set_mtu(struct mud *mud, size_t mtu)
{
mud->mtu = mtu + MUD_PKT_MIN_SIZE;
} }
static int static int
@@ -969,7 +961,6 @@ mud_create(struct sockaddr *addr)
mud->time_tolerance = MUD_TIME_TOLERANCE; mud->time_tolerance = MUD_TIME_TOLERANCE;
mud->keyx_timeout = MUD_KEYX_TIMEOUT; mud->keyx_timeout = MUD_KEYX_TIMEOUT;
mud->tc = MUD_TC; mud->tc = MUD_TC;
mud->mtu = MUD_MTU_MIN;
mud->loss_limit = MUD_LOSS_LIMIT; mud->loss_limit = MUD_LOSS_LIMIT;
memcpy(&mud->addr, addr, addrlen); memcpy(&mud->addr, addr, addrlen);
@@ -1143,6 +1134,9 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
msg->aes = (unsigned char)mud->crypto.aes; msg->aes = (unsigned char)mud->crypto.aes;
if (!path->mtu.probe)
mud_write48(msg->mtu, path->mtu.ok);
mud_write48(msg->tx_bytes, path->tx.bytes); mud_write48(msg->tx_bytes, path->tx.bytes);
mud_write48(msg->rx_bytes, path->rx.bytes); mud_write48(msg->rx_bytes, path->rx.bytes);
mud_write48(msg->tx_total, path->tx.total); mud_write48(msg->tx_total, path->tx.total);
@@ -1153,11 +1147,6 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
msg->loss = (unsigned char)path->tx.loss; msg->loss = (unsigned char)path->tx.loss;
if (!mud->peer.set || !sent_time) {
if (path->msg.sent < MUD_MSG_SENT_MAX)
path->msg.sent++;
}
const struct mud_crypto_opt opt = { const struct mud_crypto_opt opt = {
.dst = dst, .dst = dst,
.src = src, .src = src,
@@ -1166,7 +1155,8 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
mud_encrypt_opt(&mud->crypto.private, &opt); mud_encrypt_opt(&mud->crypto.private, &opt);
return mud_send_path(mud, path, now, dst, size, sent_time ? MSG_CONFIRM : 0); return mud_send_path(mud, path, now, dst, size,
sent_time ? MSG_CONFIRM : 0);
} }
static int static int
@@ -1244,6 +1234,30 @@ mud_update_window(struct mud *mud, struct mud_path *path, uint64_t now,
} }
} }
static void
mud_update_mtu(struct mud_path *path, size_t size)
{
if (!path->mtu.probe)
return;
if (size) {
if (path->mtu.min > size || path->mtu.max < size)
return;
path->mtu.min = size + 1;
path->mtu.ok = size;
} else {
path->mtu.max = path->mtu.probe - 1;
}
size_t probe = (path->mtu.min + path->mtu.max) >> 1;
if (path->mtu.min > path->mtu.max) {
path->mtu.probe = 0;
} else {
path->mtu.probe = probe;
}
}
static void static void
mud_recv_msg(struct mud *mud, struct mud_path *path, mud_recv_msg(struct mud *mud, struct mud_path *path,
uint64_t now, uint64_t sent_time, uint64_t now, uint64_t sent_time,
@@ -1292,22 +1306,11 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
const uint64_t tx_time = mud_read48(msg->sent_time); const uint64_t tx_time = mud_read48(msg->sent_time);
if (tx_time) { if (tx_time) {
path->mtu.min = size + 1;
if (!path->ok) {
path->mtu.max = MUD_MTU_MAX;
path->mtu.probe = MUD_MTU_MAX;
} else {
path->mtu.probe = (path->mtu.min + path->mtu.max) >> 1;
}
path->mtu.ok = size;
const uint64_t rx_time = sent_time;
const uint64_t tx_bytes = mud_read48(msg->fwd_bytes); const uint64_t tx_bytes = mud_read48(msg->fwd_bytes);
const uint64_t rx_bytes = mud_read48(msg->rx_bytes);
const uint64_t tx_total = mud_read48(msg->fwd_total); const uint64_t tx_total = mud_read48(msg->fwd_total);
const uint64_t rx_bytes = mud_read48(msg->rx_bytes);
const uint64_t rx_total = mud_read48(msg->rx_total); const uint64_t rx_total = mud_read48(msg->rx_total);
const uint64_t rx_time = sent_time;
if ((tx_time > path->msg.tx.time) && (tx_bytes > path->msg.tx.bytes) && if ((tx_time > path->msg.tx.time) && (tx_bytes > path->msg.tx.bytes) &&
(rx_time > path->msg.rx.time) && (rx_bytes > path->msg.rx.bytes)) { (rx_time > path->msg.rx.time) && (rx_bytes > path->msg.rx.bytes)) {
@@ -1332,13 +1335,22 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
path->rx.loss = (uint64_t)msg->loss; path->rx.loss = (uint64_t)msg->loss;
path->msg.sent = 0; path->msg.sent = 0;
path->ok = 1;
if (!mud->peer.set) if (mud->peer.set) {
if (!path->mtu.ok && !path->mtu.probe) {
path->mtu.min = MUD_MTU_MIN;
path->mtu.max = MUD_MTU_MAX;
path->mtu.probe = MUD_MTU_MAX;
} else {
mud_update_mtu(path, size);
}
} else {
return; return;
}
} else { } else {
mud_keyx_init(mud, now); mud_keyx_init(mud, now);
path->state = (enum mud_state)msg->state; path->state = (enum mud_state)msg->state;
path->mtu.ok = mud_read48(msg->mtu);
const uint64_t tx_max_rate = mud_read48(msg->tx_max_rate); const uint64_t tx_max_rate = mud_read48(msg->tx_max_rate);
@@ -1346,6 +1358,9 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
path->conf.tx_max_rate = tx_max_rate; path->conf.tx_max_rate = tx_max_rate;
path->tx.rate = tx_max_rate; path->tx.rate = tx_max_rate;
} }
path->msg.sent++;
path->msg.time = now;
} }
mud_send_msg(mud, path, now, sent_time, mud_send_msg(mud, path, now, sent_time,
@@ -1454,39 +1469,25 @@ mud_update(struct mud *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];
if (path->state <= MUD_DOWN) { if ((path->state == MUD_DOWN || !mud->peer.set) &&
if (path->state == MUD_DOWN && (mud_timeout(now, path->rx.time, 10 * MUD_ONE_SEC))) {
mud_timeout(now, path->rx.time, 10 * MUD_ONE_SEC)) mud_remove_path(path);
mud_remove_path(path);
continue; continue;
} }
if (mud->peer.set) { if (path->state <= MUD_DOWN)
if (path->msg.sent >= MUD_MSG_SENT_MAX) { continue;
if (path->mtu.probe == MUD_MTU_MIN) {
mud_reset_path(path); if (path->msg.sent >= MUD_MSG_SENT_MAX) {
} else { if (path->mtu.probe) {
if (path->mtu.ok == path->mtu.probe) { mud_update_mtu(path, 0);
path->mtu.min = MUD_MTU_MIN; } else {
path->mtu.ok = MUD_MTU_MIN; mud_reset_path(path);
mud_reset_path(path);
} else {
path->msg.sent = 0;
}
path->mtu.max = path->mtu.probe - 1;
path->mtu.probe = (path->mtu.min + path->mtu.max) >> 1;
}
}
} else {
if ((path->msg.sent >= MUD_MSG_SENT_MAX) ||
(path->rx.time &&
mud->last_recv_time > path->rx.time + MUD_ONE_SEC)) {
mud_remove_path(path);
continue;
} }
path->msg.sent = 0;
} }
if (path->ok) { if (path->mtu.ok && !path->mtu.probe) {
if (!mtu || mtu > path->mtu.ok) { if (!mtu || mtu > path->mtu.ok) {
mtu = path->mtu.ok; mtu = path->mtu.ok;
} }
@@ -1502,8 +1503,9 @@ mud_update(struct mud *mud)
if (mud->peer.set) { if (mud->peer.set) {
if (mud_timeout(now, path->msg.time, path->conf.msg_timeout)) { if (mud_timeout(now, path->msg.time, path->conf.msg_timeout)) {
mud_send_msg(mud, path, now, 0, 0, 0, path->mtu.probe); path->msg.sent++;
path->msg.time = now; path->msg.time = now;
mud_send_msg(mud, path, now, 0, 0, 0, path->mtu.probe);
} }
} }
@@ -1514,7 +1516,7 @@ mud_update(struct mud *mud)
} }
mud->window = window; mud->window = window;
mud->mtu = mtu ?: MUD_MTU_MIN; mud->mtu = mtu;
return ret; return ret;
} }

10
mud.h
View File

@@ -64,7 +64,6 @@ struct mud_path {
uint64_t window; uint64_t window;
uint64_t window_time; uint64_t window_time;
struct mud_pubkey pk; struct mud_pubkey pk;
unsigned char ok;
}; };
struct mud_bad { struct mud_bad {
@@ -78,16 +77,13 @@ struct mud_bad {
struct mud *mud_create (struct sockaddr *); struct mud *mud_create (struct sockaddr *);
void mud_delete (struct mud *); void mud_delete (struct mud *);
int mud_get_fd (struct mud *); int mud_get_fd (struct mud *);
size_t mud_get_mtu (struct mud *);
int mud_get_bad (struct mud *, struct mud_bad *);
int mud_set_key (struct mud *, unsigned char *, size_t); int mud_set_key (struct mud *, unsigned char *, size_t);
int mud_get_key (struct mud *, unsigned char *, size_t *); int mud_get_key (struct mud *, unsigned char *, size_t *);
void mud_set_mtu (struct mud *, size_t);
size_t mud_get_mtu (struct mud *);
int mud_get_bad (struct mud *, struct mud_bad *);
long mud_send_wait (struct mud *); long mud_send_wait (struct mud *);
int mud_set_time_tolerance (struct mud *, unsigned long); int mud_set_time_tolerance (struct mud *, unsigned long);