Cleaned up all the modules, unified define order and the like..
[collectd.git] / src / traffic.c
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  **/
22
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
26
27 #define MODULE_NAME "traffic"
28
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
34
35 static char *traffic_filename_template = "traffic-%s.rrd";
36
37 static char *ds_def[] =
38 {
39         "DS:incoming:COUNTER:25:0:U",
40         "DS:outgoing:COUNTER:25:0:U",
41         NULL
42 };
43 static int ds_num = 2;
44
45 #ifdef HAVE_LIBKSTAT
46 #define MAX_NUMIF 256
47 extern kstat_ctl_t *kc;
48 static kstat_t *ksp[MAX_NUMIF];
49 static int numif = 0;
50 #endif /* HAVE_LIBKSTAT */
51
52 static void traffic_init (void)
53 {
54 #ifdef HAVE_LIBKSTAT
55         kstat_t *ksp_chain;
56         kstat_named_t *kn;
57         unsigned long long val;
58
59         numif = 0;
60
61         if (kc == NULL)
62                 return;
63
64         for (numif = 0, ksp_chain = kc->kc_chain;
65                         (numif < MAX_NUMIF) && (ksp_chain != NULL);
66                         ksp_chain = ksp_chain->ks_next)
67         {
68                 if (strncmp (ksp_chain->ks_class, "net", 3))
69                         continue;
70                 if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
71                         continue;
72                 if (kstat_read (kc, ksp_chain, NULL) == -1)
73                         continue;
74                 if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
75                         continue;
76                 ksp[numif++] = ksp_chain;
77         }
78 #endif /* HAVE_LIBKSTAT */
79 }
80
81 static void traffic_write (char *host, char *inst, char *val)
82 {
83         char file[512];
84         int status;
85
86         status = snprintf (file, 512, traffic_filename_template, inst);
87         if (status < 1)
88                 return;
89         else if (status >= 512)
90                 return;
91
92         rrd_update_file (host, file, val, ds_def, ds_num);
93 }
94
95 #define BUFSIZE 512
96 static void traffic_submit (char *device,
97                 unsigned long long incoming,
98                 unsigned long long outgoing)
99 {
100         char buf[BUFSIZE];
101
102         if (snprintf (buf, BUFSIZE, "%u:%lld:%lld", (unsigned int) curtime, incoming, outgoing) >= BUFSIZE)
103                 return;
104
105         plugin_submit (MODULE_NAME, device, buf);
106 }
107 #undef BUFSIZE
108
109 #if TRAFFIC_HAVE_READ
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;
117         
118         char *dummy;
119         char *fields[16];
120         int numfields;
121
122         if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
123         {
124                 syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
125                 return;
126         }
127
128         while (fgets (buffer, 1024, fh) != NULL)
129         {
130                 if (buffer[6] != ':')
131                         continue;
132                 buffer[6] = '\0';
133
134                 device = buffer;
135                 while (device[0] == ' ')
136                         device++;
137
138                 if (device[0] == '\0')
139                         continue;
140                 
141                 dummy = buffer + 7;
142                 numfields = strsplit (dummy, fields, 16);
143
144                 if (numfields < 9)
145                         continue;
146
147                 incoming = atoll (fields[0]);
148                 outgoing = atoll (fields[8]);
149
150                 traffic_submit (device, incoming, outgoing);
151         }
152
153         fclose (fh);
154 /* #endif KERNEL_LINUX */
155
156 #elif defined(HAVE_LIBKSTAT)
157         int i;
158         unsigned long long incoming, outgoing;
159
160         if (kc == NULL)
161                 return;
162
163         for (i = 0; i < numif; i++)
164         {
165                 if (kstat_read (kc, ksp[i], NULL) == -1)
166                         continue;
167
168                 if ((incoming = get_kstat_value (ksp[i], "rbytes")) == -1LL)
169                         continue;
170                 if ((outgoing = get_kstat_value (ksp[i], "obytes")) == -1LL)
171                         continue;
172
173                 traffic_submit (ksp[i]->ks_name, incoming, outgoing);
174         }
175 /* #endif HAVE_LIBKSTAT */
176
177 #elif defined(HAVE_LIBSTATGRAB)
178         sg_network_io_stats *ios;
179         int i, num;
180
181         ios = sg_get_network_io_stats (&num);
182
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 */
190
191 void module_register (void)
192 {
193         plugin_register (MODULE_NAME, traffic_init, traffic_read, traffic_write);
194 }
195
196 #undef MODULE_NAME