2013-02-12 07:56:55

by Bing Zhao

[permalink] [raw]
Subject: [PATCH] nl80211: minor correction in sample wowlan mask calculation

From: Amitkumar Karwar <[email protected]>

The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where xx indicates
"don't care") should be represented by a pattern of twelve zero
bytes, and a mask of "0xed,0x01", not "0xed,0x07".

mask_len = (pat_len + 7) / 8 = (12 + 7) / 8 = 2
Hence the mask will be of 2 bytes.
Replace each valid byte in pattern by 1 and don't care byte by 0:
10110111 1000 (0000)

1st byte of pattern corresponds to lower order bit in first byte
of mask. And 9th byte of pattern corresponds to lower order bit
in second byte of mask. With this logic the mask will be
11101101 00000001 = 0xed 0x01

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
include/uapi/linux/nl80211.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9a2ecdc..b233211 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2906,7 +2906,7 @@ enum nl80211_tx_power_setting {
* corresponds to the lowest-order bit in the second byte of the mask.
* For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where
* xx indicates "don't care") would be represented by a pattern of
- * twelve zero bytes, and a mask of "0xed,0x07".
+ * twelve zero bytes, and a mask of "0xed,0x01".
* Note that the pattern matching is done as though frames were not
* 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
* first (including SNAP header unpacking) and then matched.
--
1.8.0



2013-02-12 09:04:00

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] nl80211: minor correction in sample wowlan mask calculation

On Mon, 2013-02-11 at 23:56 -0800, Bing Zhao wrote:
> From: Amitkumar Karwar <[email protected]>
>
> The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where xx indicates
> "don't care") should be represented by a pattern of twelve zero
> bytes, and a mask of "0xed,0x01", not "0xed,0x07".
>
> mask_len = (pat_len + 7) / 8 = (12 + 7) / 8 = 2
> Hence the mask will be of 2 bytes.
> Replace each valid byte in pattern by 1 and don't care byte by 0:
> 10110111 1000 (0000)
>
> 1st byte of pattern corresponds to lower order bit in first byte
> of mask. And 9th byte of pattern corresponds to lower order bit
> in second byte of mask. With this logic the mask will be
> 11101101 00000001 = 0xed 0x01

Yep, clearly I got that wrong, thanks! Applied.

johannes


2013-02-12 07:57:03

by Bing Zhao

[permalink] [raw]
Subject: [PATCH] iw: add packet offset information for wowlan pattern

From: Amitkumar Karwar <[email protected]>

Now user can provide packet offset along with the pattern in
"iw wowlan" command. Default offset will be 0 when it is not
provided.

A trailing ':' should be used for single byte pattern to
distinguish it from an offset.
Ex. "iw phy phy# wowlan patterns 18 43:" means wakeup on
offset 18 pattern 0x43.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
util.c | 2 ++
wowlan.c | 30 +++++++++++++++++++++++-------
2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/util.c b/util.c
index c272c1d..6ef86cd 100644
--- a/util.c
+++ b/util.c
@@ -75,6 +75,8 @@ int parse_hex_mask(char *hexmask, unsigned char **result, size_t *result_len,
if (cp) {
*cp = 0;
cp++;
+ } else if (!strlen(hexmask)) {
+ break;
}

if (result_mask && (strcmp(hexmask, "-") == 0 ||
diff --git a/wowlan.c b/wowlan.c
index 6d324ef..a314c7d 100644
--- a/wowlan.c
+++ b/wowlan.c
@@ -26,7 +26,8 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
int err = -ENOBUFS;
unsigned char *pat, *mask;
size_t patlen;
- int patnum = 0;
+ int patnum = 0, pkt_offset;
+ char *eptr;

wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
if (!wowlan)
@@ -62,7 +63,16 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
}
break;
case PS_PAT:
- if (parse_hex_mask(argv[0], &pat, &patlen, &mask)) {
+ pkt_offset = strtoul(argv[0], &eptr, 10);
+ if (eptr != argv[0] + strlen(argv[0])) {
+ /* packet offset is not provided, set default value to 0 */
+ pkt_offset = 0;
+ } else {
+ argv++;
+ argc--;
+ }
+
+ if (!argc || parse_hex_mask(argv[0], &pat, &patlen, &mask)) {
err = 1;
goto nla_put_failure;
}
@@ -71,6 +81,7 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
DIV_ROUND_UP(patlen, 8), mask);
NLA_PUT(patterns, NL80211_WOWLAN_PKTPAT_PATTERN,
patlen, pat);
+ NLA_PUT_U32(patterns, NL80211_WOWLAN_PKTPAT_OFFSET, pkt_offset);
nla_nest_end(patterns, pattern);
free(mask);
free(pat);
@@ -91,12 +102,14 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb,
return err;
}
COMMAND(wowlan, enable, "[any] [disconnect] [magic-packet] [gtk-rekey-failure] [eap-identity-request]"
- " [4way-handshake] [rfkill-release] [patterns <pattern>*]",
+ " [4way-handshake] [rfkill-release] [patterns [offset1] <pattern1> ...]",
NL80211_CMD_SET_WOWLAN, 0, CIB_PHY, handle_wowlan_enable,
"Enable WoWLAN with the given triggers.\n"
"Each pattern is given as a bytestring with '-' in places where any byte\n"
"may be present, e.g. 00:11:22:-:44 will match 00:11:22:33:44 and\n"
- "00:11:22:33:ff:44 etc.");
+ "00:11:22:33:ff:44 etc.\n"
+ "Use ':' for single byte pattern as well, e.g. 18 43: will match '43' "
+ "after 18 bytes of offset in Rx packet.");


static int handle_wowlan_disable(struct nl80211_state *state, struct nl_cb *cb,
@@ -152,23 +165,26 @@ static int print_wowlan_handler(struct nl_msg *msg, void *arg)
trig[NL80211_WOWLAN_TRIG_PKT_PATTERN],
rem_pattern) {
struct nlattr *patattr[NUM_NL80211_WOWLAN_PKTPAT];
- int i, patlen, masklen;
+ int i, patlen, masklen, pkt_offset;
uint8_t *mask, *pat;
nla_parse(patattr, MAX_NL80211_WOWLAN_PKTPAT,
nla_data(pattern), nla_len(pattern),
NULL);
if (!patattr[NL80211_WOWLAN_PKTPAT_MASK] ||
- !patattr[NL80211_WOWLAN_PKTPAT_PATTERN]) {
+ !patattr[NL80211_WOWLAN_PKTPAT_PATTERN] ||
+ !patattr[NL80211_WOWLAN_PKTPAT_OFFSET]) {
printf(" * (invalid pattern specification)\n");
continue;
}
masklen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
patlen = nla_len(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
+ pkt_offset = nla_get_u32(patattr[NL80211_WOWLAN_PKTPAT_OFFSET]);
if (DIV_ROUND_UP(patlen, 8) != masklen) {
printf(" * (invalid pattern specification)\n");
continue;
}
- printf(" * wake up on pattern: ");
+ printf(" * wake up on packet offset: %d", pkt_offset);
+ printf(" pattern: ");
pat = nla_data(patattr[NL80211_WOWLAN_PKTPAT_PATTERN]);
mask = nla_data(patattr[NL80211_WOWLAN_PKTPAT_MASK]);
for (i = 0; i < patlen; i++) {
--
1.8.0


2013-02-12 20:26:41

by Bing Zhao

[permalink] [raw]
Subject: RE: [PATCH] nl80211: add packet offset information for wowlan pattern

SGkgSm9oYW5uZXMsDQoNCj4gT24gTW9uLCAyMDEzLTAyLTExIGF0IDIzOjU2IC0wODAwLCBCaW5n
IFpoYW8gd3JvdGU6DQo+ID4gRnJvbTogQW1pdGt1bWFyIEthcndhciA8YWthcndhckBtYXJ2ZWxs
LmNvbT4NCj4gPg0KPiA+IElmIHVzZXIga25vd3MgdGhlIGxvY2F0aW9uIG9mIGEgd293bGFuIHBh
dHRlcm4gdG8gYmUgbWF0Y2hlZCBpbg0KPiA+IFJ4IHBhY2tldCwgaGUgY2FuIHByb3ZpZGUgYW4g
b2Zmc2V0IHdpdGggdGhlIHBhdHRlcm4uIFRoaXMgd2lsbA0KPiA+IGhlbHAgZHJpdmVycyB0byBp
Z25vcmUgaW5pdGlhbCBieXRlcyBhbmQgbWF0Y2ggdGhlIHBhdHRlcm4NCj4gPiBlZmZpY2llbnRs
eS4NCj4gDQo+IFRoaXMgaXMgYSBiaXQgdHJpY2t5LiBSaWdodCBub3csIHRoZSBkb2N1bWVudGF0
aW9uIHNheXM6DQo+IA0KPiAgKiBATkw4MDIxMV9XT1dMQU5fVFJJR19QS1RfUEFUVEVSTjogd2Fr
ZSB1cCBvbiB0aGUgc3BlY2lmaWVkIHBhY2tldCBwYXR0ZXJucw0KPiAgKiAgICAgIHdoaWNoIGFy
ZSBwYXNzZWQgaW4gYW4gYXJyYXkgb2YgbmVzdGVkIGF0dHJpYnV0ZXMsIGVhY2ggbmVzdGVkIGF0
dHJpYnV0ZQ0KPiAgKiAgICAgIGRlZmluaW5nIGEgd2l0aCBhdHRyaWJ1dGVzIGZyb20gJnN0cnVj
dCBubDgwMjExX3dvd2xhbl90cmlnX3BrdF9wYXR0ZXJuLg0KPiAgKiAgICAgIEVhY2ggcGF0dGVy
biBkZWZpbmVzIGEgd2FrZXVwIHBhY2tldC4gVGhlIG1hdGNoaW5nIGlzIGRvbmUgb24gdGhlIE1T
RFUsDQo+ICAqICAgICAgaS5lLiBhcyB0aG91Z2ggdGhlIHBhY2tldCB3YXMgYW4gODAyLjMgcGFj
a2V0LCBzbyB0aGUgcGF0dGVybiBtYXRjaGluZw0KPiAgKiAgICAgIGlzIGRvbmUgYWZ0ZXIgdGhl
IHBhY2tldCBpcyBjb252ZXJ0ZWQgdG8gdGhlIE1TRFUuDQo+IA0KPiBJIGRvbid0IG1pbmQgYWRk
aW5nIHRoZSBvZmZzZXQsIGJ1dCBub3QgYWxsIGRldmljZXMgd2lsbCBzdXBwb3J0IHRoYXQNCj4g
KG91cnMgZG9lc24ndCkgc28gd2hlbiBhZHZlcnRpc2luZyB0aGUgZmVhdHVyZSBpdCBuZWVkcyB0
byBiZSBkb2N1bWVudGVkDQo+IHRvIGJlIHNvbWV0aGluZyBsaWtlIHRoZSBtYXhpbXVtIHBvc3Np
YmxlIG9mZnNldD8gU28geW91IGFsc28gbmVlZCB0bw0KPiBtb2RpZnkgdGhlIGRvY3VtZW50YXRp
b24gZm9yIHRoYXQgYW5kIHRoZSBjb2RlIGluIG5sODAyMTFfc2VuZF93aXBoeSgpLg0KPiANCj4g
PiBAQCAtNzA3MCw3ICs3MDczLDggQEAgc3RhdGljIGludCBubDgwMjExX3NldF93b3dsYW4oc3Ry
dWN0IHNrX2J1ZmYgKnNrYiwgc3RydWN0IGdlbmxfaW5mbyAqaW5mbykNCj4gPiAgCQkJCSAgbmxh
X2RhdGEocGF0KSwgbmxhX2xlbihwYXQpLCBOVUxMKTsNCj4gPiAgCQkJZXJyID0gLUVJTlZBTDsN
Cj4gPiAgCQkJaWYgKCFwYXRfdGJbTkw4MDIxMV9XT1dMQU5fUEtUUEFUX01BU0tdIHx8DQo+ID4g
LQkJCSAgICAhcGF0X3RiW05MODAyMTFfV09XTEFOX1BLVFBBVF9QQVRURVJOXSkNCj4gPiArCQkJ
ICAgICFwYXRfdGJbTkw4MDIxMV9XT1dMQU5fUEtUUEFUX1BBVFRFUk5dIHx8DQo+ID4gKwkJCSAg
ICAhcGF0X3RiW05MODAyMTFfV09XTEFOX1BLVFBBVF9PRkZTRVRdKQ0KPiA+ICAJCQkJZ290byBl
cnJvcjsNCj4gDQo+IFlvdSBjYW4ndCBqdXN0IGJyZWFrIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkg
bGlrZSB0aGF0LCB0aGUgbmV3IGF0dHJpYnV0ZQ0KPiBtdXN0IGJlIG9wdGlvbmFsIGFuZCBhc3N1
bWVkIDAgaWYgaXQncyBub3QgcHJlc2VudC4NCj4gDQo+ID4gQEAgLTcwOTYsNiArNzEwMCw4IEBA
IHN0YXRpYyBpbnQgbmw4MDIxMV9zZXRfd293bGFuKHN0cnVjdCBza19idWZmICpza2IsIHN0cnVj
dCBnZW5sX2luZm8gKmluZm8pDQo+ID4gIAkJCW1lbWNweShuZXdfdHJpZ2dlcnMucGF0dGVybnNb
aV0ucGF0dGVybiwNCj4gPiAgCQkJICAgICAgIG5sYV9kYXRhKHBhdF90YltOTDgwMjExX1dPV0xB
Tl9QS1RQQVRfUEFUVEVSTl0pLA0KPiA+ICAJCQkgICAgICAgcGF0X2xlbik7DQo+ID4gKwkJCW5l
d190cmlnZ2Vycy5wYXR0ZXJuc1tpXS5wa3Rfb2Zmc2V0ID0gbmxhX2dldF91MzIoDQo+ID4gKwkJ
CQkJcGF0X3RiW05MODAyMTFfV09XTEFOX1BLVFBBVF9PRkZTRVRdKTsNCj4gDQo+IFNpbmNlIGFs
bCBleGlzdGluZyB1c2VycyBvZiB0aGUgQVBJIHdvdWxkIGlnbm9yZSB0aGUgcGt0X29mZnNldCwg
eW91DQo+IG11c3QgcmVqZWN0IHRoZSBjb25maWd1cmF0aW9uIGlmIHRoZSBvZmZzZXQgZXhjZWVk
cyB0aGUgbWF4aW11bQ0KPiBwZXJtaXNzaWJsZSBvZmZzZXQgdGhlIGRldmljZSBhZHZlcnRpc2Vz
IChleGlzdGluZyBvbmVzIHdvdWxkIGFkdmVydGlzZQ0KPiAwKQ0KDQpUaGFua3MgZm9yIHlvdXIg
Y29tbWVudHMuDQoNClRoZSByZXZpc2VkIHYyIHBhdGNoIGhhcyBiZWVuIHN1Ym1pdHRlZC4gUGxl
YXNlIHJldmlldy4NCg0KUmVnYXJkcywNCkJpbmcNCg==

2013-02-12 09:09:27

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] nl80211: add packet offset information for wowlan pattern

On Mon, 2013-02-11 at 23:56 -0800, Bing Zhao wrote:
> From: Amitkumar Karwar <[email protected]>
>
> If user knows the location of a wowlan pattern to be matched in
> Rx packet, he can provide an offset with the pattern. This will
> help drivers to ignore initial bytes and match the pattern
> efficiently.

This is a bit tricky. Right now, the documentation says:

* @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
* which are passed in an array of nested attributes, each nested attribute
* defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
* Each pattern defines a wakeup packet. The matching is done on the MSDU,
* i.e. as though the packet was an 802.3 packet, so the pattern matching
* is done after the packet is converted to the MSDU.

I don't mind adding the offset, but not all devices will support that
(ours doesn't) so when advertising the feature it needs to be documented
to be something like the maximum possible offset? So you also need to
modify the documentation for that and the code in nl80211_send_wiphy().

> @@ -7070,7 +7073,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
> nla_data(pat), nla_len(pat), NULL);
> err = -EINVAL;
> if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
> - !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
> + !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN] ||
> + !pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
> goto error;

You can't just break backward compatibility like that, the new attribute
must be optional and assumed 0 if it's not present.

> @@ -7096,6 +7100,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
> memcpy(new_triggers.patterns[i].pattern,
> nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
> pat_len);
> + new_triggers.patterns[i].pkt_offset = nla_get_u32(
> + pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);

Since all existing users of the API would ignore the pkt_offset, you
must reject the configuration if the offset exceeds the maximum
permissible offset the device advertises (existing ones would advertise
0)

johannes


2013-02-12 07:56:59

by Bing Zhao

[permalink] [raw]
Subject: [PATCH] nl80211: add packet offset information for wowlan pattern

From: Amitkumar Karwar <[email protected]>

If user knows the location of a wowlan pattern to be matched in
Rx packet, he can provide an offset with the pattern. This will
help drivers to ignore initial bytes and match the pattern
efficiently.

Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 3 +++
net/wireless/nl80211.c | 12 +++++++++---
3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 77686ca..a5b0ea3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1576,6 +1576,7 @@ struct cfg80211_pmksa {
* one bit per byte, in same format as nl80211
* @pattern: bytes to match where bitmask is 1
* @pattern_len: length of pattern (in bytes)
+ * @pkt_offset: packet offset (in bytes)
*
* Internal note: @mask and @pattern are allocated in one chunk of
* memory, free @mask only!
@@ -1583,6 +1584,7 @@ struct cfg80211_pmksa {
struct cfg80211_wowlan_trig_pkt_pattern {
u8 *mask, *pattern;
int pattern_len;
+ int pkt_offset;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b233211..14da5b3 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting {
* Note that the pattern matching is done as though frames were not
* 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
* first (including SNAP header unpacking) and then matched.
+ * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
+ * these fixed number of bytes of received packet
* @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
* @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
*/
@@ -2917,6 +2919,7 @@ enum nl80211_wowlan_packet_pattern_attr {
__NL80211_WOWLAN_PKTPAT_INVALID,
NL80211_WOWLAN_PKTPAT_MASK,
NL80211_WOWLAN_PKTPAT_PATTERN,
+ NL80211_WOWLAN_PKTPAT_OFFSET,

NUM_NL80211_WOWLAN_PKTPAT,
MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 93bc63e..c512596 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6953,8 +6953,11 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
DIV_ROUND_UP(pat_len, 8),
rdev->wowlan->patterns[i].mask) ||
nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
- pat_len,
- rdev->wowlan->patterns[i].pattern))
+ pat_len,
+ rdev->wowlan->patterns[i].pattern) ||
+ nla_put_u32(msg,
+ NL80211_WOWLAN_PKTPAT_OFFSET,
+ rdev->wowlan->patterns[i].pkt_offset))
goto nla_put_failure;
nla_nest_end(msg, nl_pat);
}
@@ -7070,7 +7073,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
nla_data(pat), nla_len(pat), NULL);
err = -EINVAL;
if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
- !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
+ !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN] ||
+ !pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
goto error;
pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
mask_len = DIV_ROUND_UP(pat_len, 8);
@@ -7096,6 +7100,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
memcpy(new_triggers.patterns[i].pattern,
nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
pat_len);
+ new_triggers.patterns[i].pkt_offset = nla_get_u32(
+ pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
i++;
}
}
--
1.8.0