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

124
mud.c
View File

@@ -125,6 +125,7 @@ struct mud_msg {
struct mud_addr addr;
unsigned char pk[MUD_PUBKEY_SIZE];
unsigned char aes;
unsigned char mtu[MUD_U48_SIZE];
unsigned char fwd_total[MUD_U48_SIZE];
unsigned char fwd_bytes[MUD_U48_SIZE];
unsigned char tx_bytes[MUD_U48_SIZE];
@@ -571,8 +572,8 @@ static void
mud_reset_path(struct mud_path *path)
{
path->window = 0;
path->ok = 0;
memset(&path->msg, 0, sizeof(path->msg));
path->mtu.ok = 0;
path->mtu.probe = 0;
}
static void
@@ -640,12 +641,6 @@ mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
memcpy(&path->addr, addr, sizeof(*addr));
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;
return path;
@@ -802,13 +797,10 @@ mud_set_keyx_timeout(struct mud *mud, unsigned long msec)
size_t
mud_get_mtu(struct mud *mud)
{
return mud->mtu - MUD_PKT_MIN_SIZE;
}
if (!mud->mtu)
return 0;
void
mud_set_mtu(struct mud *mud, size_t mtu)
{
mud->mtu = mtu + MUD_PKT_MIN_SIZE;
return mud->mtu - MUD_PKT_MIN_SIZE;
}
static int
@@ -969,7 +961,6 @@ mud_create(struct sockaddr *addr)
mud->time_tolerance = MUD_TIME_TOLERANCE;
mud->keyx_timeout = MUD_KEYX_TIMEOUT;
mud->tc = MUD_TC;
mud->mtu = MUD_MTU_MIN;
mud->loss_limit = MUD_LOSS_LIMIT;
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;
if (!path->mtu.probe)
mud_write48(msg->mtu, path->mtu.ok);
mud_write48(msg->tx_bytes, path->tx.bytes);
mud_write48(msg->rx_bytes, path->rx.bytes);
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;
if (!mud->peer.set || !sent_time) {
if (path->msg.sent < MUD_MSG_SENT_MAX)
path->msg.sent++;
}
const struct mud_crypto_opt opt = {
.dst = dst,
.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);
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
@@ -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
mud_recv_msg(struct mud *mud, struct mud_path *path,
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);
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 rx_bytes = mud_read48(msg->rx_bytes);
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_time = sent_time;
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)) {
@@ -1332,13 +1335,22 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
path->rx.loss = (uint64_t)msg->loss;
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;
}
} else {
mud_keyx_init(mud, now);
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);
@@ -1346,6 +1358,9 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
path->conf.tx_max_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,
@@ -1454,39 +1469,25 @@ mud_update(struct mud *mud)
for (unsigned i = 0; i < mud->count; i++) {
struct mud_path *path = &mud->paths[i];
if (path->state <= MUD_DOWN) {
if (path->state == MUD_DOWN &&
mud_timeout(now, path->rx.time, 10 * MUD_ONE_SEC))
if ((path->state == MUD_DOWN || !mud->peer.set) &&
(mud_timeout(now, path->rx.time, 10 * MUD_ONE_SEC))) {
mud_remove_path(path);
continue;
}
if (mud->peer.set) {
if (path->state <= MUD_DOWN)
continue;
if (path->msg.sent >= MUD_MSG_SENT_MAX) {
if (path->mtu.probe == MUD_MTU_MIN) {
mud_reset_path(path);
if (path->mtu.probe) {
mud_update_mtu(path, 0);
} else {
if (path->mtu.ok == path->mtu.probe) {
path->mtu.min = MUD_MTU_MIN;
path->mtu.ok = MUD_MTU_MIN;
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;
}
}
if (path->ok) {
if (path->mtu.ok && !path->mtu.probe) {
if (!mtu || mtu > path->mtu.ok) {
mtu = path->mtu.ok;
}
@@ -1502,8 +1503,9 @@ mud_update(struct mud *mud)
if (mud->peer.set) {
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;
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->mtu = mtu ?: MUD_MTU_MIN;
mud->mtu = mtu;
return ret;
}

8
mud.h
View File

@@ -64,7 +64,6 @@ struct mud_path {
uint64_t window;
uint64_t window_time;
struct mud_pubkey pk;
unsigned char ok;
};
struct mud_bad {
@@ -79,15 +78,12 @@ struct mud *mud_create (struct sockaddr *);
void mud_delete (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_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 *);
int mud_set_time_tolerance (struct mud *, unsigned long);