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
,
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
);
49 if (!fgets(buf
, sizeof(buf
), f
))
52 eol
= strchr(buf
+ 5, '\r');
55 eol
= strchr(buf
+ 5, '\n');
59 switch (parse_state
) {
61 if (strncmp(buf
, "delay=", 6) == 0) {
62 char *delay
= buf
+ 6;
65 nl_rule
= nla_nest_start(msg
, rule_num
);
69 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_DELAY
,
70 strtoul(delay
, &end
, 10));
73 parse_state
= PS_CONDITION
;
79 if (strncmp(buf
, "condition=", 10) == 0) {
80 char *cond
= buf
+ 10;
82 condition
= strtoul(cond
, &end
, 10);
85 NLA_PUT_U32(msg
, NL80211_ATTR_COALESCE_RULE_CONDITION
,
87 parse_state
= PS_PATTERNS
;
93 if (strncmp(buf
, "patterns=", 9) == 0) {
94 char *cur_pat
= buf
+ 9;
95 char *next_pat
= strchr(buf
+ 9, ',');
102 nl_pats
= nla_nest_start(msg
, NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
);
104 value1
= strtok_r(cur_pat
, "+", &sptr
);
105 value2
= strtok_r(NULL
, "+", &sptr
);
113 pkt_offset
= strtoul(value1
, &eptr
, 10);
114 if (eptr
!= value1
+ strlen(value1
))
118 if (parse_hex_mask(value2
, &pat
, &patlen
, &mask
))
121 nl_pat
= nla_nest_start(msg
, ++patnum
);
122 NLA_PUT(msg
, NL80211_PKTPAT_MASK
,
123 DIV_ROUND_UP(patlen
, 8), mask
);
124 NLA_PUT(msg
, NL80211_PKTPAT_PATTERN
, patlen
, pat
);
125 NLA_PUT_U32(msg
, NL80211_PKTPAT_OFFSET
,
127 nla_nest_end(msg
, nl_pat
);
134 next_pat
= strchr(cur_pat
, ',');
140 nla_nest_end(msg
, nl_pats
);
141 nla_nest_end(msg
, nl_rule
);
142 parse_state
= PS_DELAY
;
155 if (parse_state
== PS_DELAY
)
164 nla_nest_end(msg
, nl_rules
);
168 COMMAND(coalesce
, enable
, "<config-file>",
169 NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
, handle_coalesce_enable
,
170 "Enable coalesce with given configuration.\n"
171 "The configuration file contains coalesce rules:\n"
173 " condition=<condition>\n"
174 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
176 " condition=<condition>\n"
177 " patterns=<[offset1+]<pattern1>,<[offset2+]<pattern2>,...>\n"
179 "delay: maximum coalescing delay in msec.\n"
180 "condition: 1/0 i.e. 'not match'/'match' the patterns\n"
181 "patterns: each pattern is given as a bytestring with '-' in\n"
182 "places where any byte may be present, e.g. 00:11:22:-:44 will\n"
183 "match 00:11:22:33:44 and 00:11:22:33:ff:44 etc. Offset and\n"
184 "pattern should be separated by '+', e.g. 18+43:34:00:12 will\n"
185 "match '43:34:00:12' after 18 bytes of offset in Rx packet.\n");
188 handle_coalesce_disable(struct nl80211_state
*state
,
189 struct nl_msg
*msg
, int argc
, char **argv
,
192 /* just a set w/o coalesce attribute */
195 COMMAND(coalesce
, disable
, "", NL80211_CMD_SET_COALESCE
, 0, CIB_PHY
,
196 handle_coalesce_disable
, "Disable coalesce.");
198 static int print_coalesce_handler(struct nl_msg
*msg
, void *arg
)
200 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
201 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
202 struct nlattr
*pattern
, *rule
;
203 int rem_pattern
, rem_rule
;
204 enum nl80211_coalesce_condition condition
;
207 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
208 genlmsg_attrlen(gnlh
, 0), NULL
);
210 if (!attrs
[NL80211_ATTR_COALESCE_RULE
]) {
211 printf("Coalesce is disabled.\n");
215 printf("Coalesce is enabled:\n");
217 nla_for_each_nested(rule
, attrs
[NL80211_ATTR_COALESCE_RULE
], rem_rule
) {
218 struct nlattr
*ruleattr
[NUM_NL80211_ATTR_COALESCE_RULE
];
220 nla_parse(ruleattr
, NL80211_ATTR_COALESCE_RULE_MAX
,
221 nla_data(rule
), nla_len(rule
), NULL
);
223 delay
= nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_DELAY
]);
225 nla_get_u32(ruleattr
[NL80211_ATTR_COALESCE_RULE_CONDITION
]);
227 printf("Rule - max coalescing delay: %dmsec condition:", delay
);
229 printf("not match\n");
233 if (ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
]) {
234 nla_for_each_nested(pattern
,
235 ruleattr
[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN
],
237 struct nlattr
*patattr
[NUM_NL80211_PKTPAT
];
238 int i
, patlen
, masklen
, pkt_offset
;
241 nla_parse(patattr
, MAX_NL80211_PKTPAT
,
242 nla_data(pattern
), nla_len(pattern
),
244 if (!patattr
[NL80211_PKTPAT_MASK
] ||
245 !patattr
[NL80211_PKTPAT_PATTERN
] ||
246 !patattr
[NL80211_PKTPAT_OFFSET
]) {
247 printf(" * (invalid pattern specification)\n");
250 masklen
= nla_len(patattr
[NL80211_PKTPAT_MASK
]);
251 patlen
= nla_len(patattr
[NL80211_PKTPAT_PATTERN
]);
252 pkt_offset
= nla_get_u32(patattr
[NL80211_PKTPAT_OFFSET
]);
253 if (DIV_ROUND_UP(patlen
, 8) != masklen
) {
254 printf(" * (invalid pattern specification)\n");
257 printf(" * packet offset: %d", pkt_offset
);
258 printf(" pattern: ");
259 pat
= nla_data(patattr
[NL80211_PKTPAT_PATTERN
]);
260 mask
= nla_data(patattr
[NL80211_PKTPAT_MASK
]);
261 for (i
= 0; i
< patlen
; i
++) {
262 if (mask
[i
/ 8] & (1 << (i
% 8)))
263 printf("%.2x", pat
[i
]);
277 static int handle_coalesce_show(struct nl80211_state
*state
,
278 struct nl_msg
*msg
, int argc
, char **argv
,
281 register_handler(print_coalesce_handler
, NULL
);
285 COMMAND(coalesce
, show
, "", NL80211_CMD_GET_COALESCE
, 0, CIB_PHY
, handle_coalesce_show
,
286 "Show coalesce status.");