1 /**
2 * collectd - src/traffic.c
3 * Copyright (C) 2005 Florian octo Forster
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Authors:
20 * Florian octo Forster <octo at verplant.org>
21 **/
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
27 #define MODULE_NAME "traffic"
29 #if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
30 # define TRAFFIC_HAVE_READ 1
31 #else
32 # define TRAFFIC_HAVE_READ 0
33 #endif
35 #define BUFSIZE 512
37 static char *traffic_filename_template = "traffic-%s.rrd";
39 static char *ds_def[] =
40 {
41 "DS:incoming:COUNTER:25:0:U",
42 "DS:outgoing:COUNTER:25:0:U",
43 NULL
44 };
45 static int ds_num = 2;
47 #ifdef HAVE_LIBKSTAT
48 #define MAX_NUMIF 256
49 extern kstat_ctl_t *kc;
50 static kstat_t *ksp[MAX_NUMIF];
51 static int numif = 0;
52 #endif /* HAVE_LIBKSTAT */
54 static void traffic_init (void)
55 {
56 #ifdef HAVE_LIBKSTAT
57 kstat_t *ksp_chain;
58 kstat_named_t *kn;
59 unsigned long long val;
61 numif = 0;
63 if (kc == NULL)
64 return;
66 for (numif = 0, ksp_chain = kc->kc_chain;
67 (numif < MAX_NUMIF) && (ksp_chain != NULL);
68 ksp_chain = ksp_chain->ks_next)
69 {
70 if (strncmp (ksp_chain->ks_class, "net", 3))
71 continue;
72 if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
73 continue;
74 if (kstat_read (kc, ksp_chain, NULL) == -1)
75 continue;
76 if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
77 continue;
78 ksp[numif++] = ksp_chain;
79 }
80 #endif /* HAVE_LIBKSTAT */
81 }
83 static void traffic_write (char *host, char *inst, char *val)
84 {
85 char file[BUFSIZE];
86 int status;
88 status = snprintf (file, BUFSIZE, traffic_filename_template, inst);
89 if (status < 1)
90 return;
91 else if (status >= BUFSIZE)
92 return;
94 rrd_update_file (host, file, val, ds_def, ds_num);
95 }
97 #if TRAFFIC_HAVE_READ
98 static void traffic_submit (char *device,
99 unsigned long long incoming,
100 unsigned long long outgoing)
101 {
102 char buf[BUFSIZE];
104 if (snprintf (buf, BUFSIZE, "%u:%lld:%lld", (unsigned int) curtime, incoming, outgoing) >= BUFSIZE)
105 return;
107 plugin_submit (MODULE_NAME, device, buf);
108 }
110 static void traffic_read (void)
111 {
112 #ifdef KERNEL_LINUX
113 FILE *fh;
114 char buffer[1024];
115 unsigned long long incoming, outgoing;
116 char *device;
118 char *dummy;
119 char *fields[16];
120 int numfields;
122 if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
123 {
124 syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
125 return;
126 }
128 while (fgets (buffer, 1024, fh) != NULL)
129 {
130 if (buffer[6] != ':')
131 continue;
132 buffer[6] = '\0';
134 device = buffer;
135 while (device[0] == ' ')
136 device++;
138 if (device[0] == '\0')
139 continue;
141 dummy = buffer + 7;
142 numfields = strsplit (dummy, fields, 16);
144 if (numfields < 9)
145 continue;
147 incoming = atoll (fields[0]);
148 outgoing = atoll (fields[8]);
150 traffic_submit (device, incoming, outgoing);
151 }
153 fclose (fh);
154 /* #endif KERNEL_LINUX */
156 #elif defined(HAVE_LIBKSTAT)
157 int i;
158 unsigned long long incoming, outgoing;
160 if (kc == NULL)
161 return;
163 for (i = 0; i < numif; i++)
164 {
165 if (kstat_read (kc, ksp[i], NULL) == -1)
166 continue;
168 if ((incoming = get_kstat_value (ksp[i], "rbytes")) == -1LL)
169 continue;
170 if ((outgoing = get_kstat_value (ksp[i], "obytes")) == -1LL)
171 continue;
173 traffic_submit (ksp[i]->ks_name, incoming, outgoing);
174 }
175 /* #endif HAVE_LIBKSTAT */
177 #elif defined(HAVE_LIBSTATGRAB)
178 sg_network_io_stats *ios;
179 int i, num;
181 ios = sg_get_network_io_stats (&num);
183 for (i = 0; i < num; i++)
184 traffic_submit (ios[i].interface_name, ios[i].rx, ios[i].tx);
185 #endif /* HAVE_LIBSTATGRAB */
186 }
187 #else
188 #define traffic_read NULL
189 #endif /* TRAFFIC_HAVE_READ */
191 void module_register (void)
192 {
193 plugin_register (MODULE_NAME, traffic_init, traffic_read, traffic_write);
194 }
196 #undef BUFSIZE
197 #undef MODULE_NAME