Skip to content

Commit

Permalink
Add stats on userspace joold
Browse files Browse the repository at this point in the history
Will serve stats through an UDP socket. Start joold with a third
argument representing the port number:

	$ joold netsocket.json modsocket.json 45678

Then query using a simple UDP request:

	$ echo "" | nc -u 127.0.0.1 45678
	KERNEL_SENT_PKTS,4
	KERNEL_SENT_BYTES,208
	NET_RCVD_PKTS,0
	NET_RCVD_BYTES,0
	NET_SENT_PKTS,4
	NET_SENT_BYTES,208

- KERNEL_SENT_PKTS: Packets sent to the kernel module.
  (Should match the local instance's JSTAT_JOOLD_PKT_RCVD.)
- KERNEL_SENT_BYTES: Session bytes sent to the kernel module.
  (Should match the local instance's JSTAT_JOOLD_SSS_RCVD multiplied by
  the session size.)
- NET_RCVD_PKTS: Packets received from the network.
  (Should match the remote instance's JSTAT_JOOLD_PKT_SENT.)
- NET_RCVD_BYTES: Session bytes received from the network.
  (Should match the remote instance's JSTAT_JOOLD_SSS_SENT multiplied by
  the session size.)
- NET_SENT_PKTS: Packets sent to the network.
  (Should match the remote joold's NET_RCVD_PKTS.)
- NET_SENT_BYTES: Session bytes sent to the network.
  (Should match the remote joold's NET_RCVD_BYTES.)

Will not start the server if the port is absent.
  • Loading branch information
ydahhrk committed Feb 27, 2024
1 parent c3975f2 commit fcc5ccc
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/usr/joold/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ joold_SOURCES = \
joold.c \
log.c log.h \
modsocket.c modsocket.h \
netsocket.c netsocket.h
netsocket.c netsocket.h \
statsocket.c statsocket.h

joold_CFLAGS = ${WARNINGCFLAGS}
joold_CFLAGS += -I${top_srcdir}/src
Expand Down
4 changes: 4 additions & 0 deletions src/usr/joold/joold.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "common/xlat.h"
#include "usr/joold/modsocket.h"
#include "usr/joold/netsocket.h"
#include "usr/joold/statsocket.h"

static void cancel_thread(pthread_t thread)
{
Expand Down Expand Up @@ -44,6 +45,9 @@ int main(int argc, char **argv)
netsocket_teardown();
goto end;
}
error = statsocket_start(argc, argv);
if (error)
goto clean;

error = pthread_create(&mod2net_thread, NULL, modsocket_listen, NULL);
if (error) {
Expand Down
7 changes: 7 additions & 0 deletions src/usr/joold/modsocket.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "modsocket.h"

#include <errno.h>
#include <stdatomic.h>
#include <string.h>
#include <syslog.h>
#include <netlink/genl/ctrl.h>
Expand All @@ -15,6 +16,9 @@
static struct joolnl_socket jsocket;
static char *iname;

atomic_int modsocket_pkts_sent;
atomic_int modsocket_bytes_sent;

/* Called by the net socket whenever joold receives data from the network. */
void modsocket_send(void *request, size_t request_len)
{
Expand Down Expand Up @@ -82,6 +86,9 @@ static int updated_entries_cb(struct nl_msg *msg, void *arg)
*/
netsocket_send(nla_data(root), nla_len(root));
do_ack();

modsocket_pkts_sent++;
modsocket_bytes_sent += nla_len(root);
return 0;

einval:
Expand Down
14 changes: 13 additions & 1 deletion src/usr/joold/netsocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <errno.h>
#include <netdb.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -48,6 +49,11 @@ static struct addrinfo *addr_candidates;
/** Candidate from @addr_candidates that we managed to bind the socket with. */
static struct addrinfo *bound_address;

atomic_int netsocket_pkts_rcvd;
atomic_int netsocket_bytes_rcvd;
atomic_int netsocket_pkts_sent;
atomic_int netsocket_bytes_sent;

static struct in_addr *get_addr4(struct addrinfo *addr)
{
return &((struct sockaddr_in *)addr->ai_addr)->sin_addr;
Expand Down Expand Up @@ -482,6 +488,9 @@ void *netsocket_listen(void *arg)
continue;
}

netsocket_pkts_rcvd++;
netsocket_bytes_rcvd += bytes;

syslog(LOG_DEBUG, "Received %d bytes from the network.", bytes);
modsocket_send(buffer, bytes);
} while (true);
Expand All @@ -499,6 +508,9 @@ void netsocket_send(void *buffer, size_t size)
bound_address->ai_addrlen);
if (bytes < 0)
pr_perror("Could not send a packet to the network", errno);
else
else {
syslog(LOG_DEBUG, "Sent %d bytes to the network.\n", bytes);
netsocket_pkts_sent++;
netsocket_bytes_sent += bytes;
}
}
136 changes: 136 additions & 0 deletions src/usr/joold/statsocket.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include "usr/joold/statsocket.h"

#include <errno.h>
#include <netdb.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "log.h"

static int create_socket(char const *port, int *fd)
{
int sk;
struct addrinfo hints = { 0 };
struct addrinfo *ais, *ai;
int err;

syslog(LOG_INFO, "Setting up statsocket (port %s)...", port);

hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags |= AI_PASSIVE;

err = getaddrinfo(NULL, port, &hints, &ais);
if (err) {
syslog(LOG_ERR, "getaddrinfo() failed: %s", gai_strerror(err));
return err;
}

for (ai = ais; ai; ai = ai->ai_next) {
syslog(LOG_INFO, "Trying an address candidate...");

sk = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sk < 0) {
pr_perror("socket() failed", errno);
continue;
}

if (bind(sk, ai->ai_addr, ai->ai_addrlen)) {
pr_perror("bind() failed", errno);
close(sk);
continue;
}

syslog(LOG_INFO, "Statsocket created successfully.");
freeaddrinfo(ais);
*fd = sk;
return 0;
}

syslog(LOG_ERR, "None of the candidates yielded a valid statsocket.");
freeaddrinfo(ais);
return 1;
}

extern atomic_int modsocket_pkts_sent;
extern atomic_int modsocket_bytes_sent;
extern atomic_int netsocket_pkts_rcvd;
extern atomic_int netsocket_bytes_rcvd;
extern atomic_int netsocket_pkts_sent;
extern atomic_int netsocket_bytes_sent;

#define BUFFER_SIZE 1024

void *serve_stats(void *arg)
{
int sk;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len;
int nread, nstr, nwritten;
char buffer[BUFFER_SIZE];

sk = *((int *)arg);
free(arg);

while (true) {
peer_addr_len = sizeof(peer_addr);
nread = recvfrom(sk, buffer, BUFFER_SIZE, 0,
(struct sockaddr *) &peer_addr,
&peer_addr_len);
if (nread == -1)
continue; /* Ignore failed request */

nstr = snprintf(buffer, BUFFER_SIZE,
"KERNEL_SENT_PKTS,%d\nKERNEL_SENT_BYTES,%d\n"
"NET_RCVD_PKTS,%d\nNET_RCVD_BYTES,%d\n"
"NET_SENT_PKTS,%d\nNET_SENT_BYTES,%d\n",
modsocket_pkts_sent, modsocket_bytes_sent,
netsocket_pkts_rcvd, netsocket_bytes_rcvd,
netsocket_pkts_sent, netsocket_bytes_sent);
if (nstr >= BUFFER_SIZE)
snprintf(buffer, BUFFER_SIZE, "Bug!");

nwritten = sendto(sk, buffer, nstr, 0,
(struct sockaddr *) &peer_addr,
peer_addr_len);
if (nwritten != nstr)
syslog(LOG_ERR, "statsocket error: %s\n", strerror(errno));
}
}

int statsocket_start(int argc, char **argv)
{
int sk, *sk2;
pthread_t thread;
int error;

if (argc < 3) {
syslog(LOG_INFO, "statsocket port unavailable; skipping statsocket.");
return 0;
}

error = create_socket(argv[2], &sk);
if (error)
return error;

sk2 = malloc(sizeof(int));
if (!sk2)
return -ENOMEM;
*sk2 = sk;

error = pthread_create(&thread, NULL, serve_stats, sk2);
if (error) {
free(sk2);
close(sk);
}

return error;
}
6 changes: 6 additions & 0 deletions src/usr/joold/statsocket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef SRC_USR_JOOLD_STATSOCKET_H_
#define SRC_USR_JOOLD_STATSOCKET_H_

int statsocket_start(int argc, char **argv);

#endif /* SRC_USR_JOOLD_STATSOCKET_H_ */

0 comments on commit fcc5ccc

Please sign in to comment.