]> git.meshlink.io Git - meshlink/commitdiff
Propagate the discovered PMTU between nodes to UTCP.
authorGuus Sliepen <guus@meshlink.io>
Sun, 29 Mar 2020 17:33:18 +0000 (19:33 +0200)
committerGuus Sliepen <guus@meshlink.io>
Sun, 29 Mar 2020 21:37:52 +0000 (23:37 +0200)
src/meshlink++.h
src/meshlink.c
src/meshlink.h
src/net.h
src/net_packet.c

index 8493c1ed71c70d3b1c4f71d5a795b96fa61dc2d9..93020661b922b21b1c1b43dbc2e7dd105f65138d 100644 (file)
@@ -993,6 +993,17 @@ public:
                return meshlink_channel_get_recvq(handle, channel);
        }
 
+       /// Get the maximum segment size of a channel.
+       /** This returns the amount of bytes that can be sent at once for channels with UDP semantics.
+        *
+        *  @param channel      A handle for the channel.
+        *
+        *  @return             The amount of bytes in the receive buffer.
+        */
+       size_t channel_get_mss(channel *channel) {
+               return meshlink_channel_get_mss(handle, channel);
+       };
+
        /// Enable or disable zeroconf discovery of local peers
        /** This controls whether zeroconf discovery using the Catta library will be
         *  enabled to search for peers on the local network. By default, it is enabled.
index 747bd3b5071a406310b4e4e7e8c7d8a463fcd736..38ef57508b7e13540644bdababfc27f2d1042602 100644 (file)
@@ -3672,6 +3672,7 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac
        for splay_each(node_t, n, mesh->nodes) {
                if(!n->utcp && n != mesh->self) {
                        n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+                       utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
                }
        }
 
@@ -3720,6 +3721,7 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
 
        if(!n->utcp) {
                n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+               utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
                mesh->receive_cb = channel_receive;
 
                if(!n->utcp) {
@@ -4007,6 +4009,15 @@ size_t meshlink_channel_get_recvq(meshlink_handle_t *mesh, meshlink_channel_t *c
        return utcp_get_recvq(channel->c);
 }
 
+size_t meshlink_channel_get_mss(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
+       if(!mesh || !channel) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return -1;
+       }
+
+       return utcp_get_mss(channel->node->utcp);
+}
+
 void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t *node, int timeout) {
        if(!mesh || !node) {
                meshlink_errno = MESHLINK_EINVAL;
@@ -4019,6 +4030,7 @@ void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t
 
        if(!n->utcp) {
                n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+               utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
        }
 
        utcp_set_user_timeout(n->utcp, timeout);
@@ -4029,6 +4041,7 @@ void meshlink_set_node_channel_timeout(meshlink_handle_t *mesh, meshlink_node_t
 void update_node_status(meshlink_handle_t *mesh, node_t *n) {
        if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) {
                n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
+               utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
        }
 
        if(mesh->node_status_cb) {
@@ -4041,6 +4054,8 @@ void update_node_status(meshlink_handle_t *mesh, node_t *n) {
 }
 
 void update_node_pmtu(meshlink_handle_t *mesh, node_t *n) {
+       utcp_set_mtu(n->utcp, (n->minmtu > MINMTU ? n->minmtu : MINMTU) - sizeof(meshlink_packethdr_t));
+
        if(mesh->node_pmtu_cb && !n->status.blacklisted) {
                mesh->node_pmtu_cb(mesh, (meshlink_node_t *)n, n->minmtu);
        }
index 13976266652296e67477447ff1dfb1e483a1dc1d..5390c4e8645c9e30ce0db49162f0b9e016f5850e 100644 (file)
@@ -1504,6 +1504,17 @@ extern size_t meshlink_channel_get_sendq(struct meshlink_handle *mesh, struct me
  */
 extern size_t meshlink_channel_get_recvq(struct meshlink_handle *mesh, struct meshlink_channel *channel) __attribute__((__warn_unused_result__));
 
+/// Get the maximum segment size of a channel.
+/** This returns the amount of bytes that can be sent at once for channels with UDP semantics.
+ *
+ *  \memberof meshlink_channel
+ *  @param mesh         A handle which represents an instance of MeshLink.
+ *  @param channel      A handle for the channel.
+ *
+ *  @return             The amount of bytes in the receive buffer.
+ */
+extern size_t meshlink_channel_get_mss(struct meshlink_handle *mesh, struct meshlink_channel *channel) __attribute__((__warn_unused_result__));
+
 /// Set the connection timeout used for channels to the given node.
 /** This sets the timeout after which unresponsive channels will be reported as closed.
  *  The timeout is set for all current and future channels to the given node.
index cae63bf12a33795bf763d72fbf3a33e32df676ea..38727c28c31f8647930e268862898cf5eb38a62c 100644 (file)
--- a/src/net.h
+++ b/src/net.h
 #include "event.h"
 #include "sockaddr.h"
 
+/* Maximum size of SPTPS payload */
 #ifdef ENABLE_JUMBOGRAMS
-#define MTU 9018        /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
+#define MTU 8951        /* 9000 bytes payload - 28 bytes IP+UDP header - 21 bytes SPTPS header+MAC */
 #else
-#define MTU 1518        /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
+#define MTU 1451        /* 1500 bytes payload - 28 bytes IP+UDP - 21 bytes SPTPS header+MAC */
 #endif
 
-/* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + HMAC + compressor overhead */
-#define MAXSIZE (MTU + 4 + 32 + MTU/64 + 20)
+#define MINMTU 527      /* 576 minimum recommended Internet MTU - 28 bytes IP+UDP - 21 bytes SPTPS header+MAC */
 
-/* MAXBUFSIZE is the maximum size of a request: enough for a MAXSIZEd packet or a 8192 bits RSA key */
-#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128)
+/* MAXSIZE is the maximum size of an encapsulated packet */
+#define MAXSIZE (MTU + 64)
+
+/* MAXBUFSIZE is the maximum size of a request: enough for a base64 encoded MAXSIZEd packet plus request header */
+#define MAXBUFSIZE ((MAXSIZE * 8) / 6 + 128)
 
 typedef struct vpn_packet_t {
        uint16_t probe: 1;
index 7dae0fe0a558c3ac5eed8920de4f00ef290e2f14..8aca6aa59adda1ef8f78d9eecec914625a9a367a 100644 (file)
@@ -370,7 +370,7 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
 
        /* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */
 
-       if(type >= SPTPS_HANDSHAKE || (type != PKT_PROBE && len > to->minmtu)) {
+       if(type >= SPTPS_HANDSHAKE || (type != PKT_PROBE && (len - 21) > to->minmtu)) {
                char buf[len * 4 / 3 + 5];
                b64encode(data, buf, len);
 
@@ -433,8 +433,8 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t
                return true;
        }
 
-       if(len > MTU) {
-               logger(mesh, MESHLINK_ERROR, "Packet from %s larger than maximum supported size (%d > %d)", from->name, len, MTU);
+       if(len > MAXSIZE) {
+               logger(mesh, MESHLINK_ERROR, "Packet from %s larger than maximum supported size (%d > %d)", from->name, len, MAXSIZE);
                return false;
        }