Merge MTU probing with failover
This commit also fixes MTU probing in some corner cases. Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
82
mud.c
82
mud.c
@@ -64,7 +64,7 @@
|
|||||||
#define MUD_MSG(X) ((X) & UINT64_C(1))
|
#define MUD_MSG(X) ((X) & UINT64_C(1))
|
||||||
#define MUD_MSG_MARK(X) ((X) | UINT64_C(1))
|
#define MUD_MSG_MARK(X) ((X) | UINT64_C(1))
|
||||||
#define MUD_MSG_TC (192) // CS6
|
#define MUD_MSG_TC (192) // CS6
|
||||||
#define MUD_MSG_SENT_MAX (10)
|
#define MUD_MSG_SENT_MAX (3)
|
||||||
#define MUD_MSG_MIN_RTT (100 * MUD_ONE_MSEC)
|
#define MUD_MSG_MIN_RTT (100 * MUD_ONE_MSEC)
|
||||||
|
|
||||||
#define MUD_PKT_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
#define MUD_PKT_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
||||||
@@ -545,10 +545,6 @@ mud_update_rate(struct mud *mud, struct mud_path *path, uint64_t rate)
|
|||||||
static void
|
static void
|
||||||
mud_reset_path(struct mud *mud, struct mud_path *path)
|
mud_reset_path(struct mud *mud, struct mud_path *path)
|
||||||
{
|
{
|
||||||
path->mtu.ok = MUD_MTU_MIN;
|
|
||||||
path->mtu.min = MUD_MTU_MIN;
|
|
||||||
path->mtu.max = MUD_MTU_MAX;
|
|
||||||
path->mtu.count = 0;
|
|
||||||
path->window = 0;
|
path->window = 0;
|
||||||
path->ok = 0;
|
path->ok = 0;
|
||||||
path->msg_sent = 0;
|
path->msg_sent = 0;
|
||||||
@@ -612,6 +608,12 @@ 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;
|
||||||
|
|
||||||
mud_reset_path(mud, path);
|
mud_reset_path(mud, path);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -1242,10 +1244,14 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
|
|||||||
const uint64_t peer_sent = mud_read48(msg->sent);
|
const uint64_t peer_sent = mud_read48(msg->sent);
|
||||||
|
|
||||||
if (peer_sent) {
|
if (peer_sent) {
|
||||||
if (path->mtu.ok < size) {
|
|
||||||
path->mtu.ok = size;
|
|
||||||
path->mtu.min = size + 1;
|
path->mtu.min = size + 1;
|
||||||
path->mtu.count = 0;
|
path->mtu.ok = size;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
mud_update_stat(&path->rtt, MUD_TIME_MASK(now - peer_sent));
|
mud_update_stat(&path->rtt, MUD_TIME_MASK(now - peer_sent));
|
||||||
@@ -1394,35 +1400,6 @@ mud_path_timeout(struct mud_path *path)
|
|||||||
return rtt > MUD_MSG_MIN_RTT ? rtt : MUD_MSG_MIN_RTT;
|
return rtt > MUD_MSG_MIN_RTT ? rtt : MUD_MSG_MIN_RTT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
mud_probe_mtu(struct mud *mud, struct mud_path *path, uint64_t now)
|
|
||||||
{
|
|
||||||
if (path->mtu.min > path->mtu.max)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (path->mtu.count &&
|
|
||||||
!mud_timeout(now, path->mtu.time, mud_path_timeout(path)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
path->mtu.time = now;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
const size_t probe = (path->mtu.min + path->mtu.max) >> 1;
|
|
||||||
|
|
||||||
if (path->mtu.count == 2) {
|
|
||||||
path->mtu.max = probe - 1;
|
|
||||||
path->mtu.count = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
path->mtu.count++;
|
|
||||||
|
|
||||||
if ((mud_send_msg(mud, path, now, 0, 0, 0, probe) != -1) ||
|
|
||||||
(errno != EMSGSIZE))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mud_update(struct mud *mud, uint64_t now)
|
mud_update(struct mud *mud, uint64_t now)
|
||||||
{
|
{
|
||||||
@@ -1442,19 +1419,34 @@ mud_update(struct mud *mud, uint64_t now)
|
|||||||
if (path->state <= MUD_DOWN)
|
if (path->state <= MUD_DOWN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (path->ok) {
|
if (mud->peer.set) {
|
||||||
if (path->msg_sent >= MUD_MSG_SENT_MAX || (path->recv.time &&
|
if (path->msg_sent >= MUD_MSG_SENT_MAX) {
|
||||||
mud->last_recv_time > path->recv.time + MUD_ONE_SEC)) {
|
if (path->mtu.probe == MUD_MTU_MIN) {
|
||||||
mud_reset_path(mud, path);
|
mud_reset_path(mud, path);
|
||||||
} else {
|
} else {
|
||||||
if (!mtu || mtu > path->mtu.ok)
|
if (path->mtu.ok == path->mtu.probe) {
|
||||||
mtu = path->mtu.ok;
|
path->mtu.min = MUD_MTU_MIN;
|
||||||
|
path->mtu.ok = MUD_MTU_MIN;
|
||||||
|
mud_reset_path(mud, 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->recv.time &&
|
||||||
|
mud->last_recv_time > path->recv.time + MUD_ONE_SEC)) {
|
||||||
|
mud_reset_path(mud, path);
|
||||||
}
|
}
|
||||||
if (mud->peer.set)
|
|
||||||
mud_probe_mtu(mud, path, now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path->ok) {
|
if (path->ok) {
|
||||||
|
if (!mtu || mtu > path->mtu.ok) {
|
||||||
|
mtu = path->mtu.ok;
|
||||||
|
}
|
||||||
if (mud_timeout(now, path->window_time, MUD_WINDOW_TIMEOUT)) {
|
if (mud_timeout(now, path->window_time, MUD_WINDOW_TIMEOUT)) {
|
||||||
path->window = path->window_size;
|
path->window = path->window_size;
|
||||||
path->window_time = now;
|
path->window_time = now;
|
||||||
@@ -1465,7 +1457,7 @@ mud_update(struct mud *mud, uint64_t now)
|
|||||||
|
|
||||||
if (mud->peer.set) {
|
if (mud->peer.set) {
|
||||||
if (mud_timeout(now, path->send.msg_time, mud_path_timeout(path)))
|
if (mud_timeout(now, path->send.msg_time, mud_path_timeout(path)))
|
||||||
mud_send_msg(mud, path, now, 0, 0, 0, 0);
|
mud_send_msg(mud, path, now, 0, 0, 0, path->mtu.probe);
|
||||||
}
|
}
|
||||||
|
|
||||||
window += path->window;
|
window += path->window;
|
||||||
|
|||||||
Reference in New Issue
Block a user