Add clean
[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
10 static const char *mib_prefix = ".1.3.6.1.4.1.27934.2.2";
11 static char *prog;
12 static int found;
13
14 static struct mib {
15     char *mib_suffix;
16     char *name;
17     char *id;
18 } mibv[] = {
19     { "1", "default", "01:02" },
20     { "2", "orion", "01:03" },
21     { "3", "campus", "01:04" },
22 };
23
24 static int mibc = sizeof(mibv)/sizeof(*mibv);
25
26 static int mib_match(const char *arg, const char *mib_suffix) {
27     if (strlen(arg) < strlen(mib_prefix) + 1)
28         return 0;
29     if (strncmp(arg, mib_prefix, strlen(mib_prefix)))
30         return 0;
31     return !strcmp(arg + strlen(mib_prefix) + 1, mib_suffix);
32 }
33
34 static int mib_find(const char *arg) {
35     int i;
36     for (i = 0; i < mibc; i++) {
37         if (mib_match(arg, mibv[i].mib_suffix))
38                 return i;
39     }
40     return -1;
41 }
42
43 static struct nl_handle *nl_handle;
44
45 static void dump_class_stats(struct nl_object *obj, void *arg)
46 {
47     struct mib *mib = arg;
48     struct rtnl_class *class = (struct rtnl_class *)obj;
49     uint32_t handle = rtnl_class_get_handle(class);
50 //    uint64_t rate = rtnl_class_get_stat(class, RTNL_TC_RATE_BPS);
51     uint64_t bytes = rtnl_class_get_stat(class, RTNL_TC_BYTES);
52     char id[32];
53
54     rtnl_tc_handle2str(handle, id, sizeof(id));
55
56     if (strcmp(id, mib->id))
57         return;
58
59     fprintf(stdout, "%s.%s\ncounter\n%ld\n", mib_prefix, mib->mib_suffix, bytes);
60     found = 1;
61 }
62
63 void die(const char *message) {
64     fprintf(stderr, "fatal: %s\n", message);
65     exit(1);
66 }
67
68 static void usage(void) {
69     fprintf(stderr, "usage: %s [-g | -n] %s[.X]\n", prog, mib_prefix);
70     exit(2);
71 }
72
73 int main(int argc, char *argv[]) {
74     struct nl_cache *link_cache, *class_cache;
75     struct rtnl_link *eth;
76     int ifindex, mibindex;
77
78     prog = basename(argv[0]);
79
80     if (argc < 2)
81         usage();
82
83     mibindex = mib_find(argv[2]);
84
85     if (!strcmp(argv[1], "-n")) {
86         if (mibindex < 0) {
87             if (!strcmp(argv[2], mib_prefix))
88                 mibindex = 0;
89         } else if (mibindex == mibc - 1) {
90             exit(0);
91         } else {
92             mibindex++;
93         }
94     } else if (strcmp(argv[1], "-g")) {
95         usage();
96     }
97
98     if (mibindex < 0 || mibindex >= mibc)
99         die("invalid mib");
100
101     nl_handle = nl_handle_alloc();
102     if (!nl_handle)
103         die("unable to allocate handle");
104
105     if (nl_connect(nl_handle, NETLINK_ROUTE) < 0)
106         die("unable to connect to netlink");
107
108     link_cache = rtnl_link_alloc_cache(nl_handle);
109     if (!link_cache)
110         die("unable to allocate link cache");
111 //    nl_cache_mgmt_provide(link_cache);
112
113     eth = rtnl_link_get_by_name(link_cache, "eth0");
114     if (!eth)
115         die("unable to acquire eth0");
116     ifindex = rtnl_link_get_ifindex(eth);
117
118     class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
119     if (!class_cache)
120         die("unable to allocate class cache");
121
122     nl_cache_foreach(class_cache, dump_class_stats, &mibv[mibindex]);
123
124     if (!found)
125         die("class not found");
126
127     rtnl_link_put(eth);
128     nl_cache_free(class_cache);
129     nl_cache_free(link_cache);
130     nl_close(nl_handle);
131     nl_handle_destroy(nl_handle);
132     return 0;
133 }