aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-25 14:31:42 -0500
committerJohannes Berg <johannes@sipsolutions.net>2009-11-25 14:31:42 -0500
commit1806a49845e48a3e5f5ffb33d549bdefa2c1190b (patch)
tree3bbc557bbb074288daefd3b2bb651576c74e6b6c
parenta2ae0f35f900008b7862a34eb9e1afec2c0cb592 (diff)
add mac80211 plugin
-rw-r--r--Makefile8
-rw-r--r--plugin_mac80211.c203
2 files changed, 210 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 7a6dd0a..c4b13b9 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ LIBS = -L. -lparsevent -ldl
9%.o: %.c 9%.o: %.c
10 $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ 10 $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@
11 11
12TARGETS = libparsevent.a trace-cmd plugin_hrtimer.so 12TARGETS = libparsevent.a trace-cmd plugin_hrtimer.so plugin_mac80211.so
13 13
14all: $(TARGETS) 14all: $(TARGETS)
15 15
@@ -41,6 +41,12 @@ plugin_hrtimer.o: plugin_hrtimer.c parse-events.h
41plugin_hrtimer.so: plugin_hrtimer.o 41plugin_hrtimer.so: plugin_hrtimer.o
42 $(CC) -shared -nostartfiles -o $@ $< 42 $(CC) -shared -nostartfiles -o $@ $<
43 43
44plugin_mac80211.o: plugin_mac80211.c parse-events.h
45 $(CC) -c $(CFLAGS) -fPIC -o $@ $<
46
47plugin_mac80211.so: plugin_mac80211.o
48 $(CC) -shared -nostartfiles -o $@ $<
49
44.PHONY: force 50.PHONY: force
45force: 51force:
46 52
diff --git a/plugin_mac80211.c b/plugin_mac80211.c
new file mode 100644
index 0000000..791bd63
--- /dev/null
+++ b/plugin_mac80211.c
@@ -0,0 +1,203 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "parse-events.h"
6
7#define INDENT 65
8
9/* return -1 (field not found/not valid number), 0 (ok), 1 (buffer full) */
10static int _print_field(struct trace_seq *s, const char *fmt,
11 struct event *event, const char *name, const void *data)
12{
13 struct format_field *f = pevent_find_field(event, name);
14 unsigned long long val;
15
16 if (!f)
17 return -1;
18
19 if (pevent_read_number_field(f, data, &val))
20 return -1;
21
22 return trace_seq_printf(s, fmt, val);
23}
24
25/* return 0 (ok), 1 (buffer full) */
26static void print_field(struct trace_seq *s, const char *fmt,
27 struct event *event, const char *name, const void *data)
28{
29 int ret = _print_field(s, fmt, event, name, data);
30
31 if (ret == -1)
32 trace_seq_printf(s, "NOTFOUND:%s", name);
33}
34
35static void print_string(struct trace_seq *s, struct event *event,
36 const char *name, const void *data)
37{
38 struct format_field *f = pevent_find_field(event, name);
39 int offset;
40 int length;
41
42 if (!f) {
43 trace_seq_printf(s, "NOTFOUND:%s", name);
44 return;
45 }
46
47 offset = f->offset;
48 length = f->size;
49
50 if (!strncmp(f->type, "__data_loc", 10)) {
51 unsigned long long v;
52 if (pevent_read_number_field(f, data, &v)) {
53 trace_seq_printf(s, "invalid_data_loc");
54 return;
55 }
56 offset = v & 0xffff;
57 length = v >> 16;
58 }
59
60 trace_seq_printf(s, "%.*s", length, (char *)data + offset);
61}
62
63struct value_name {
64 unsigned long long value;
65 const char *name;
66};
67
68static void _print_enum(struct trace_seq *s, struct event *event,
69 const char *name, const void *data,
70 const struct value_name *names, int n_names)
71{
72 struct format_field *f = pevent_find_field(event, name);
73 unsigned long long val;
74 int i;
75
76 if (!f) {
77 trace_seq_puts(s, "field-not-found");
78 return;
79 }
80
81 if (pevent_read_number_field(f, data, &val)) {
82 trace_seq_puts(s, "field-invalid");
83 return;
84 }
85
86 for (i = 0; i < n_names; i++) {
87 if (names[i].value == val) {
88 trace_seq_puts(s, names[i].name);
89 return;
90 }
91 }
92
93 trace_seq_printf(s, "%llu", val);
94}
95
96#define print_enum(s, ev, name, data, enums...) \
97 ({ static const struct value_name __n[] = { enums }; \
98 _print_enum(s, ev, name, data, __n, sizeof(__n)/sizeof(__n[0])); \
99 })
100
101static void _print_flag(struct trace_seq *s, struct event *event,
102 const char *name, const void *data,
103 const struct value_name *names, int n_names)
104{
105 struct format_field *f = pevent_find_field(event, name);
106 unsigned long long val;
107 int i, j, found, first = 1;
108
109 if (!f) {
110 trace_seq_puts(s, "field-not-found");
111 return;
112 }
113
114 if (pevent_read_number_field(f, data, &val)) {
115 trace_seq_puts(s, "field-invalid");
116 return;
117 }
118
119 for (i = 0; i < 64; i++) {
120 if (!(val & (1ULL<<i)))
121 continue;
122 if (!first)
123 trace_seq_putc(s, '|');
124 first = 0;
125
126 found = 0;
127 for (j = 0; j < n_names; j++) {
128 if (j == names[i].value) {
129 trace_seq_puts(s, names[i].name);
130 found = 1;
131 break;
132 }
133 }
134 if (!found)
135 trace_seq_printf(s, "b%d", i);
136 }
137}
138
139#define print_flag(s, ev, name, data, enums...) \
140 ({ static const struct value_name __n[] = { enums }; \
141 _print_flag(s, ev, name, data, __n, sizeof(__n)/sizeof(__n[0])); \
142 })
143
144#define SF(fn) _print_field(s, fn ":%d", event, fn, data)
145#define SFX(fn) _print_field(s, fn ":%#x", event, fn, data)
146#define SP() trace_seq_putc(s, ' ')
147
148static int drv_bss_info_changed(struct trace_seq *s, void *data, int size,
149 struct event *event)
150{
151 print_string(s, event, "wiphy_name", data);
152 trace_seq_printf(s, " vif:");
153 print_string(s, event, "vif_name", data);
154 print_field(s, "(%d)", event, "vif_type", data);
155
156 trace_seq_printf(s, "\n%*s", INDENT, "");
157 SF("assoc"); SP();
158 SF("aid"); SP();
159 SF("cts"); SP();
160 SF("shortpre"); SP();
161 SF("shortslot"); SP();
162 SF("dtimper"); SP();
163 trace_seq_printf(s, "\n%*s", INDENT, "");
164 SF("bcnint"); SP();
165 SFX("assoc_cap"); SP();
166 SFX("basic_rates"); SP();
167 SF("enable_beacon");
168 trace_seq_printf(s, "\n%*s", INDENT, "");
169 SF("ht_operation_mode");
170
171 return 0;
172}
173
174static int drv_config(struct trace_seq *s, void *data,
175 int size, struct event *event)
176{
177 print_string(s, event, "wiphy_name", data);
178 trace_seq_putc(s, ' ');
179 print_flag(s, event, "flags", data,
180 { 0, "MONITOR" },
181 { 1, "PS" },
182 { 2, "IDLE" });
183 print_field(s, " chan:%d/", event, "center_freq", data);
184 print_enum(s, event, "channel_type", data,
185 { 0, "noht" },
186 { 1, "ht20" },
187 { 2, "ht40-" },
188 { 3, "ht40+" });
189 trace_seq_putc(s, ' ');
190 SF("power_level");
191
192 return 0;
193}
194
195int PEVENT_PLUGIN_LOADER(void)
196{
197 pevent_register_event_handler(-1, "mac80211", "drv_bss_info_changed",
198 drv_bss_info_changed);
199 pevent_register_event_handler(-1, "mac80211", "drv_config",
200 drv_config);
201
202 return 0;
203}