From 8cbd423d5425bd13232de9c69a84a9b4b1ff3b88 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 8 Aug 2021 22:18:46 +0200 Subject: [PATCH] Improved node traffic counters. 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 | 90 +++++++++++++++++++++++++++++----------------- src/devtools.h | 26 +++++++++++--- src/meshlink.c | 2 -- src/meshlink.sym | 1 + src/meta.c | 4 +++ src/net_packet.c | 12 +++---- src/net_socket.c | 4 +++ src/node.h | 10 +++--- src/protocol_key.c | 9 +++++ src/route.c | 9 ++++- 10 files changed, 117 insertions(+), 50 deletions(-) diff --git a/src/devtools.c b/src/devtools.c index 2a98e595..12c5432e 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -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; diff --git a/src/devtools.h b/src/devtools.h index 786e2900..78e36428 100644 --- a/src/devtools.h +++ b/src/devtools.h @@ -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 diff --git a/src/meshlink.c b/src/meshlink.c index 71263b91..ce3b12c5 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -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); } diff --git a/src/meshlink.sym b/src/meshlink.sym index f598bcb6..44692bf6 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -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 diff --git a/src/meta.c b/src/meta.c index a023d2a5..ffd835c4 100644 --- a/src/meta.c +++ b/src/meta.c @@ -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); diff --git a/src/net_packet.c b/src/net_packet.c index 67fadfc5..4d47f0f3 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -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); diff --git a/src/net_socket.c b/src/net_socket.c index 4989b6cf..8b1263b0 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -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) { diff --git a/src/node.h b/src/node.h index f88cde68..918f1cce 100644 --- a/src/node.h +++ b/src/node.h @@ -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 */ diff --git a/src/protocol_key.c b/src/protocol_key.c index 25dbc55e..768b6371 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -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; diff --git a/src/route.c b/src/route.c index ea3a5434..25256de3 100644 --- a/src/route.c +++ b/src/route.c @@ -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]; -- 2.39.5