2 * luci-bwc - Very simple bandwidth collector cache for LuCI realtime graphs
4 * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
31 #include <arpa/inet.h>
37 #define DB_PATH "/var/lib/luci-bwc"
38 #define DB_FILE DB_PATH "/%s"
40 #define SCAN_PATTERN \
41 " %[^ :]:%" SCNu64 " %" SCNu64 \
42 " %*d %*d %*d %*d %*d %*d" \
43 " %" SCNu64 " %" SCNu64
46 struct traffic_entry {
54 static uint64_t htonll(uint64_t value)
58 if (*(char *)&num == 1)
59 return htonl((uint32_t)(value & 0xFFFFFFFF)) |
60 htonl((uint32_t)(value >> 32));
68 static int init_minutely(const char *ifname)
73 struct traffic_entry e = { 0 };
75 snprintf(path, sizeof(path), DB_FILE, ifname);
77 for (p = &path[1]; *p; p++)
83 if (mkdir(path, 0700) && (errno != EEXIST))
90 if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
92 for (i = 0; i < STEP_COUNT; i++)
94 if (write(file, &e, sizeof(struct traffic_entry)) < 0)
106 static int update_minutely(
107 const char *ifname, uint64_t rxb, uint64_t rxp, uint64_t txb, uint64_t txp
112 int entrysize = sizeof(struct traffic_entry);
113 int mapsize = STEP_COUNT * entrysize;
119 struct traffic_entry e;
121 snprintf(path, sizeof(path), DB_FILE, ifname);
125 if (init_minutely(ifname))
127 fprintf(stderr, "Failed to init %s: %s\n",
128 path, strerror(errno));
134 if ((file = open(path, O_RDWR)) >= 0)
136 map = mmap(NULL, mapsize, PROT_READ | PROT_WRITE,
137 MAP_SHARED | MAP_LOCKED, file, 0);
139 if ((map != NULL) && (map != MAP_FAILED))
141 e.time = htonll(time(NULL));
147 memmove(map, map + entrysize, mapsize - entrysize);
148 memcpy(map + mapsize - entrysize, &e, entrysize);
150 munmap(map, mapsize);
161 static int run_daemon(int nofork)
164 uint64_t rxb, txb, rxp, txp;
198 if ((info = fopen("/proc/net/dev", "r")) != NULL)
200 while (fgets(line, sizeof(line), info))
202 if (strchr(line, '|'))
205 if (sscanf(line, SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp))
207 if (strncmp(ifname, "lo", sizeof(ifname)))
208 update_minutely(ifname, rxb, rxp, txb, txp);
219 static int run_dump(const char *ifname)
224 int entrysize = sizeof(struct traffic_entry);
225 int mapsize = STEP_COUNT * entrysize;
230 struct traffic_entry *e;
232 snprintf(path, sizeof(path), DB_FILE, ifname);
234 if ((file = open(path, O_RDONLY)) >= 0)
236 map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED | MAP_LOCKED, file, 0);
238 if ((map != NULL) && (map != MAP_FAILED))
240 for (i = 0; i < mapsize; i += entrysize)
242 e = (struct traffic_entry *) &map[i];
247 printf("[ %" PRIu64 ", %" PRIu64 ", %" PRIu64
248 ", %" PRIu64 ", %" PRIu64 " ]%s\n",
250 ntohll(e->rxb), ntohll(e->rxp),
251 ntohll(e->txb), ntohll(e->txp),
252 ((i + entrysize) < mapsize) ? "," : "");
255 munmap(map, mapsize);
263 fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
270 int main(int argc, char *argv[])
278 while ((opt = getopt(argc, argv, "dfp:")) > -1)
301 return run_daemon(nofork);
303 else if (dprint && ifname)
304 return run_dump(ifname);