Added implementation for this function.
1998-11-22 Martin Baulig <baulig@merkur.uni-trier.de> * netload.c (glibtop_get_netload_s): Added implementation for this function. The code here is smart enough to use /proc/net/ip_acct if IP accounting is enabled in the kernel and activated on the requested device and /proc/net/dev if not. To get separate statistics for received and transmitted packets you need to use two accounting rules: ipfwadm -A in -a -P all -W eth0 ipfwadm -A out -a -P all -W eth0 But before you activate IP accounting, please have a look at /proc/net/dev - if if already contains byte counters, then don't use IP accounting.
This commit is contained in:
committed by
Martin Baulig
parent
4ac6972be6
commit
9c0ec8c69f
@@ -1,3 +1,22 @@
|
|||||||
|
1998-11-22 Martin Baulig <baulig@merkur.uni-trier.de>
|
||||||
|
|
||||||
|
* netload.c (glibtop_get_netload_s): Added implementation
|
||||||
|
for this function.
|
||||||
|
|
||||||
|
The code here is smart enough to use /proc/net/ip_acct if
|
||||||
|
IP accounting is enabled in the kernel and activated on the
|
||||||
|
requested device and /proc/net/dev if not.
|
||||||
|
|
||||||
|
To get separate statistics for received and transmitted
|
||||||
|
packets you need to use two accounting rules:
|
||||||
|
|
||||||
|
ipfwadm -A in -a -P all -W eth0
|
||||||
|
ipfwadm -A out -a -P all -W eth0
|
||||||
|
|
||||||
|
But before you activate IP accounting, please have a look
|
||||||
|
at /proc/net/dev - if if already contains byte counters,
|
||||||
|
then don't use IP accounting.
|
||||||
|
|
||||||
1998-10-28 Martin Baulig <martin@home-of-linux.org>
|
1998-10-28 Martin Baulig <martin@home-of-linux.org>
|
||||||
|
|
||||||
* ppp.c: Added code for ISDN here.
|
* ppp.c: Added code for ISDN here.
|
||||||
|
@@ -23,14 +23,63 @@
|
|||||||
#include <glibtop/error.h>
|
#include <glibtop/error.h>
|
||||||
#include <glibtop/netload.h>
|
#include <glibtop/netload.h>
|
||||||
|
|
||||||
static const unsigned long _glibtop_sysdeps_netload = 0;
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/ip_fw.h>
|
||||||
|
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload =
|
||||||
|
(1 << GLIBTOP_NETLOAD_ERRORS_IN) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_ERRORS_OUT) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_COLLISIONS);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_data =
|
||||||
|
(1 << GLIBTOP_NETLOAD_ADDRESS) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_SUBNET) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_MTU);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_bytes =
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_IN) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_OUT) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_TOTAL);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_packets =
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_IN) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_OUT) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_TOTAL);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_total =
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_TOTAL);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_in =
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_TOTAL) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_IN) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_IN);
|
||||||
|
|
||||||
|
static const unsigned long _glibtop_sysdeps_netload_out =
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_TOTAL) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_PACKETS_OUT) +
|
||||||
|
(1 << GLIBTOP_NETLOAD_BYTES_OUT);
|
||||||
|
|
||||||
/* Init function. */
|
/* Init function. */
|
||||||
|
|
||||||
void
|
void
|
||||||
glibtop_init_netload_s (glibtop *server)
|
glibtop_init_netload_s (glibtop *server)
|
||||||
{
|
{
|
||||||
server->sysdeps.netload = _glibtop_sysdeps_netload;
|
server->sysdeps.netload = _glibtop_sysdeps_netload |
|
||||||
|
_glibtop_sysdeps_netload_data |
|
||||||
|
_glibtop_sysdeps_netload_bytes |
|
||||||
|
_glibtop_sysdeps_netload_packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Provides network statistics. */
|
/* Provides network statistics. */
|
||||||
@@ -39,5 +88,241 @@ void
|
|||||||
glibtop_get_netload_s (glibtop *server, glibtop_netload *buf,
|
glibtop_get_netload_s (glibtop *server, glibtop_netload *buf,
|
||||||
const char *interface)
|
const char *interface)
|
||||||
{
|
{
|
||||||
|
char buffer [BUFSIZ], *p;
|
||||||
|
int have_bytes, fields, skfd;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
memset (buf, 0, sizeof (glibtop_netload));
|
memset (buf, 0, sizeof (glibtop_netload));
|
||||||
|
|
||||||
|
skfd = socket (AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (skfd) {
|
||||||
|
struct ifreq ifr;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
char *address;
|
||||||
|
unsigned flags;
|
||||||
|
|
||||||
|
strcpy (ifr.ifr_name, interface);
|
||||||
|
if (!ioctl (skfd, SIOCGIFFLAGS, &ifr)) {
|
||||||
|
buf->flags |= (1 << GLIBTOP_NETLOAD_IF_FLAGS);
|
||||||
|
flags = ifr.ifr_flags;
|
||||||
|
} else
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
if (flags & IFF_UP)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_UP);
|
||||||
|
|
||||||
|
if (flags & IFF_BROADCAST)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_BROADCAST);
|
||||||
|
|
||||||
|
if (flags & IFF_DEBUG)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_DEBUG);
|
||||||
|
|
||||||
|
if (flags & IFF_LOOPBACK)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_LOOPBACK);
|
||||||
|
|
||||||
|
if (flags & IFF_POINTOPOINT)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_POINTOPOINT);
|
||||||
|
|
||||||
|
if (flags & IFF_RUNNING)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_RUNNING);
|
||||||
|
|
||||||
|
if (flags & IFF_NOARP)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_NOARP);
|
||||||
|
|
||||||
|
if (flags & IFF_PROMISC)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_PROMISC);
|
||||||
|
|
||||||
|
if (flags & IFF_ALLMULTI)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_ALLMULTI);
|
||||||
|
|
||||||
|
if (flags & IFF_MULTICAST)
|
||||||
|
buf->if_flags |= (1 << GLIBTOP_IF_FLAGS_MULTICAST);
|
||||||
|
|
||||||
|
strcpy (ifr.ifr_name, interface);
|
||||||
|
if (!ioctl (skfd, SIOCGIFADDR, &ifr)) {
|
||||||
|
struct sockaddr_in addr =
|
||||||
|
*(struct sockaddr_in *) &ifr.ifr_addr;
|
||||||
|
buf->address = addr.sin_addr.s_addr;
|
||||||
|
buf->flags |= (1 << GLIBTOP_NETLOAD_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy (ifr.ifr_name, interface);
|
||||||
|
if (!ioctl (skfd, SIOCGIFNETMASK, &ifr)) {
|
||||||
|
struct sockaddr_in addr =
|
||||||
|
*(struct sockaddr_in *) &ifr.ifr_addr;
|
||||||
|
buf->subnet = addr.sin_addr.s_addr;
|
||||||
|
buf->flags |= (1 << GLIBTOP_NETLOAD_SUBNET);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy (ifr.ifr_name, interface);
|
||||||
|
if (!ioctl (skfd, SIOCGIFMTU, &ifr)) {
|
||||||
|
buf->mtu = ifr.ifr_mtu;
|
||||||
|
buf->flags |= (1 << GLIBTOP_NETLOAD_MTU);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (skfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If IP accounting is enabled in the kernel and it is
|
||||||
|
* enabled for the requested interface, we use it to
|
||||||
|
* get the data. In this case, we don't use /proc/net/dev
|
||||||
|
* to get errors and collisions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
f = fopen ("/proc/net/ip_acct", "r");
|
||||||
|
if (f) {
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
/* Skip over the header line. */
|
||||||
|
fgets (buffer, BUFSIZ-1, f);
|
||||||
|
|
||||||
|
while (fgets (buffer, BUFSIZ-1, f)) {
|
||||||
|
unsigned long flags, packets, bytes;
|
||||||
|
char *p, *dev;
|
||||||
|
|
||||||
|
/* Skip over the network thing. */
|
||||||
|
dev = skip_token (buffer) + 1;
|
||||||
|
p = skip_token (dev);
|
||||||
|
*p++ = 0;
|
||||||
|
|
||||||
|
if (strcmp (dev, interface))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
success = 1;
|
||||||
|
|
||||||
|
p = skip_token (p);
|
||||||
|
|
||||||
|
flags = strtoul (p, &p, 16);
|
||||||
|
|
||||||
|
p = skip_multiple_token (p, 2);
|
||||||
|
|
||||||
|
packets = strtoul (p, &p, 0);
|
||||||
|
bytes = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
if (flags & IP_FW_F_ACCTIN) {
|
||||||
|
/* Incoming packets only. */
|
||||||
|
|
||||||
|
buf->packets_total += packets;
|
||||||
|
buf->packets_in += packets;
|
||||||
|
|
||||||
|
buf->bytes_total += bytes;
|
||||||
|
buf->bytes_in += bytes;
|
||||||
|
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload_in;
|
||||||
|
|
||||||
|
} else if (flags & IP_FW_F_ACCTOUT) {
|
||||||
|
/* Outgoing packets only. */
|
||||||
|
|
||||||
|
buf->packets_total += packets;
|
||||||
|
buf->packets_out += packets;
|
||||||
|
|
||||||
|
buf->bytes_total += bytes;
|
||||||
|
buf->bytes_out += bytes;
|
||||||
|
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload_out;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Only have total values. */
|
||||||
|
|
||||||
|
buf->packets_total += packets;
|
||||||
|
buf->bytes_total += bytes;
|
||||||
|
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload_total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (f);
|
||||||
|
|
||||||
|
if (success) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ok, either IP accounting is not enabled in the kernel or
|
||||||
|
* it was not enabled for the requested interface. */
|
||||||
|
|
||||||
|
f = fopen ("/proc/net/dev", "r");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
/* Skip over the header line. */
|
||||||
|
fgets (buffer, BUFSIZ-1, f);
|
||||||
|
fgets (buffer, BUFSIZ-1, f);
|
||||||
|
|
||||||
|
/* Starting with 2.1.xx (don't know exactly which version)
|
||||||
|
* /proc/net/dev contains both byte and package counters. */
|
||||||
|
|
||||||
|
p = strchr (buffer, '|');
|
||||||
|
if (!p) {
|
||||||
|
fclose (f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we already have byte counters ? */
|
||||||
|
have_bytes = strncmp (++p, "bytes", 5) == 0;
|
||||||
|
|
||||||
|
/* Count remaining 'Receive' fields so we know where
|
||||||
|
* the first 'Transmit' field starts. */
|
||||||
|
|
||||||
|
fields = 0;
|
||||||
|
while (*p != '|') {
|
||||||
|
if (isspace (*p))
|
||||||
|
fields++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should never happen. */
|
||||||
|
if (!fields) return;
|
||||||
|
fields--;
|
||||||
|
|
||||||
|
while (fgets (buffer, BUFSIZ-1, f)) {
|
||||||
|
char *p, *dev;
|
||||||
|
|
||||||
|
dev = buffer;
|
||||||
|
while (isspace (*dev)) dev++;
|
||||||
|
|
||||||
|
p = strchr (dev, ':');
|
||||||
|
if (!p) continue;
|
||||||
|
*p++ = 0;
|
||||||
|
|
||||||
|
/* If it's not a digit, then it's most likely an error
|
||||||
|
* message like 'No statistics available'. */
|
||||||
|
while (isspace (*p)) p++;
|
||||||
|
if (!isdigit (*p)) continue;
|
||||||
|
|
||||||
|
if (strcmp (dev, interface))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Only read byte counts if we really have them. */
|
||||||
|
|
||||||
|
if (have_bytes)
|
||||||
|
buf->bytes_in = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
buf->packets_in = strtoul (p, &p, 0);
|
||||||
|
buf->errors_in = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
p = skip_multiple_token (p, fields);
|
||||||
|
|
||||||
|
if (have_bytes)
|
||||||
|
buf->bytes_out = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
buf->packets_out = strtoul (p, &p, 0);
|
||||||
|
buf->errors_out = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
p = skip_multiple_token (p, 2);
|
||||||
|
|
||||||
|
buf->collisions = strtoul (p, &p, 0);
|
||||||
|
|
||||||
|
/* Compute total valules. */
|
||||||
|
|
||||||
|
buf->bytes_total = buf->bytes_in + buf->bytes_out;
|
||||||
|
buf->packets_total = buf->packets_in + buf->packets_out;
|
||||||
|
|
||||||
|
/* And now the flags. */
|
||||||
|
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload;
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload_packets;
|
||||||
|
|
||||||
|
if (have_bytes)
|
||||||
|
buf->flags |= _glibtop_sysdeps_netload_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (f);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user