6 #include <netlink/genl/genl.h>
7 #include <netlink/genl/family.h>
8 #include <netlink/genl/ctrl.h>
9 #include <netlink/msg.h>
10 #include <netlink/attr.h>
12 #include <arpa/inet.h>
19 static int handle_coalesce_enable(struct nl80211_state
*state
, struct nl_cb
*cb
,
20 struct nl_msg
*msg
, int argc
, char **argv
,
23 struct nlattr
*nl_rules
, *nl_rule
= NULL
, *nl_pats
, *nl_pat
;
24 unsigned char *pat
, *mask
;
26 int patnum
= 0, pkt_offset
, err
= 1;
27 char *eptr
, *value1
, *value2
, *sptr
= NULL
, *end
, buf
[16768];
28 enum nl80211_coalesce_condition condition
;
29 FILE *f
= fopen(argv
[0], "r");
34 } parse_state
= PS_DELAY
;
40 nl_rules
= nla_nest_start(msg
, NL80211_ATTR_COALESCE_RULE
);
47 if (!fgets(buf
, sizeof(buf
), f
))
50 eol
= strchr(buf
+ 5, '\r');
53 eol
= strchr(buf
+ 5, '\n');
57 switch (parse_state
) {
59 if (strncmp(buf
, "delay=", 6) == 0) {
60 char *delay
= buf
+ 6;
63 nl_rule
= nla_nest_start(msg
, rule_num
);
67 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_DELAY
,
68 strtoul(delay
, &end
, 10));
71 parse_state
= PS_CONDITION
;
77 if (strncmp(buf
, "condition=", 10) == 0) {
78 char *cond
= buf
+ 10;
80 condition
= strtoul(cond
, &end
, 10);
83 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_CONDITION
,
85 parse_state
= PS_PATTERNS
;
91 if (strncmp(buf
, "patterns=", 9) == 0) {
92 char *cur_pat
= buf
+ 9;
93 char *next_pat
= strchr(buf
+ 9, ',');
100 nl_pats
= nla_nest_start(msg
, NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
);
102 value1
= strtok_r(cur_pat
, "+", &sptr
);
103 value2
= strtok_r(NULL
, "+", &sptr
);
111 pkt_offset
= strtoul(value1
, &eptr
, 10);
112 if (eptr
!= value1
+ strlen(value1
))
116 if (parse_hex_mask(value2
, &pat
, &patlen
, &mask
))
119 nl_pat
= nla_nest_start(msg
, ++patnum
);
120 NLA_PUT(msg
, NL80211_PKTPAT_MASK
,
121 DIV_ROUND_UP(patlen
, 8), mask
);
122 NLA_PUT(msg
, NL80211_PKTPAT_PATTERN
, patlen
, pat
);
123 NLA_PUT_U32(msg
, NL80211_PKTPAT_OFFSET
,
125 nla_nest_end(msg
, nl_pat
);
132 next_pat
= strchr(cur_pat
, ',');
138 nla_nest_end(msg
, nl_pats
);
139 nla_nest_end(msg
, nl_rule
);
140 parse_state
= PS_DELAY
;
153 if (parse_state
== PS_DELAY
)
162 nla_nest_end(msg
, nl_rules
);
166 COMMAND(coalesce
, enable
, "<config-file>",
167 NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
, handle_coalesce_enable
,
168 "Enable coalesce with given configuration.\n"
169 "The configuration file contains coalesce rules:\n"
171 " condition=<condition>\n"
172 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
174 " condition=<condition>\n"
175 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
177 "delay: maximum coalescing delay in msec.\n"
178 "condition: 1/0 i.e. 'not match'/'match' the patterns\n"
179 "patterns: each pattern is given as a bytestring with '-' in\n"
180 "places where any byte may be present, e.g. 00:11:22:-:44 will\n"
181 "match 00:11:22:33:44 and 00:11:22:33:ff:44 etc. Offset and\n"
182 "pattern should be separated by '+', e.g. 18+43:34:00:12 will\n"
183 "match '43:34:00:12' after 18 bytes of offset in Rx packet.\n");
186 handle_coalesce_disable(struct nl80211_state
*state
, struct nl_cb
*cb
,
187 struct nl_msg
*msg
, int argc
, char **argv
,
190 /* just a set w/o coalesce attribute */
193 COMMAND(coalesce
, disable
, "", NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
,
194 handle_coalesce_disable
, "Disable coalesce.");
196 static int print_coalesce_handler(struct nl_msg
*msg
, void *arg
)
198 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
199 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
200 struct nlattr
*pattern
, *rule
;
201 int rem_pattern
, rem_rule
;
202 enum nl80211_coalesce_condition condition
;
205 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
206 genlmsg_attrlen(gnlh
, 0), NULL
);
208 if (!attrs
[NL80211_ATTR_COALESCE_RULE
]) {
209 printf("Coalesce is disabled.\n");
213 printf("Coalesce is enabled:\n");
215 nla_for_each_nested(rule
, attrs
[NL80211_ATTR_COALESCE_RULE
], rem_rule
) {
216 struct nlattr
*ruleattr
[NUM_NL80211_ATTR_COALESCE_RULE
];
218 nla_parse(ruleattr
, NL80211_ATTR_COALESCE_RULE_MAX
,
219 nla_data(rule
), nla_len(rule
), NULL
);
221 delay
= nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_DELAY
]);
223 nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_CONDITION
]);
225 printf("Rule - max coalescing delay: %dmsec condition:", delay
);
227 printf("not match\n");
231 if (ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
]) {
232 nla_for_each_nested(pattern
,
233 ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
],
235 struct nlattr
*patattr
[NUM_NL80211_PKTPAT
];
236 int i
, patlen
, masklen
, pkt_offset
;
239 nla_parse(patattr
, MAX_NL80211_PKTPAT
,
240 nla_data(pattern
), nla_len(pattern
),
242 if (!patattr
[NL80211_PKTPAT_MASK
] ||
243 !patattr
[NL80211_PKTPAT_PATTERN
] ||
244 !patattr
[NL80211_PKTPAT_OFFSET
]) {
245 printf(" * (invalid pattern specification)\n");
248 masklen
= nla_len(patattr
[NL80211_PKTPAT_MASK
]);
249 patlen
= nla_len(patattr
[NL80211_PKTPAT_PATTERN
]);
250 pkt_offset
= nla_get_u32(patattr
[NL80211_PKTPAT_OFFSET
]);
251 if (DIV_ROUND_UP(patlen
, 8) != masklen
) {
252 printf(" * (invalid pattern specification)\n");
255 printf(" * packet offset: %d", pkt_offset
);
256 printf(" pattern: ");
257 pat
= nla_data(patattr
[NL80211_PKTPAT_PATTERN
]);
258 mask
= nla_data(patattr
[NL80211_PKTPAT_MASK
]);
259 for (i
= 0; i
< patlen
; i
++) {
260 if (mask
[i
/ 8] & (1 << (i
% 8)))
261 printf("%.2x", pat
[i
]);
275 static int handle_coalesce_show(struct nl80211_state
*state
, struct nl_cb
*cb
,
276 struct nl_msg
*msg
, int argc
, char **argv
,
279 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
,
280 print_coalesce_handler
, NULL
);
284 COMMAND(coalesce
, show
, "", NL80211_CMD_GET_COALESCE
, 0, CIB_PHY
, handle_coalesce_show
,
285 "Show coalesce status.");