]> git.meshlink.io Git - meshlink/commitdiff
Improved node traffic counters.
authorGuus Sliepen <guus@meshlink.io>
Sun, 8 Aug 2021 20:18:46 +0000 (22:18 +0200)
committerGuus Sliepen <guus@meshlink.io>
Thu, 9 Sep 2021 18:09:07 +0000 (20:09 +0200)
Drop counters for packets, keep byte counters. But distinguish between
application data (channel traffic) and meta-data (including UDP probes).
Also track how much data we forward for other nodes.

The counters can be read by devtool_get_node_status(), and a new function
devtool_reset_node_counters() has been added that will zero the counters.

src/devtools.c
src/devtools.h
src/meshlink.c
src/meshlink.sym
src/meta.c
src/net_packet.c
src/net_socket.c
src/node.h
src/protocol_key.c
src/route.c

index 2a98e595054850a78fecd489058acba6914db846..12c5432e2ca8dbf9ae7ece2accb612fa543c15e6 100644 (file)
@@ -259,49 +259,75 @@ done:
        return result;
 }
 
-void devtool_get_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status) {
-       if(!mesh || !node || !status) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return;
-       }
-
+static void devtool_get_reset_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status, bool reset) {
        node_t *internal = (node_t *)node;
 
        if(pthread_mutex_lock(&mesh->mutex) != 0) {
                abort();
        }
 
-       memcpy(&status->status, &internal->status, sizeof status->status);
-       memcpy(&status->address, &internal->address, sizeof status->address);
-       status->mtu = internal->mtu;
-       status->minmtu = internal->minmtu;
-       status->maxmtu = internal->maxmtu;
-       status->mtuprobes = internal->mtuprobes;
-       status->in_packets = internal->in_packets;
-       status->in_bytes = internal->in_bytes;
-       status->out_packets = internal->out_packets;
-       status->out_bytes = internal->out_bytes;
-
-       // Derive UDP connection status
-       if(internal == mesh->self) {
-               status->udp_status = DEVTOOL_UDP_WORKING;
-       } else if(!internal->status.reachable) {
-               status->udp_status = DEVTOOL_UDP_IMPOSSIBLE;
-       } else if(!internal->status.validkey) {
-               status->udp_status = DEVTOOL_UDP_UNKNOWN;
-       } else if(internal->status.udp_confirmed) {
-               status->udp_status = DEVTOOL_UDP_WORKING;
-       } else if(internal->mtuprobes > 30) {
-               status->udp_status = DEVTOOL_UDP_FAILED;
-       } else if(internal->mtuprobes > 0) {
-               status->udp_status = DEVTOOL_UDP_TRYING;
-       } else {
-               status->udp_status = DEVTOOL_UDP_UNKNOWN;
+       if(status) {
+               memcpy(&status->status, &internal->status, sizeof status->status);
+               memcpy(&status->address, &internal->address, sizeof status->address);
+               status->mtu = internal->mtu;
+               status->minmtu = internal->minmtu;
+               status->maxmtu = internal->maxmtu;
+               status->mtuprobes = internal->mtuprobes;
+               status->in_data = internal->in_data;
+               status->out_data = internal->out_data;
+               status->in_forward = internal->in_forward;
+               status->out_forward = internal->out_forward;
+               status->in_meta = internal->in_meta;
+               status->out_meta = internal->out_meta;
+
+               // Derive UDP connection status
+               if(internal == mesh->self) {
+                       status->udp_status = DEVTOOL_UDP_WORKING;
+               } else if(!internal->status.reachable) {
+                       status->udp_status = DEVTOOL_UDP_IMPOSSIBLE;
+               } else if(!internal->status.validkey) {
+                       status->udp_status = DEVTOOL_UDP_UNKNOWN;
+               } else if(internal->status.udp_confirmed) {
+                       status->udp_status = DEVTOOL_UDP_WORKING;
+               } else if(internal->mtuprobes > 30) {
+                       status->udp_status = DEVTOOL_UDP_FAILED;
+               } else if(internal->mtuprobes > 0) {
+                       status->udp_status = DEVTOOL_UDP_TRYING;
+               } else {
+                       status->udp_status = DEVTOOL_UDP_UNKNOWN;
+               }
+       }
+
+       if(reset) {
+               internal->in_data = 0;
+               internal->out_data = 0;
+               internal->in_forward = 0;
+               internal->out_forward = 0;
+               internal->in_meta = 0;
+               internal->out_meta = 0;
        }
 
        pthread_mutex_unlock(&mesh->mutex);
 }
 
+void devtool_get_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status) {
+       if(!mesh || !node || !status) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return;
+       }
+
+       devtool_get_reset_node_status(mesh, node, status, false);
+}
+
+void devtool_reset_node_counters(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status) {
+       if(!mesh || !node) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return;
+       }
+
+       devtool_get_reset_node_status(mesh, node, status, true);
+}
+
 meshlink_submesh_t **devtool_get_all_submeshes(meshlink_handle_t *mesh, meshlink_submesh_t **submeshes, size_t *nmemb) {
        if(!mesh || !nmemb || (*nmemb && !submeshes)) {
                meshlink_errno = MESHLINK_EINVAL;
index 786e290012e6f28c13f8e60940247413d263cf0b..78e3642859e50301ce84399419735eb579337fe1 100644 (file)
@@ -92,6 +92,7 @@ struct devtool_node_status {
        uint16_t minmtu;
        uint16_t maxmtu;
        int mtuprobes;
+
        enum {
                DEVTOOL_UDP_FAILED = -2,     /// UDP tried but failed
                DEVTOOL_UDP_IMPOSSIBLE = -1, /// UDP not possible (node unreachable)
@@ -99,10 +100,13 @@ struct devtool_node_status {
                DEVTOOL_UDP_TRYING,          /// UDP detection in progress
                DEVTOOL_UDP_WORKING,         /// UDP communication established
        } udp_status;
-       uint64_t in_packets;
-       uint64_t in_bytes;
-       uint64_t out_packets;
-       uint64_t out_bytes;
+
+       uint64_t in_data;                    /// Bytes received from channels
+       uint64_t out_data;                   /// Bytes sent via channels
+       uint64_t in_forward;                 /// Bytes received for channels that need to be forwarded to other nodes
+       uint64_t out_forward;                /// Bytes forwarded from channel from other nodes
+       uint64_t in_meta;                    /// Bytes received from meta-connections, heartbeat packets etc.
+       uint64_t out_meta;                   /// Bytes sent on meta-connections, heartbeat packets etc.
 };
 
 /// Get the status of a node.
@@ -118,6 +122,20 @@ struct devtool_node_status {
  */
 void devtool_get_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status);
 
+/// Reset the traffic counters of a node.
+/** This function resets the byte counters for the given node to zero.
+ *  It also returns the status containing the counters right before they are zeroed.
+ *
+ *  @param mesh         A handle which represents an instance of MeshLink.
+ *  @param node         A pointer to a meshlink_node_t.
+ *  @param status       A pointer to a devtools_node_status_t variable that has
+ *                      to be provided by the caller.
+ *                      The contents of this variable will be changed to reflect
+ *                      the current status of the node before the counters are zeroed.
+ *                      If a NULL pointers is passed, no status will be written.
+ */
+void devtool_reset_node_counters(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status);
+
 /// Get the list of all submeshes of a meshlink instance.
 /** This function returns an array of submesh handles.
  *  These pointers are the same pointers that are present in the submeshes list
index 71263b910696a4e9531672afec7c8252c4223b82..ce3b12c59ae5c10c9d5b9574749ac17dd2551118 100644 (file)
@@ -2270,8 +2270,6 @@ void meshlink_send_from_queue(event_loop_t *loop, void *data) {
 
        for(vpn_packet_t *packet; (packet = meshlink_queue_pop(&mesh->outpacketqueue));) {
                logger(mesh, MESHLINK_DEBUG, "Removing packet of %d bytes from packet queue", packet->len);
-               mesh->self->in_packets++;
-               mesh->self->in_bytes += packet->len;
                route(mesh, mesh->self, packet);
                free(packet);
        }
index f598bcb61b70364de1a493777b1eb3e463b3b8c1..44692bf67da080c6198edb9c0869854eeefce5d6 100644 (file)
@@ -5,6 +5,7 @@ devtool_get_all_submeshes
 devtool_get_node_status
 devtool_keyrotate_probe
 devtool_open_in_netns
+devtool_reset_node_counters
 devtool_set_meta_status_cb
 devtool_set_inviter_commits_first
 devtool_trybind_probe
index a023d2a54131950647df0b56d2065ee0abf443bf..ffd835c46e6bdbf108553aa28e7d7ff0be321daa 100644 (file)
@@ -150,6 +150,10 @@ bool receive_meta(meshlink_handle_t *mesh, connection_t *c) {
 
        logger(mesh, MESHLINK_DEBUG, "Received %d bytes of metadata from %s", inlen, c->name);
 
+       if(c->node) {
+               c->node->in_meta += inlen;
+       }
+
        if(c->allow_request == ID) {
                buffer_add(&c->inbuf, inbuf, inlen);
 
index 67fadfc5a8c6817d740ec5a33aba029ea4417994..4d47f0f3b7cbef9713a8944ec56270e22fd11c6b 100644 (file)
@@ -142,6 +142,7 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) {
 
                logger(mesh, MESHLINK_DEBUG, "Sending MTU probe length %d to %s", len, n->name);
 
+               n->out_meta += packet.len;
                send_udppacket(mesh, n, &packet);
        }
 
@@ -161,6 +162,8 @@ void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) {
 }
 
 static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet, uint16_t len) {
+       n->in_meta += len;
+
        if(len < 64) {
                logger(mesh, MESHLINK_WARNING, "Got too short MTU probe length %d from %s", packet->len, n->name);
                return;
@@ -178,6 +181,8 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet
 
                bool udp_confirmed = n->status.udp_confirmed;
                n->status.udp_confirmed = true;
+               logger(mesh, MESHLINK_DEBUG, "Sending MTU probe reply %d to %s", packet->len, n->name);
+               n->out_meta += packet->len;
                send_udppacket(mesh, n, packet);
                n->status.udp_confirmed = udp_confirmed;
        } else {
@@ -238,9 +243,6 @@ static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *pac
        if(n->status.blacklisted) {
                logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name);
        } else {
-               n->in_packets++;
-               n->in_bytes += packet->len;
-
                route(mesh, n, packet);
        }
 }
@@ -534,8 +536,6 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t
 */
 void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) {
        if(n == mesh->self) {
-               n->out_packets++;
-               n->out_bytes += packet->len;
                // TODO: send to application
                return;
        }
@@ -547,8 +547,6 @@ void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) {
                return;
        }
 
-       n->out_packets++;
-       n->out_bytes += packet->len;
        n->status.want_udp = true;
 
        send_sptps_packet(mesh, n, packet);
index 4989b6cf0578a0471a868cdfc8a1a09a633bdd32..8b1263b063fb8df8c5900e68a09361921ac5e636 100644 (file)
@@ -136,6 +136,10 @@ static void handle_meta_write(meshlink_handle_t *mesh, connection_t *c) {
                return;
        }
 
+       if(c->node) {
+               c->node->out_meta += outlen;
+       }
+
        buffer_read(&c->outbuf, outlen);
 
        if(!c->outbuf.len) {
index f88cde6893141bbabd7cea1061fe9a039a9b1ab2..918f1cce8db0821c064ac9dad125b53d3ef3ae55 100644 (file)
@@ -62,10 +62,12 @@ typedef struct node_t {
        struct utcp *utcp;
 
        // Traffic counters
-       uint64_t in_packets;
-       uint64_t in_bytes;
-       uint64_t out_packets;
-       uint64_t out_bytes;
+       uint64_t in_data;                       /* Bytes received from channels */
+       uint64_t out_data;                      /* Bytes sent via channels */
+       uint64_t in_forward;                    /* Bytes received for channels that need to be forwarded to other nodes */
+       uint64_t out_forward;                   /* Bytes forwarded from channel from other nodes */
+       uint64_t in_meta;                       /* Bytes received from meta-connections, heartbeat packets etc. */
+       uint64_t out_meta;                      /* Bytes sent on meta-connections, heartbeat packets etc. */
 
        // MTU probes
        timeout_t mtutimeout;                   /* Probe event */
index 25dbc55e5c04b7533e9eb0f6c5eeb62214cc648e..768b6371e4a03338cc98f93b06595d4fe3726da9 100644 (file)
@@ -345,6 +345,10 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                        return true;
                }
 
+               size_t len = strlen(request);
+               from->in_forward += len;
+               to->out_forward += len;
+
                send_request(mesh, to->nexthop->connection, NULL, "%s", request);
        }
 
@@ -411,6 +415,11 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                        return false;
                }
 
+               /* TODO: find a good way to avoid the use of strlen() */
+               size_t len = strlen(request);
+               from->in_forward += len;
+               to->out_forward += len;
+
                /* Append the known UDP address of the from node, if we have a confirmed one */
                if(!*address && from->status.udp_confirmed && from->address.sa.sa_family != AF_UNSPEC) {
                        char *reflexive_address, *reflexive_port;
index ea3a54340c8c9dbd1099ff0e066a810344308186..25256de36196054af238f64ff395d761f7e3a891 100644 (file)
@@ -57,9 +57,16 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) {
                return;
        }
 
+       size_t len = packet->len - sizeof(*hdr);
+
+       // Channel traffic accounting
+       if(source == mesh->self) {
+               dest->out_data += len;
+       }
+
        if(dest == mesh->self) {
+               source->in_data += len;
                const void *payload = packet->data + sizeof(*hdr);
-               size_t len = packet->len - sizeof(*hdr);
 
                char hex[len * 2 + 1];