nl80211: add packet offset information for wowlan pattern
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 <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> [refactor pattern sending] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
66d5757051
commit
bb92d19983
@ -1576,6 +1576,7 @@ struct cfg80211_pmksa {
|
|||||||
* one bit per byte, in same format as nl80211
|
* one bit per byte, in same format as nl80211
|
||||||
* @pattern: bytes to match where bitmask is 1
|
* @pattern: bytes to match where bitmask is 1
|
||||||
* @pattern_len: length of pattern (in bytes)
|
* @pattern_len: length of pattern (in bytes)
|
||||||
|
* @pkt_offset: packet offset (in bytes)
|
||||||
*
|
*
|
||||||
* Internal note: @mask and @pattern are allocated in one chunk of
|
* Internal note: @mask and @pattern are allocated in one chunk of
|
||||||
* memory, free @mask only!
|
* memory, free @mask only!
|
||||||
@ -1583,6 +1584,7 @@ struct cfg80211_pmksa {
|
|||||||
struct cfg80211_wowlan_trig_pkt_pattern {
|
struct cfg80211_wowlan_trig_pkt_pattern {
|
||||||
u8 *mask, *pattern;
|
u8 *mask, *pattern;
|
||||||
int pattern_len;
|
int pattern_len;
|
||||||
|
int pkt_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2290,12 +2292,14 @@ enum wiphy_wowlan_support_flags {
|
|||||||
* (see nl80211.h for the pattern definition)
|
* (see nl80211.h for the pattern definition)
|
||||||
* @pattern_max_len: maximum length of each pattern
|
* @pattern_max_len: maximum length of each pattern
|
||||||
* @pattern_min_len: minimum length of each pattern
|
* @pattern_min_len: minimum length of each pattern
|
||||||
|
* @max_pkt_offset: maximum Rx packet offset
|
||||||
*/
|
*/
|
||||||
struct wiphy_wowlan_support {
|
struct wiphy_wowlan_support {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
int n_patterns;
|
int n_patterns;
|
||||||
int pattern_max_len;
|
int pattern_max_len;
|
||||||
int pattern_min_len;
|
int pattern_min_len;
|
||||||
|
int max_pkt_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting {
|
|||||||
* Note that the pattern matching is done as though frames were not
|
* 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
|
* 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
|
||||||
* first (including SNAP header unpacking) and then matched.
|
* 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
|
* @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
|
||||||
* @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
|
* @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
|
||||||
*/
|
*/
|
||||||
@ -2917,6 +2919,7 @@ enum nl80211_wowlan_packet_pattern_attr {
|
|||||||
__NL80211_WOWLAN_PKTPAT_INVALID,
|
__NL80211_WOWLAN_PKTPAT_INVALID,
|
||||||
NL80211_WOWLAN_PKTPAT_MASK,
|
NL80211_WOWLAN_PKTPAT_MASK,
|
||||||
NL80211_WOWLAN_PKTPAT_PATTERN,
|
NL80211_WOWLAN_PKTPAT_PATTERN,
|
||||||
|
NL80211_WOWLAN_PKTPAT_OFFSET,
|
||||||
|
|
||||||
NUM_NL80211_WOWLAN_PKTPAT,
|
NUM_NL80211_WOWLAN_PKTPAT,
|
||||||
MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
|
MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
|
||||||
@ -2927,6 +2930,7 @@ enum nl80211_wowlan_packet_pattern_attr {
|
|||||||
* @max_patterns: maximum number of patterns supported
|
* @max_patterns: maximum number of patterns supported
|
||||||
* @min_pattern_len: minimum length of each pattern
|
* @min_pattern_len: minimum length of each pattern
|
||||||
* @max_pattern_len: maximum length of each pattern
|
* @max_pattern_len: maximum length of each pattern
|
||||||
|
* @max_pkt_offset: maximum Rx packet offset
|
||||||
*
|
*
|
||||||
* This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
|
* This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
|
||||||
* that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
|
* that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
|
||||||
@ -2936,6 +2940,7 @@ struct nl80211_wowlan_pattern_support {
|
|||||||
__u32 max_patterns;
|
__u32 max_patterns;
|
||||||
__u32 min_pattern_len;
|
__u32 min_pattern_len;
|
||||||
__u32 max_pattern_len;
|
__u32 max_pattern_len;
|
||||||
|
__u32 max_pkt_offset;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2951,9 +2956,10 @@ struct nl80211_wowlan_pattern_support {
|
|||||||
* @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
|
* @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
|
||||||
* which are passed in an array of nested attributes, each nested attribute
|
* which are passed in an array of nested attributes, each nested attribute
|
||||||
* defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
|
* defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
|
||||||
* Each pattern defines a wakeup packet. The matching is done on the MSDU,
|
* Each pattern defines a wakeup packet. Packet offset is associated with
|
||||||
* i.e. as though the packet was an 802.3 packet, so the pattern matching
|
* each pattern which is used while matching the pattern. The matching is
|
||||||
* is done after the packet is converted to the MSDU.
|
* 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.
|
||||||
*
|
*
|
||||||
* In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
|
* In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
|
||||||
* carrying a &struct nl80211_wowlan_pattern_support.
|
* carrying a &struct nl80211_wowlan_pattern_support.
|
||||||
|
@ -1238,6 +1238,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
|
|||||||
dev->wiphy.wowlan.pattern_min_len,
|
dev->wiphy.wowlan.pattern_min_len,
|
||||||
.max_pattern_len =
|
.max_pattern_len =
|
||||||
dev->wiphy.wowlan.pattern_max_len,
|
dev->wiphy.wowlan.pattern_max_len,
|
||||||
|
.max_pkt_offset =
|
||||||
|
dev->wiphy.wowlan.max_pkt_offset,
|
||||||
};
|
};
|
||||||
if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
|
if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN,
|
||||||
sizeof(pat), &pat))
|
sizeof(pat), &pat))
|
||||||
@ -6895,6 +6897,39 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
|
||||||
|
struct cfg80211_registered_device *rdev)
|
||||||
|
{
|
||||||
|
struct nlattr *nl_pats, *nl_pat;
|
||||||
|
int i, pat_len;
|
||||||
|
|
||||||
|
if (!rdev->wowlan->n_patterns)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
|
||||||
|
if (!nl_pats)
|
||||||
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
for (i = 0; i < rdev->wowlan->n_patterns; i++) {
|
||||||
|
nl_pat = nla_nest_start(msg, i + 1);
|
||||||
|
if (!nl_pat)
|
||||||
|
return -ENOBUFS;
|
||||||
|
pat_len = rdev->wowlan->patterns[i].pattern_len;
|
||||||
|
if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
|
||||||
|
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) ||
|
||||||
|
nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
|
||||||
|
rdev->wowlan->patterns[i].pkt_offset))
|
||||||
|
return -ENOBUFS;
|
||||||
|
nla_nest_end(msg, nl_pat);
|
||||||
|
}
|
||||||
|
nla_nest_end(msg, nl_pats);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
@ -6935,32 +6970,8 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
(rdev->wowlan->rfkill_release &&
|
(rdev->wowlan->rfkill_release &&
|
||||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
|
nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if (rdev->wowlan->n_patterns) {
|
if (nl80211_send_wowlan_patterns(msg, rdev))
|
||||||
struct nlattr *nl_pats, *nl_pat;
|
goto nla_put_failure;
|
||||||
int i, pat_len;
|
|
||||||
|
|
||||||
nl_pats = nla_nest_start(msg,
|
|
||||||
NL80211_WOWLAN_TRIG_PKT_PATTERN);
|
|
||||||
if (!nl_pats)
|
|
||||||
goto nla_put_failure;
|
|
||||||
|
|
||||||
for (i = 0; i < rdev->wowlan->n_patterns; i++) {
|
|
||||||
nl_pat = nla_nest_start(msg, i + 1);
|
|
||||||
if (!nl_pat)
|
|
||||||
goto nla_put_failure;
|
|
||||||
pat_len = rdev->wowlan->patterns[i].pattern_len;
|
|
||||||
if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
|
|
||||||
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))
|
|
||||||
goto nla_put_failure;
|
|
||||||
nla_nest_end(msg, nl_pat);
|
|
||||||
}
|
|
||||||
nla_nest_end(msg, nl_pats);
|
|
||||||
}
|
|
||||||
|
|
||||||
nla_nest_end(msg, nl_wowlan);
|
nla_nest_end(msg, nl_wowlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7046,7 +7057,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
|
if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
|
||||||
struct nlattr *pat;
|
struct nlattr *pat;
|
||||||
int n_patterns = 0;
|
int n_patterns = 0;
|
||||||
int rem, pat_len, mask_len;
|
int rem, pat_len, mask_len, pkt_offset;
|
||||||
struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
|
struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
|
||||||
|
|
||||||
nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
|
nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
|
||||||
@ -7081,6 +7092,15 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||||||
pat_len < wowlan->pattern_min_len)
|
pat_len < wowlan->pattern_min_len)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
|
||||||
|
pkt_offset = 0;
|
||||||
|
else
|
||||||
|
pkt_offset = nla_get_u32(
|
||||||
|
pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
|
||||||
|
if (pkt_offset > wowlan->max_pkt_offset)
|
||||||
|
goto error;
|
||||||
|
new_triggers.patterns[i].pkt_offset = pkt_offset;
|
||||||
|
|
||||||
new_triggers.patterns[i].mask =
|
new_triggers.patterns[i].mask =
|
||||||
kmalloc(mask_len + pat_len, GFP_KERNEL);
|
kmalloc(mask_len + pat_len, GFP_KERNEL);
|
||||||
if (!new_triggers.patterns[i].mask) {
|
if (!new_triggers.patterns[i].mask) {
|
||||||
|
Reference in New Issue
Block a user