diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2013-02-12 15:16:26 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-13 04:09:48 -0500 |
commit | bb92d19983a4b54be3e3b83441a8076d92cd04bc (patch) | |
tree | e53601fab3727ec69137d67729fdf73414182aba | |
parent | 66d575705154525c33ab99b5f9ac2d246c348db6 (diff) |
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>
-rw-r--r-- | include/net/cfg80211.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 74 |
3 files changed, 60 insertions, 30 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 77686ca28948..d3a73818e44c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1576,6 +1576,7 @@ struct cfg80211_pmksa { | |||
1576 | * one bit per byte, in same format as nl80211 | 1576 | * one bit per byte, in same format as nl80211 |
1577 | * @pattern: bytes to match where bitmask is 1 | 1577 | * @pattern: bytes to match where bitmask is 1 |
1578 | * @pattern_len: length of pattern (in bytes) | 1578 | * @pattern_len: length of pattern (in bytes) |
1579 | * @pkt_offset: packet offset (in bytes) | ||
1579 | * | 1580 | * |
1580 | * Internal note: @mask and @pattern are allocated in one chunk of | 1581 | * Internal note: @mask and @pattern are allocated in one chunk of |
1581 | * memory, free @mask only! | 1582 | * memory, free @mask only! |
@@ -1583,6 +1584,7 @@ struct cfg80211_pmksa { | |||
1583 | struct cfg80211_wowlan_trig_pkt_pattern { | 1584 | struct cfg80211_wowlan_trig_pkt_pattern { |
1584 | u8 *mask, *pattern; | 1585 | u8 *mask, *pattern; |
1585 | int pattern_len; | 1586 | int pattern_len; |
1587 | int pkt_offset; | ||
1586 | }; | 1588 | }; |
1587 | 1589 | ||
1588 | /** | 1590 | /** |
@@ -2290,12 +2292,14 @@ enum wiphy_wowlan_support_flags { | |||
2290 | * (see nl80211.h for the pattern definition) | 2292 | * (see nl80211.h for the pattern definition) |
2291 | * @pattern_max_len: maximum length of each pattern | 2293 | * @pattern_max_len: maximum length of each pattern |
2292 | * @pattern_min_len: minimum length of each pattern | 2294 | * @pattern_min_len: minimum length of each pattern |
2295 | * @max_pkt_offset: maximum Rx packet offset | ||
2293 | */ | 2296 | */ |
2294 | struct wiphy_wowlan_support { | 2297 | struct wiphy_wowlan_support { |
2295 | u32 flags; | 2298 | u32 flags; |
2296 | int n_patterns; | 2299 | int n_patterns; |
2297 | int pattern_max_len; | 2300 | int pattern_max_len; |
2298 | int pattern_min_len; | 2301 | int pattern_min_len; |
2302 | int max_pkt_offset; | ||
2299 | }; | 2303 | }; |
2300 | 2304 | ||
2301 | /** | 2305 | /** |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b23321154e8b..eb7b32247ec5 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -2910,6 +2910,8 @@ enum nl80211_tx_power_setting { | |||
2910 | * Note that the pattern matching is done as though frames were not | 2910 | * Note that the pattern matching is done as though frames were not |
2911 | * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked | 2911 | * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked |
2912 | * first (including SNAP header unpacking) and then matched. | 2912 | * first (including SNAP header unpacking) and then matched. |
2913 | * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after | ||
2914 | * these fixed number of bytes of received packet | ||
2913 | * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes | 2915 | * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes |
2914 | * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number | 2916 | * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number |
2915 | */ | 2917 | */ |
@@ -2917,6 +2919,7 @@ enum nl80211_wowlan_packet_pattern_attr { | |||
2917 | __NL80211_WOWLAN_PKTPAT_INVALID, | 2919 | __NL80211_WOWLAN_PKTPAT_INVALID, |
2918 | NL80211_WOWLAN_PKTPAT_MASK, | 2920 | NL80211_WOWLAN_PKTPAT_MASK, |
2919 | NL80211_WOWLAN_PKTPAT_PATTERN, | 2921 | NL80211_WOWLAN_PKTPAT_PATTERN, |
2922 | NL80211_WOWLAN_PKTPAT_OFFSET, | ||
2920 | 2923 | ||
2921 | NUM_NL80211_WOWLAN_PKTPAT, | 2924 | NUM_NL80211_WOWLAN_PKTPAT, |
2922 | MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, | 2925 | MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, |
@@ -2927,6 +2930,7 @@ enum nl80211_wowlan_packet_pattern_attr { | |||
2927 | * @max_patterns: maximum number of patterns supported | 2930 | * @max_patterns: maximum number of patterns supported |
2928 | * @min_pattern_len: minimum length of each pattern | 2931 | * @min_pattern_len: minimum length of each pattern |
2929 | * @max_pattern_len: maximum length of each pattern | 2932 | * @max_pattern_len: maximum length of each pattern |
2933 | * @max_pkt_offset: maximum Rx packet offset | ||
2930 | * | 2934 | * |
2931 | * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when | 2935 | * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when |
2932 | * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the | 2936 | * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the |
@@ -2936,6 +2940,7 @@ struct nl80211_wowlan_pattern_support { | |||
2936 | __u32 max_patterns; | 2940 | __u32 max_patterns; |
2937 | __u32 min_pattern_len; | 2941 | __u32 min_pattern_len; |
2938 | __u32 max_pattern_len; | 2942 | __u32 max_pattern_len; |
2943 | __u32 max_pkt_offset; | ||
2939 | } __attribute__((packed)); | 2944 | } __attribute__((packed)); |
2940 | 2945 | ||
2941 | /** | 2946 | /** |
@@ -2951,9 +2956,10 @@ struct nl80211_wowlan_pattern_support { | |||
2951 | * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns | 2956 | * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns |
2952 | * which are passed in an array of nested attributes, each nested attribute | 2957 | * which are passed in an array of nested attributes, each nested attribute |
2953 | * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. | 2958 | * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. |
2954 | * Each pattern defines a wakeup packet. The matching is done on the MSDU, | 2959 | * Each pattern defines a wakeup packet. Packet offset is associated with |
2955 | * i.e. as though the packet was an 802.3 packet, so the pattern matching | 2960 | * each pattern which is used while matching the pattern. The matching is |
2956 | * is done after the packet is converted to the MSDU. | 2961 | * done on the MSDU, i.e. as though the packet was an 802.3 packet, so the |
2962 | * pattern matching is done after the packet is converted to the MSDU. | ||
2957 | * | 2963 | * |
2958 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute | 2964 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute |
2959 | * carrying a &struct nl80211_wowlan_pattern_support. | 2965 | * carrying a &struct nl80211_wowlan_pattern_support. |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 93bc63eae076..cc0fad30b8c9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1238,6 +1238,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1238 | dev->wiphy.wowlan.pattern_min_len, | 1238 | dev->wiphy.wowlan.pattern_min_len, |
1239 | .max_pattern_len = | 1239 | .max_pattern_len = |
1240 | dev->wiphy.wowlan.pattern_max_len, | 1240 | dev->wiphy.wowlan.pattern_max_len, |
1241 | .max_pkt_offset = | ||
1242 | dev->wiphy.wowlan.max_pkt_offset, | ||
1241 | }; | 1243 | }; |
1242 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | 1244 | if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, |
1243 | sizeof(pat), &pat)) | 1245 | sizeof(pat), &pat)) |
@@ -6895,6 +6897,39 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6895 | } | 6897 | } |
6896 | 6898 | ||
6897 | #ifdef CONFIG_PM | 6899 | #ifdef CONFIG_PM |
6900 | static int nl80211_send_wowlan_patterns(struct sk_buff *msg, | ||
6901 | struct cfg80211_registered_device *rdev) | ||
6902 | { | ||
6903 | struct nlattr *nl_pats, *nl_pat; | ||
6904 | int i, pat_len; | ||
6905 | |||
6906 | if (!rdev->wowlan->n_patterns) | ||
6907 | return 0; | ||
6908 | |||
6909 | nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); | ||
6910 | if (!nl_pats) | ||
6911 | return -ENOBUFS; | ||
6912 | |||
6913 | for (i = 0; i < rdev->wowlan->n_patterns; i++) { | ||
6914 | nl_pat = nla_nest_start(msg, i + 1); | ||
6915 | if (!nl_pat) | ||
6916 | return -ENOBUFS; | ||
6917 | pat_len = rdev->wowlan->patterns[i].pattern_len; | ||
6918 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | ||
6919 | DIV_ROUND_UP(pat_len, 8), | ||
6920 | rdev->wowlan->patterns[i].mask) || | ||
6921 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | ||
6922 | pat_len, rdev->wowlan->patterns[i].pattern) || | ||
6923 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, | ||
6924 | rdev->wowlan->patterns[i].pkt_offset)) | ||
6925 | return -ENOBUFS; | ||
6926 | nla_nest_end(msg, nl_pat); | ||
6927 | } | ||
6928 | nla_nest_end(msg, nl_pats); | ||
6929 | |||
6930 | return 0; | ||
6931 | } | ||
6932 | |||
6898 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | 6933 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) |
6899 | { | 6934 | { |
6900 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6935 | 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) | |||
6935 | (rdev->wowlan->rfkill_release && | 6970 | (rdev->wowlan->rfkill_release && |
6936 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 6971 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) |
6937 | goto nla_put_failure; | 6972 | goto nla_put_failure; |
6938 | if (rdev->wowlan->n_patterns) { | 6973 | if (nl80211_send_wowlan_patterns(msg, rdev)) |
6939 | struct nlattr *nl_pats, *nl_pat; | 6974 | goto nla_put_failure; |
6940 | int i, pat_len; | ||
6941 | |||
6942 | nl_pats = nla_nest_start(msg, | ||
6943 | NL80211_WOWLAN_TRIG_PKT_PATTERN); | ||
6944 | if (!nl_pats) | ||
6945 | goto nla_put_failure; | ||
6946 | |||
6947 | for (i = 0; i < rdev->wowlan->n_patterns; i++) { | ||
6948 | nl_pat = nla_nest_start(msg, i + 1); | ||
6949 | if (!nl_pat) | ||
6950 | goto nla_put_failure; | ||
6951 | pat_len = rdev->wowlan->patterns[i].pattern_len; | ||
6952 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | ||
6953 | DIV_ROUND_UP(pat_len, 8), | ||
6954 | rdev->wowlan->patterns[i].mask) || | ||
6955 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | ||
6956 | pat_len, | ||
6957 | rdev->wowlan->patterns[i].pattern)) | ||
6958 | goto nla_put_failure; | ||
6959 | nla_nest_end(msg, nl_pat); | ||
6960 | } | ||
6961 | nla_nest_end(msg, nl_pats); | ||
6962 | } | ||
6963 | |||
6964 | nla_nest_end(msg, nl_wowlan); | 6975 | nla_nest_end(msg, nl_wowlan); |
6965 | } | 6976 | } |
6966 | 6977 | ||
@@ -7046,7 +7057,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7046 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { | 7057 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { |
7047 | struct nlattr *pat; | 7058 | struct nlattr *pat; |
7048 | int n_patterns = 0; | 7059 | int n_patterns = 0; |
7049 | int rem, pat_len, mask_len; | 7060 | int rem, pat_len, mask_len, pkt_offset; |
7050 | struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; | 7061 | struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; |
7051 | 7062 | ||
7052 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | 7063 | 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) | |||
7081 | pat_len < wowlan->pattern_min_len) | 7092 | pat_len < wowlan->pattern_min_len) |
7082 | goto error; | 7093 | goto error; |
7083 | 7094 | ||
7095 | if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]) | ||
7096 | pkt_offset = 0; | ||
7097 | else | ||
7098 | pkt_offset = nla_get_u32( | ||
7099 | pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]); | ||
7100 | if (pkt_offset > wowlan->max_pkt_offset) | ||
7101 | goto error; | ||
7102 | new_triggers.patterns[i].pkt_offset = pkt_offset; | ||
7103 | |||
7084 | new_triggers.patterns[i].mask = | 7104 | new_triggers.patterns[i].mask = |
7085 | kmalloc(mask_len + pat_len, GFP_KERNEL); | 7105 | kmalloc(mask_len + pat_len, GFP_KERNEL); |
7086 | if (!new_triggers.patterns[i].mask) { | 7106 | if (!new_triggers.patterns[i].mask) { |