summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Yingqiang Ma <yma.cool@gmail.com>2010-04-13 15:12:07 +0800
committerJohn W. Linville <linville@tuxdriver.com>2010-04-20 11:50:51 -0400
commit03ceedea972a82d343fa5c2528b3952fa9e615d5 (patch)
tree7b46f62e4fd82e969bc1cea1999249d25234e330 /drivers
parente8958330190c57c0d32bee88b64a12de2f58059f (diff)
ath9k: Group Key fix for VAPs
When I set up multiple VAPs with ath9k, I encountered an issue that the traffic may be lost after a while. The detailed phenomenon is 1. After a while the clients connected to one of these VAPs will get into a state that no broadcast/multicast packets can be transfered successfully while the unicast packets can be transfered normally. 2. Minutes latter the unitcast packets transfer will fail as well, because the ARP entry is expired and it can't be freshed due to the broadcast trouble. It's caused by the group key overwritten and someone discussed this issue in ath9k-devel maillist before, but haven't work out a fix yet. I referred the method in madwifi, and made a patch for ath9k. The method is to set the high bit of the sender(AP)'s address, and associated that mac and the group key. It requires the hardware supports multicast frame key search. It seems true for AR9160. Not sure whether it's the correct way to fix this issue. But it seems to work in my test. The patch is attached, feel free to revise it. Signed-off-by: Daniel Yingqiang ma <yma.cool@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1f4ea74bf4ca..40136cf63fa4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -751,6 +751,7 @@ static int ath_key_config(struct ath_common *common,
struct ath_hw *ah = common->ah;
struct ath9k_keyval hk;
const u8 *mac = NULL;
+ u8 gmac[ETH_ALEN];
int ret = 0;
int idx;
@@ -774,9 +775,30 @@ static int ath_key_config(struct ath_common *common,
memcpy(hk.kv_val, key->key, key->keylen);
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
- /* For now, use the default keys for broadcast keys. This may
- * need to change with virtual interfaces. */
- idx = key->keyidx;
+
+ if (key->ap_addr) {
+ /*
+ * Group keys on hardware that supports multicast frame
+ * key search use a mac that is the sender's address with
+ * the high bit set instead of the app-specified address.
+ */
+ memcpy(gmac, key->ap_addr, ETH_ALEN);
+ gmac[0] |= 0x80;
+ mac = gmac;
+
+ if (key->alg == ALG_TKIP)
+ idx = ath_reserve_key_cache_slot_tkip(common);
+ else
+ idx = ath_reserve_key_cache_slot(common);
+ if (idx < 0)
+ mac = NULL; /* no free key cache entries */
+ }
+
+ if (!mac) {
+ /* For now, use the default keys for broadcast keys. This may
+ * need to change with virtual interfaces. */
+ idx = key->keyidx;
+ }
} else if (key->keyidx) {
if (WARN_ON(!sta))
return -EOPNOTSUPP;