Simplify MTU setup and allow big packets
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
116
mud.c
116
mud.c
@@ -45,12 +45,12 @@
|
|||||||
#define MUD_PKTINFO_SIZE sizeof(struct in_addr)
|
#define MUD_PKTINFO_SIZE sizeof(struct in_addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined IP_DONTFRAG
|
#if defined IP_MTU_DISCOVER
|
||||||
|
#define MUD_DFRAG IP_MTU_DISCOVER
|
||||||
|
#define MUD_DFRAG_OPT IP_PMTUDISC_PROBE
|
||||||
|
#elif defined IP_DONTFRAG
|
||||||
#define MUD_DFRAG IP_DONTFRAG
|
#define MUD_DFRAG IP_DONTFRAG
|
||||||
#define MUD_DFRAG_OPT 1
|
#define MUD_DFRAG_OPT 1
|
||||||
#elif defined IP_MTU_DISCOVER
|
|
||||||
#define MUD_DFRAG IP_MTU_DISCOVER
|
|
||||||
#define MUD_DFRAG_OPT IP_PMTUDISC_DO
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MUD_ONE_MSEC (UINT64_C(1000))
|
#define MUD_ONE_MSEC (UINT64_C(1000))
|
||||||
@@ -68,13 +68,15 @@
|
|||||||
#define MUD_PACKET_MARK(X) ((X) | UINT64_C(1))
|
#define MUD_PACKET_MARK(X) ((X) | UINT64_C(1))
|
||||||
|
|
||||||
#define MUD_PACKET_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
#define MUD_PACKET_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
||||||
#define MUD_PACKET_MAX_SIZE (1472U)
|
#define MUD_PACKET_MAX_SIZE (9000U)
|
||||||
|
|
||||||
#define MUD_PACKET_TC (192) // CS6
|
#define MUD_PACKET_TC (192) // CS6
|
||||||
|
|
||||||
#define MUD_PACKET_SIZE(X) \
|
#define MUD_PACKET_SIZE(X) \
|
||||||
(sizeof(((struct mud_packet *)0)->hdr) + (X) + MUD_MAC_SIZE)
|
(sizeof(((struct mud_packet *)0)->hdr) + (X) + MUD_MAC_SIZE)
|
||||||
|
|
||||||
|
#define MUD_MTU (1280U + MUD_PACKET_MIN_SIZE)
|
||||||
|
|
||||||
#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_SEND_TIMEOUT (MUD_ONE_SEC)
|
#define MUD_SEND_TIMEOUT (MUD_ONE_SEC)
|
||||||
@@ -520,7 +522,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->mtu.ok = mud->mtu;
|
path->mtu.ok = MUD_MTU;
|
||||||
path->mtu.probe = mud->mtu;
|
path->mtu.probe = mud->mtu;
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -562,6 +564,27 @@ mud_peer(struct mud *mud, struct sockaddr *peer)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mud_update_mtu(struct mud *mud)
|
||||||
|
{
|
||||||
|
size_t mtu = MUD_PACKET_MAX_SIZE;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
|
if (path->state <= MUD_DOWN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (mtu > path->mtu.ok)
|
||||||
|
mtu = path->mtu.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
mud->mtu = count ? mtu : MUD_MTU;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
mud_get_key(struct mud *mud, unsigned char *key, size_t *size)
|
mud_get_key(struct mud *mud, unsigned char *key, size_t *size)
|
||||||
{
|
{
|
||||||
@@ -697,6 +720,7 @@ mud_set_state(struct mud *mud, struct sockaddr *addr, enum mud_state state)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
path->state = state;
|
path->state = state;
|
||||||
|
mud_update_mtu(mud);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -704,55 +728,13 @@ mud_set_state(struct mud *mud, struct sockaddr *addr, enum mud_state state)
|
|||||||
size_t
|
size_t
|
||||||
mud_get_mtu(struct mud *mud)
|
mud_get_mtu(struct mud *mud)
|
||||||
{
|
{
|
||||||
size_t mtu = MUD_PACKET_MAX_SIZE;
|
return mud->mtu - MUD_PACKET_MIN_SIZE;
|
||||||
unsigned count = 0;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < mud->count; i++) {
|
|
||||||
struct mud_path *path = &mud->paths[i];
|
|
||||||
|
|
||||||
if (path->state <= MUD_DOWN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (mtu > path->mtu.ok)
|
|
||||||
mtu = path->mtu.ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count)
|
|
||||||
mtu = mud->mtu;
|
|
||||||
|
|
||||||
if (mtu > MUD_PACKET_MAX_SIZE)
|
|
||||||
mtu = MUD_PACKET_MAX_SIZE;
|
|
||||||
|
|
||||||
if (mtu < sizeof(struct mud_packet))
|
|
||||||
mtu = sizeof(struct mud_packet);
|
|
||||||
|
|
||||||
return mtu - MUD_PACKET_MIN_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mud_set_mtu(struct mud *mud, size_t mtu)
|
mud_set_mtu(struct mud *mud, size_t mtu)
|
||||||
{
|
{
|
||||||
if (mtu > MUD_PACKET_MAX_SIZE + 28U) {
|
mud->mtu = mtu + MUD_PACKET_MIN_SIZE;
|
||||||
mtu = MUD_PACKET_MAX_SIZE;
|
|
||||||
} else if (mtu < sizeof(struct mud_packet) + 28U) {
|
|
||||||
mtu = sizeof(struct mud_packet);
|
|
||||||
} else {
|
|
||||||
mtu -= 28U;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < mud->count; i++) {
|
|
||||||
struct mud_path *path = &mud->paths[i];
|
|
||||||
|
|
||||||
if (path->state == MUD_EMPTY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
path->mtu.ok = mtu;
|
|
||||||
path->mtu.probe = mtu;
|
|
||||||
}
|
|
||||||
|
|
||||||
mud->mtu = mtu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -912,7 +894,7 @@ 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_PACKET_TC;
|
mud->tc = MUD_PACKET_TC;
|
||||||
mud->mtu = sizeof(struct mud_packet);
|
mud->mtu = MUD_MTU;
|
||||||
|
|
||||||
memcpy(&mud->addr, addr, addrlen);
|
memcpy(&mud->addr, addr, addrlen);
|
||||||
|
|
||||||
@@ -1055,7 +1037,7 @@ mud_localaddr(struct sockaddr_storage *addr, struct msghdr *msg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
||||||
struct mud_path *path, uint64_t now, int flags)
|
struct mud_path *path, uint64_t now, int flags)
|
||||||
{
|
{
|
||||||
@@ -1079,7 +1061,8 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
memcpy(packet->hdr.addr.port,
|
memcpy(packet->hdr.addr.port,
|
||||||
&((struct sockaddr_in6 *)&path->addr)->sin6_port, 2);
|
&((struct sockaddr_in6 *)&path->addr)->sin6_port, 2);
|
||||||
} else {
|
} else {
|
||||||
return;
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->hdr.state = (unsigned char)path->state;
|
packet->hdr.state = (unsigned char)path->state;
|
||||||
@@ -1116,7 +1099,10 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
};
|
};
|
||||||
|
|
||||||
mud_encrypt_opt(&mud->crypto.private, &opt);
|
mud_encrypt_opt(&mud->crypto.private, &opt);
|
||||||
mud_send_path(mud, path, now, packet, MUD_PACKET_SIZE(size), mud->tc, flags);
|
|
||||||
|
return mud_send_path(mud, path, now,
|
||||||
|
packet, MUD_PACKET_SIZE(size),
|
||||||
|
mud->tc, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1242,6 +1228,8 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mud_update_mtu(mud);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -1317,8 +1305,10 @@ mud_recv(struct mud *mud, void *data, size_t size)
|
|||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MUD_PACKET(send_time)) {
|
if (MUD_PACKET(send_time)) {
|
||||||
@@ -1335,19 +1325,25 @@ static void
|
|||||||
mud_probe_mtu(struct mud *mud, struct mud_path *path, uint64_t now)
|
mud_probe_mtu(struct mud *mud, struct mud_path *path, uint64_t now)
|
||||||
{
|
{
|
||||||
if ((!path->rtt) ||
|
if ((!path->rtt) ||
|
||||||
(!mud_timeout(now, path->mtu.time, path->rtt)) ||
|
(!mud_timeout(now, path->mtu.time, path->rtt)))
|
||||||
(path->mtu.probe == path->r_rms + 1) ||
|
|
||||||
(path->r_rms == MUD_PACKET_MAX_SIZE))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
while ((path->mtu.probe != path->r_rms + 1) &&
|
||||||
|
(path->r_rms != 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;
|
||||||
} else {
|
} else {
|
||||||
path->mtu.probe = (MUD_PACKET_MAX_SIZE + path->mtu.ok + 1) >> 1;
|
path->mtu.probe = (MUD_PACKET_MAX_SIZE + path->mtu.ok + 1) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mud_packet_send(mud, mud_fake, path, now, 0);
|
|
||||||
path->mtu.time = now;
|
path->mtu.time = now;
|
||||||
|
|
||||||
|
if ((path->mtu.probe == MUD_MTU) ||
|
||||||
|
(mud_packet_send(mud, mud_fake, path, now, 0) != -1) ||
|
||||||
|
(errno != EMSGSIZE))
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1394,7 +1390,7 @@ mud_send(struct mud *mud, const void *data, size_t size, int tc)
|
|||||||
if (!size)
|
if (!size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size > mud_get_mtu(mud)) {
|
if (size > sizeof(packet) - MUD_PACKET_MIN_SIZE) {
|
||||||
errno = EMSGSIZE;
|
errno = EMSGSIZE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user