Added function to print network interface statistics.

This commit is contained in:
Nikos Mavrogiannopoulos
2014-01-13 15:27:35 +01:00
parent 68bd5af105
commit 766ab8ee21
5 changed files with 170 additions and 3 deletions

View File

@@ -2,7 +2,8 @@ SUBDIRS =
AM_CPPFLAGS = -I$(srcdir)/../gl/ -I$(builddir)/../gl/ \
-I$(srcdir)/ -I$(builddir)/../ $(LIBOPTS_CFLAGS) \
$(LIBPROTOBUF_C_CFLAGS) $(LIBDBUS_CFLAGS)
$(LIBPROTOBUF_C_CFLAGS) $(LIBDBUS_CFLAGS) \
$(LIBNL3_CFLAGS)
BUILT_SOURCES = ocpasswd-args.c ocpasswd-args.h \
ocserv-args.c ocserv-args.h ipc.pb-c.c ipc.pb-c.h
@@ -84,8 +85,10 @@ ocpasswd-args.c: $(srcdir)/ocpasswd-args.def
$(AUTOGEN) $<
ocpasswd-args.h: ocpasswd-args.c
occtl_SOURCES = occtl.c occtl-pager.c occtl.h occtl-time.c occtl-cache.c
occtl_LDADD = ../gl/libgnu.a $(LIBDBUS_LIBS) $(LIBREADLINE_LIBS)
occtl_SOURCES = occtl.c occtl-pager.c occtl.h occtl-time.c occtl-cache.c \
occtl-nl.c
occtl_LDADD = ../gl/libgnu.a $(LIBDBUS_LIBS) $(LIBREADLINE_LIBS) \
$(LIBNL3_LIBS)
ipc.pb-c.c: ipc.proto
protoc-c --c_out=. $<

155
src/occtl-nl.c Normal file
View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2014 Red Hat
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
* ocserv is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* GnuTLS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <occtl.h>
#if defined(HAVE_LIBNL) && defined(__linux__)
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/route/link.h>
#include <inttypes.h>
static struct nl_sock *sock = NULL;
static struct nl_cache *cache = NULL;
static struct rtnl_link *rlink = NULL;
static int nl_failed = 0;
static int open_netlink(const char* iface)
{
int err;
int if_idx;
if (sock != NULL)
return 0;
if (nl_failed != 0) /* don't bother re-opening */
return -1;
sock = nl_socket_alloc();
if (sock == NULL) {
fprintf(stderr, "nl: cannot open netlink\n");
goto error;
}
if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
fprintf(stderr, "nl: error in nl_connect");
goto error;
}
if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache) < 0) {
fprintf(stderr, "nl: failed to alloc cache");
goto error;
}
if (!(if_idx = rtnl_link_name2i(cache, iface))) {
fprintf(stderr, "nl: cannot find %s\n", iface);
goto error;
}
rlink = rtnl_link_get (cache, if_idx);
if (rlink == NULL) {
fprintf(stderr, "nl: cannot get rlink\n");
goto error;
}
return 0;
error:
if (sock != NULL) {
nl_socket_free(sock);
sock = NULL;
}
if (cache != NULL)
nl_cache_free(cache);
nl_failed = 1;
return -1;
}
static void
bytes2human(unsigned long bytes, char* output, unsigned output_size, const char* suffix)
{
double data;
if (suffix == NULL)
suffix = "";
if (bytes > 1000 && bytes < 1000 * 1000) {
data = ((double) bytes) / 1000;
snprintf(output, output_size, "%.1f KB%s", data, suffix);
return;
} else if (bytes >= 1000 * 1000 && bytes < 1000 * 1000 * 1000) {
data = ((double) bytes) / (1000 * 1000);
snprintf(output, output_size, "%.1f MB%s", data, suffix);
return;
} else if (bytes >= 1000 * 1000 * 1000) {
data = ((double) bytes) / (1000 * 1000 * 1000);
snprintf(output, output_size, "%.1f GB%s", data, suffix);
return;
} else {
snprintf(output, output_size, "%lu bytes%s", bytes, suffix);
return;
}
}
static void
value2speed(unsigned long bytes, time_t time, char* output, unsigned output_size)
{
unsigned long speed;
speed = bytes / time;
bytes2human(speed, output, output_size, "/sec");
}
void print_iface_stats(const char *iface, time_t since, FILE * out)
{
uint64_t tx, rx;
char buf1[32], buf2[32];
time_t diff = time(0) - since;
if (open_netlink(iface) < 0)
return;
rx = rtnl_link_get_stat(rlink, RTNL_LINK_RX_BYTES);
tx = rtnl_link_get_stat(rlink, RTNL_LINK_TX_BYTES);
bytes2human(rx, buf1, sizeof(buf1), NULL);
bytes2human(tx, buf2, sizeof(buf2), NULL);
fprintf(out, "\tRX: %"PRIu64" (%s) TX: %"PRIu64" (%s)\n", rx, buf1, tx, buf2);
value2speed(rx, diff, buf1, sizeof(buf1));
value2speed(tx, diff, buf2, sizeof(buf2));
fprintf(out, "\tAverage bandwidth RX: %s TX: %s\n", buf1, buf2);
return;
}
#else
void print_iface_stats(const char *iface, FILE * out)
{
return;
}
#endif

View File

@@ -889,6 +889,8 @@ int common_info_cmd(DBusMessageIter * args)
else
fprintf(out, "\n");
print_iface_stats(device, since, out);
if (hostname != NULL && hostname[0] != 0)
fprintf(out, "\tHostname: %s\n", hostname);

View File

@@ -7,6 +7,7 @@
FILE* pager_start(void);
void pager_stop(FILE* fp);
void print_time_ival7(time_t t, FILE * fout);
void print_iface_stats(const char *iface, time_t since, FILE * out);
char* search_for_id(unsigned idx, const char* match, int match_size);
char* search_for_user(unsigned idx, const char* match, int match_size);