mirror of
https://github.com/OpenSolo/OpenSolo.git
synced 2025-04-30 14:44:31 +02:00
142 lines
4.9 KiB
C
142 lines
4.9 KiB
C
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "net_stats.h"
|
|
|
|
/* The udp rx queue size is reported in multiples of some kernel-internal
|
|
* buffer. We want the number of packets queued, which is presumably the
|
|
* number of buffers. However, if we ever see a rx queue value that is not
|
|
* a multiple of this, start reporting the raw number. */
|
|
#define UDP_RX_QUEUE_BUFSIZE 2496
|
|
int udp_rx_queue_bufsize_correct = 1; /* assume correct */
|
|
|
|
/*
|
|
* udp_info_get - get info about a udp port
|
|
*
|
|
* Read /proc/net/udp and fill in udp_info with status of a particular port.
|
|
* At the moment we only care about the rx queue size, so that is the only
|
|
* field in udp_info_t, and the only thing parsed from /proc/net/udp for the
|
|
* port.
|
|
*
|
|
* /proc/net/udp:
|
|
* sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
|
* ref pointer drops
|
|
* 53: 00000000:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 5842 2
|
|
* 86b0c500 0
|
|
* 67: 00000000:0043 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 5837 2
|
|
* 86b0c280 0
|
|
* 136: 00000000:A288 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 31927
|
|
* 2 86b0c780 0
|
|
* 141: 00000000:138D 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 31880
|
|
* 2 86b0cc80 0
|
|
* 205: 00000000:15CD 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 31982
|
|
* 2 86b0cf00 0
|
|
* 209: 00000000:CFD1 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 31855
|
|
* 2 86b0d180 0
|
|
* 224: 00000000:38E0 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 31870
|
|
* 2 86b0ca00 0
|
|
*
|
|
* Returns 0 on success, nonzero on error.
|
|
*/
|
|
int udp_info_get(unsigned port, udp_info_t *udp_info)
|
|
{
|
|
int status = -1;
|
|
FILE *fp;
|
|
char linebuf[200];
|
|
|
|
memset(udp_info, 0, sizeof(*udp_info));
|
|
|
|
fp = fopen("/proc/net/udp", "r");
|
|
if (fp == NULL)
|
|
return -1;
|
|
|
|
while (fgets(linebuf, sizeof(linebuf), fp) != NULL) {
|
|
char *saveptr;
|
|
char *token;
|
|
unsigned token_len;
|
|
char *endptr;
|
|
unsigned token_val;
|
|
|
|
/* get first token (sl, "53") */
|
|
token = strtok_r(linebuf, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting first token in line */
|
|
token_len = strlen(token);
|
|
if (token_len == 0)
|
|
continue; /* odd... */
|
|
if (!isdigit(token[0]))
|
|
continue; /* first line, token is "sl" */
|
|
/* token not used */
|
|
|
|
/* get next token (local_address/IP, "00000000") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
/* token not used */
|
|
|
|
/* get third token local_address/port in hex */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
endptr = NULL;
|
|
token_val = strtol(token, &endptr, 16);
|
|
if (*endptr != '\0')
|
|
continue; /* error converting token from hex to decimal */
|
|
if (token_val != port)
|
|
continue; /* not the port we're looking for */
|
|
|
|
/* get next token (remote_address/IP, "00000000") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
/* token not used */
|
|
|
|
/* get next token (remote_address/port, "0000") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
/* token not used */
|
|
|
|
/* get next token (st, "07") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
/* token not used */
|
|
|
|
/* get next token (tx_queue, "00000000") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
/* token not used */
|
|
|
|
/* get next token (rx_queue, "00000000") */
|
|
token = strtok_r(NULL, " :", &saveptr);
|
|
if (token == NULL)
|
|
continue; /* error getting next token in line */
|
|
endptr = NULL;
|
|
token_val = strtol(token, &endptr, 16);
|
|
if (*endptr != '\0')
|
|
continue; /* error converting token from hex to decimal */
|
|
/* verify our assumed rx queue bufsize is correct */
|
|
if ((token_val % UDP_RX_QUEUE_BUFSIZE) != 0)
|
|
udp_rx_queue_bufsize_correct = 0;
|
|
/* if correct, adjust the queue depth we are reporting */
|
|
if (udp_rx_queue_bufsize_correct)
|
|
token_val = token_val / UDP_RX_QUEUE_BUFSIZE;
|
|
/* report queue depth */
|
|
udp_info->rx_queue = token_val;
|
|
|
|
/* not interested in any more fields; we are done */
|
|
status = 0;
|
|
break;
|
|
|
|
} /* while (fgets...) */
|
|
|
|
fclose(fp);
|
|
|
|
return status;
|
|
|
|
} /* udp_info_get */
|