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