Update stats files
[public/mirror.git] / mib-tc-stats.c
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <inttypes.h>
6 #include <libgen.h>
7 #include <netlink/route/class.h>
8 #include <netlink/route/link.h>
9 #include <netlink/cache-api.h>
10 #include <netlink/object.h>
11
12 static struct nl_cache *link_cache, *class_cache;
13 static struct rtnl_link *eth;
14 static int ifindex;
15
16 struct class_info {
17     char *name;
18     char *id;
19 };
20
21 struct class_info cogent_class = { "cogent", "01:02", };
22 struct class_info orion_class  = { "orion",  "01:03", };
23 struct class_info campus_class = { "campus", "01:04", };
24
25 static struct nl_handle *nl_handle;
26
27 void die(const char *message) {
28     fprintf(stderr, "fatal: %s\n", message);
29     exit(1);
30 }
31
32 static void match_obj(struct nl_object *obj, void *arg) {
33     struct nl_object *needle = *(struct nl_object **)arg;
34     struct nl_object **ret = (struct nl_object **)arg + 1;
35
36     if (!*ret && nl_object_identical(obj, needle)) {
37         nl_object_get(obj);
38         *ret = obj;
39     }
40 }
41
42 static struct rtnl_class *get_class_by_id(char *id, int ifindex) {
43     uint32_t handle;
44     struct rtnl_class *needle;
45     struct nl_object *magic[2];
46
47     if (rtnl_tc_str2handle(id, &handle))
48         die("invalid id");
49
50     needle = rtnl_class_alloc();
51     rtnl_class_set_ifindex(needle, ifindex);
52     rtnl_class_set_handle(needle, handle);
53
54     magic[0] = (struct nl_object *)needle;
55     magic[1] = (struct nl_object *)NULL;
56
57     nl_cache_foreach(class_cache, match_obj, magic);
58
59     rtnl_class_put(needle);
60     return (struct rtnl_class *)magic[1];
61 }
62
63 uint64_t get_class_byte_count(struct class_info *info) {
64     struct rtnl_class *class = get_class_by_id(info->id, ifindex);
65     uint64_t bytes;
66     if (!class)
67         die("class not found");
68     bytes = rtnl_class_get_stat(class, RTNL_TC_BYTES);
69     rtnl_class_put(class);
70     return bytes;
71 }
72
73 void mirror_stats_refresh(void) {
74     nl_cache_refill(nl_handle, class_cache);
75 }
76
77 void mirror_stats_initialize(void) {
78     nl_handle = nl_handle_alloc();
79     if (!nl_handle)
80         die("unable to allocate handle");
81
82     if (nl_connect(nl_handle, NETLINK_ROUTE) < 0)
83         die("unable to connect to netlink");
84
85     link_cache = rtnl_link_alloc_cache(nl_handle);
86     if (!link_cache)
87         die("unable to allocate link cache");
88
89     eth = rtnl_link_get_by_name(link_cache, "eth0");
90     if (!eth)
91         die("unable to acquire eth0");
92     ifindex = rtnl_link_get_ifindex(eth);
93
94     class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
95     if (!class_cache)
96         die("unable to allocate class cache");
97 }
98
99 void mirror_stats_cleanup(void) {
100     rtnl_link_put(eth);
101     nl_cache_free(class_cache);
102     nl_cache_free(link_cache);
103     nl_close(nl_handle);
104     nl_handle_destroy(nl_handle);
105 }
106
107 int main(int argc, char *argv[]) {
108     mirror_stats_initialize();
109     for (;;) {
110         printf("%s %"PRIu64"\n", cogent_class.id, get_class_byte_count(&cogent_class));
111         printf("%s %"PRIu64"\n", orion_class.id, get_class_byte_count(&orion_class));
112         printf("%s %"PRIu64"\n", campus_class.id, get_class_byte_count(&campus_class));
113         sleep(1);
114         mirror_stats_refresh();
115     }
116 }