5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <netlink/msg.h>
9 #include <netlink/attr.h>
16 static int handle_coalesce_enable(struct nl80211_state
*state
,
17 struct nl_msg
*msg
, int argc
, char **argv
,
20 struct nlattr
*nl_rules
, *nl_rule
= NULL
, *nl_pats
, *nl_pat
;
21 unsigned char *pat
, *mask
;
23 int patnum
= 0, pkt_offset
, err
= 1;
24 char *eptr
, *value1
, *value2
, *sptr
= NULL
, *end
, buf
[16768];
25 enum nl80211_coalesce_condition condition
;
26 FILE *f
= fopen(argv
[0], "r");
31 } parse_state
= PS_DELAY
;
37 nl_rules
= nla_nest_start(msg
, NL80211_ATTR_COALESCE_RULE
);
46 if (!fgets(buf
, sizeof(buf
), f
))
49 eol
= strchr(buf
+ 5, '\r');
52 eol
= strchr(buf
+ 5, '\n');
56 switch (parse_state
) {
58 if (strncmp(buf
, "delay=", 6) == 0) {
59 char *delay
= buf
+ 6;
62 nl_rule
= nla_nest_start(msg
, rule_num
);
66 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_DELAY
,
67 strtoul(delay
, &end
, 10));
70 parse_state
= PS_CONDITION
;
76 if (strncmp(buf
, "condition=", 10) == 0) {
77 char *cond
= buf
+ 10;
79 condition
= strtoul(cond
, &end
, 10);
82 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_CONDITION
,
84 parse_state
= PS_PATTERNS
;
90 if (strncmp(buf
, "patterns=", 9) == 0) {
91 char *cur_pat
= buf
+ 9;
92 char *next_pat
= strchr(buf
+ 9, ',');
99 nl_pats
= nla_nest_start(msg
, NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
);
101 value1
= strtok_r(cur_pat
, "+", &sptr
);
102 value2
= strtok_r(NULL
, "+", &sptr
);
110 pkt_offset
= strtoul(value1
, &eptr
, 10);
111 if (eptr
!= value1
+ strlen(value1
))
115 if (parse_hex_mask(value2
, &pat
, &patlen
, &mask
))
118 nl_pat
= nla_nest_start(msg
, ++patnum
);
119 NLA_PUT(msg
, NL80211_PKTPAT_MASK
,
120 DIV_ROUND_UP(patlen
, 8), mask
);
121 NLA_PUT(msg
, NL80211_PKTPAT_PATTERN
, patlen
, pat
);
122 NLA_PUT_U32(msg
, NL80211_PKTPAT_OFFSET
,
124 nla_nest_end(msg
, nl_pat
);
131 next_pat
= strchr(cur_pat
, ',');
137 nla_nest_end(msg
, nl_pats
);
138 nla_nest_end(msg
, nl_rule
);
139 parse_state
= PS_DELAY
;
152 if (parse_state
== PS_DELAY
)
161 nla_nest_end(msg
, nl_rules
);
165 COMMAND(coalesce
, enable
, "<config-file>",
166 NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
, handle_coalesce_enable
,
167 "Enable coalesce with given configuration.\n"
168 "The configuration file contains coalesce rules:\n"
170 " condition=<condition>\n"
171 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
173 " condition=<condition>\n"
174 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
176 "delay: maximum coalescing delay in msec.\n"
177 "condition: 1/0 i.e. 'not match'/'match' the patterns\n"
178 "patterns: each pattern is given as a bytestring with '-' in\n"
179 "places where any byte may be present, e.g. 00:11:22:-:44 will\n"
180 "match 00:11:22:33:44 and 00:11:22:33:ff:44 etc. Offset and\n"
181 "pattern should be separated by '+', e.g. 18+43:34:00:12 will\n"
182 "match '43:34:00:12' after 18 bytes of offset in Rx packet.\n");
185 handle_coalesce_disable(struct nl80211_state
*state
,
186 struct nl_msg
*msg
, int argc
, char **argv
,
189 /* just a set w/o coalesce attribute */
192 COMMAND(coalesce
, disable
, "", NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
,
193 handle_coalesce_disable
, "Disable coalesce.");
195 static int print_coalesce_handler(struct nl_msg
*msg
, void *arg
)
197 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
198 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
199 struct nlattr
*pattern
, *rule
;
200 int rem_pattern
, rem_rule
;
201 enum nl80211_coalesce_condition condition
;
204 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
205 genlmsg_attrlen(gnlh
, 0), NULL
);
207 if (!attrs
[NL80211_ATTR_COALESCE_RULE
]) {
208 printf("Coalesce is disabled.\n");
212 printf("Coalesce is enabled:\n");
214 nla_for_each_nested(rule
, attrs
[NL80211_ATTR_COALESCE_RULE
], rem_rule
) {
215 struct nlattr
*ruleattr
[NUM_NL80211_ATTR_COALESCE_RULE
];
217 nla_parse(ruleattr
, NL80211_ATTR_COALESCE_RULE_MAX
,
218 nla_data(rule
), nla_len(rule
), NULL
);
220 delay
= nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_DELAY
]);
222 nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_CONDITION
]);
224 printf("Rule - max coalescing delay: %dmsec condition:", delay
);
226 printf("not match\n");
230 if (ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
]) {
231 nla_for_each_nested(pattern
,
232 ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
],
234 struct nlattr
*patattr
[NUM_NL80211_PKTPAT
];
235 int i
, patlen
, masklen
, pkt_offset
;
238 nla_parse(patattr
, MAX_NL80211_PKTPAT
,
239 nla_data(pattern
), nla_len(pattern
),
241 if (!patattr
[NL80211_PKTPAT_MASK
] ||
242 !patattr
[NL80211_PKTPAT_PATTERN
] ||
243 !patattr
[NL80211_PKTPAT_OFFSET
]) {
244 printf(" * (invalid pattern specification)\n");
247 masklen
= nla_len(patattr
[NL80211_PKTPAT_MASK
]);
248 patlen
= nla_len(patattr
[NL80211_PKTPAT_PATTERN
]);
249 pkt_offset
= nla_get_u32(patattr
[NL80211_PKTPAT_OFFSET
]);
250 if (DIV_ROUND_UP(patlen
, 8) != masklen
) {
251 printf(" * (invalid pattern specification)\n");
254 printf(" * packet offset: %d", pkt_offset
);
255 printf(" pattern: ");
256 pat
= nla_data(patattr
[NL80211_PKTPAT_PATTERN
]);
257 mask
= nla_data(patattr
[NL80211_PKTPAT_MASK
]);
258 for (i
= 0; i
< patlen
; i
++) {
259 if (mask
[i
/ 8] & (1 << (i
% 8)))
260 printf("%.2x", pat
[i
]);
274 static int handle_coalesce_show(struct nl80211_state
*state
,
275 struct nl_msg
*msg
, int argc
, char **argv
,
278 register_handler(print_coalesce_handler
, NULL
);
282 COMMAND(coalesce
, show
, "", NL80211_CMD_GET_COALESCE
, 0, CIB_PHY
, handle_coalesce_show
,
283 "Show coalesce status.");