This patch adds %ifutil to statistics displayed by sar -n.
%ifutil is a new metric giving the utilization percentage of the
corresponding network interface.
struct activity net_dev_act = {
.id = A_NET_DEV,
.options = AO_COLLECTED,
- .magic = ACTIVITY_MAGIC_BASE + 1,
+ .magic = ACTIVITY_MAGIC_BASE + 2,
.group = G_DEFAULT,
#ifdef SOURCE_SADC
.f_count = wrap_get_iface_nr,
.f_render = render_net_dev_stats,
.f_xml_print = xml_print_net_dev_stats,
.f_json_print = json_print_net_dev_stats,
- .hdr_line = "IFACE;rxpck/s;txpck/s;rxkB/s;txkB/s;rxcmp/s;txcmp/s;rxmcst/s",
+ .hdr_line = "IFACE;rxpck/s;txpck/s;rxkB/s;txkB/s;rxcmp/s;txcmp/s;rxmcst/s;%ifutil",
.name = "A_NET_DEV",
#endif
.nr = -1,
{
int i, j;
struct stats_net_dev *sndc, *sndp;
+ double rxkb, txkb, ifutil;
if (dis) {
printf("\n%-11s IFACE rxpck/s txpck/s rxkB/s txkB/s"
- " rxcmp/s txcmp/s rxmcst/s\n", timestamp[!curr]);
+ " rxcmp/s txcmp/s rxmcst/s %%ifutil\n", timestamp[!curr]);
}
for (i = 0; i < a->nr; i++) {
printf("%-11s %9s", timestamp[curr], sndc->interface);
- printf(" %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n",
+ rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
+ txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
+
+ printf(" %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f",
S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
- S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv) / 1024,
- S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv) / 1024,
+ rxkb / 1024,
+ txkb / 1024,
S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
S_VALUE(sndp->multicast, sndc->multicast, itv));
+
+ ifutil = compute_ifutil(sndc, rxkb, txkb);
+ printf(" %6.2f\n", ifutil);
}
}
*
* OUT:
* @st_net_dev Structure with statistics.
+ *
+ * RETURNS:
+ * Number of interfaces for which stats have been read.
***************************************************************************
*/
-void read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
+int read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
{
FILE *fp;
struct stats_net_dev *st_net_dev_i;
int pos;
if ((fp = fopen(NET_DEV, "r")) == NULL)
- return;
+ return 0;
while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
}
fclose(fp);
+
+ return dev;
+}
+
+/*
+ ***************************************************************************
+ * Read duplex and speed data for network interface cards.
+ *void
+ * IN:
+ * @st_net_dev Structure where stats will be saved.
+ * @nbr Real number of network interfaces available.
+ *
+ * OUT:
+ * @st_net_dev Structure with statistics.
+ ***************************************************************************
+ */
+void read_if_info(struct stats_net_dev *st_net_dev, int nbr)
+{
+ FILE *fp;
+ struct stats_net_dev *st_net_dev_i;
+ char filename[128], duplex[32];
+ int dev, n;
+
+ for (dev = 0; dev < nbr; dev++) {
+
+ st_net_dev_i = st_net_dev + dev;
+
+ /* Read speed info */
+ sprintf(filename, IF_DUPLEX, st_net_dev_i->interface);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ /* Cannot read NIC duplex */
+ continue;
+
+ n = fscanf(fp, "%s", duplex);
+
+ fclose(fp);
+
+ if (n != 1)
+ /* Cannot read NIC duplex */
+ continue;
+
+ if (!strcmp(duplex, K_DUPLEX_FULL)) {
+ st_net_dev_i->duplex = C_DUPLEX_FULL;
+ }
+ else if (!strcmp(duplex, K_DUPLEX_HALF)) {
+ st_net_dev_i->duplex = C_DUPLEX_HALF;
+ }
+ else
+ continue;
+
+ /* Read speed info */
+ sprintf(filename, IF_SPEED, st_net_dev_i->interface);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ /* Cannot read NIC speed */
+ continue;
+
+ fscanf(fp, "%u", &st_net_dev_i->speed);
+
+ fclose(fp);
+ }
}
+
/*
***************************************************************************
* Read network interfaces errors statistics from /proc/net/dev.
#define CNT_ALL_DEV 0
#define CNT_USED_DEV 1
+#define K_DUPLEX_HALF "half"
+#define K_DUPLEX_FULL "full"
+
+#define C_DUPLEX_HALF 1
+#define C_DUPLEX_FULL 2
+
/*
***************************************************************************
* System files containing statistics
#define NET_SNMP6 "/proc/net/snmp6"
#define CPUINFO "/proc/cpuinfo"
#define MTAB "/etc/mtab"
+#define IF_DUPLEX "/sys/class/net/%s/duplex"
+#define IF_SPEED "/sys/class/net/%s/speed"
/*
unsigned long long rx_compressed __attribute__ ((aligned (16)));
unsigned long long tx_compressed __attribute__ ((aligned (16)));
unsigned long long multicast __attribute__ ((aligned (16)));
- char interface[MAX_IFACE_LEN] __attribute__ ((aligned (16)));
+ unsigned int speed __attribute__ ((aligned (16)));
+ char interface[MAX_IFACE_LEN] __attribute__ ((aligned (4)));
+ char duplex;
};
#define STATS_NET_DEV_SIZE (sizeof(struct stats_net_dev))
read_tty_driver_serial(struct stats_serial *, int);
extern void
read_kernel_tables(struct stats_ktables *);
-extern void
+extern int
read_net_dev(struct stats_net_dev *, int);
+extern void
+ read_if_info(struct stats_net_dev *, int);
extern void
read_net_edev(struct stats_net_edev *, int);
extern void
check_net_dev_reg(struct activity *, int, int, unsigned int);
extern unsigned int
check_net_edev_reg(struct activity *, int, int, unsigned int);
+extern double
+ compute_ifutil(struct stats_net_dev *, double, double);
extern void
copy_structures(struct activity * [], unsigned int [],
struct record_header [], int, int);
return 0;
}
+/*
+ ***************************************************************************
+ * Compute network interface utilization.
+ *
+ * IN:
+ * @st_net_dev Structure with network interface stats.
+ * @rx Number of bytes received per second.
+ * @tx Number of bytes transmitted per second.
+ *
+ * RETURNS:
+ * NIC utilization (0-100%).
+ ***************************************************************************
+ */
+double compute_ifutil(struct stats_net_dev *st_net_dev, double rx, double tx)
+{
+ unsigned long long speed;
+
+ if (st_net_dev->speed) {
+
+ speed = st_net_dev->speed * 1000000;
+
+ if (st_net_dev->duplex == C_DUPLEX_FULL) {
+ /* Full duplex */
+ if (rx > tx) {
+ return (rx * 800 / speed);
+ }
+ else {
+ return (tx * 800 / speed);
+ }
+ }
+ else {
+ /* Half duplex */
+ return ((rx + tx) * 800 / speed);
+ }
+ }
+
+ return 0;
+}
+
{
struct stats_net_dev *st_net_dev
= (struct stats_net_dev *) a->_buf0;
+ int dev;
/* Read network interfaces stats */
- read_net_dev(st_net_dev, a->nr);
+ dev = read_net_dev(st_net_dev, a->nr);
+ if (!dev)
+ /* No data read. Exit */
+ return;
+
+ /* Read duplex and speed info for each interface */
+ read_if_info(st_net_dev, dev);
return;
}