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 "traffic.h"
25 #if COLLECT_TRAFFIC
26 #define MODULE_NAME "traffic"
28 #include "plugin.h"
29 #include "common.h"
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 */
38 static char *traffic_filename_template = "traffic-%s.rrd";
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;
48 void traffic_init (void)
49 {
50 #ifdef HAVE_LIBKSTAT
51 kstat_t *ksp_chain;
52 kstat_named_t *kn;
53 unsigned long long val;
55 numif = 0;
57 if (kc == NULL)
58 return;
60 for (numif = 0, ksp_chain = kc->kc_chain;
61 (numif < MAX_NUMIF) && (ksp_chain != NULL);
62 ksp_chain = ksp_chain->ks_next)
63 {
64 if (strncmp (ksp_chain->ks_class, "net", 3))
65 continue;
66 if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
67 continue;
68 if (kstat_read (kc, ksp_chain, NULL) == -1)
69 continue;
70 if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
71 continue;
72 ksp[numif++] = ksp_chain;
73 }
74 #endif /* HAVE_LIBKSTAT */
75 }
77 void traffic_write (char *host, char *inst, char *val)
78 {
79 char file[512];
80 int status;
82 status = snprintf (file, 512, traffic_filename_template, inst);
83 if (status < 1)
84 return;
85 else if (status >= 512)
86 return;
88 rrd_update_file (host, file, val, ds_def, ds_num);
89 }
91 #define BUFSIZE 512
92 void traffic_submit (char *device,
93 unsigned long long incoming,
94 unsigned long long outgoing)
95 {
96 char buf[BUFSIZE];
98 if (snprintf (buf, BUFSIZE, "%u:%lld:%lld", (unsigned int) curtime, incoming, outgoing) >= BUFSIZE)
99 return;
101 plugin_submit (MODULE_NAME, device, buf);
102 }
103 #undef BUFSIZE
105 void traffic_read (void)
106 {
107 #ifdef KERNEL_LINUX
108 FILE *fh;
109 char buffer[1024];
110 unsigned long long incoming, outgoing;
111 char *device;
113 char *dummy;
114 char *fields[16];
115 int numfields;
117 if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
118 {
119 syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
120 return;
121 }
123 while (fgets (buffer, 1024, fh) != NULL)
124 {
125 if (buffer[6] != ':')
126 continue;
127 buffer[6] = '\0';
129 device = buffer;
130 while (device[0] == ' ')
131 device++;
133 if (device[0] == '\0')
134 continue;
136 dummy = buffer + 7;
137 numfields = strsplit (dummy, fields, 16);
139 if (numfields < 9)
140 continue;
142 incoming = atoll (fields[0]);
143 outgoing = atoll (fields[8]);
145 traffic_submit (device, incoming, outgoing);
146 }
148 fclose (fh);
149 /* #endif KERNEL_LINUX */
151 #elif defined(HAVE_LIBKSTAT)
152 int i;
153 unsigned long long incoming, outgoing;
155 if (kc == NULL)
156 return;
158 for (i = 0; i < numif; i++)
159 {
160 if (kstat_read (kc, ksp[i], NULL) == -1)
161 continue;
163 if ((incoming = get_kstat_value (ksp[i], "rbytes")) == -1LL)
164 continue;
165 if ((outgoing = get_kstat_value (ksp[i], "obytes")) == -1LL)
166 continue;
168 traffic_submit (ksp[i]->ks_name, incoming, outgoing);
169 }
170 /* #endif HAVE_LIBKSTAT */
172 #elif defined(HAVE_LIBSTATGRAB)
173 sg_network_io_stats *ios;
174 int i, num;
176 ios = sg_get_network_io_stats (&num);
178 for (i = 0; i < num; i++)
179 traffic_submit (ios[i].interface_name, ios[i].rx, ios[i].tx);
180 #endif /* HAVE_LIBSTATGRAB */
181 }
183 void module_register (void)
184 {
185 plugin_register (MODULE_NAME, traffic_init, traffic_read, traffic_write);
186 }
188 #undef MODULE_NAME
189 #endif /* COLLECT_TRAFFIC */