diff options
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 124 |
1 files changed, 44 insertions, 80 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 7e91f30..ac99401 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -112,7 +112,8 @@ static void ath_fatal_proc(void *, int); static void ath_rxorn_proc(void *, int); static void ath_bmiss_proc(void *, int); static int ath_key_alloc(struct ieee80211com *, - const struct ieee80211_key *); + const struct ieee80211_key *, + ieee80211_keyix *, ieee80211_keyix *); static int ath_key_delete(struct ieee80211com *, const struct ieee80211_key *); static int ath_key_set(struct ieee80211com *, const struct ieee80211_key *, @@ -568,6 +569,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ic->ic_recv_mgmt = ath_recv_mgmt; sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = ath_newstate; + ic->ic_crypto.cs_max_keyix = sc->sc_keymax; ic->ic_crypto.cs_key_alloc = ath_key_alloc; ic->ic_crypto.cs_key_delete = ath_key_delete; ic->ic_crypto.cs_key_set = ath_key_set; @@ -1262,7 +1264,7 @@ ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, KASSERT(sc->sc_splitmic, ("key cache !split")); if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) { /* - * TX key goes at first index, RX key at +32. + * TX key goes at first index, RX key at the rx index. * The hal handles the MIC keys at index+64. */ memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic)); @@ -1357,7 +1359,8 @@ ath_keyset(struct ath_softc *sc, const struct ieee80211_key *k, * each key, one for decrypt/encrypt and the other for the MIC. */ static u_int16_t -key_alloc_2pair(struct ath_softc *sc) +key_alloc_2pair(struct ath_softc *sc, + ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) { #define N(a) (sizeof(a)/sizeof(a[0])) u_int i, keyix; @@ -1396,19 +1399,22 @@ key_alloc_2pair(struct ath_softc *sc) "%s: key pair %u,%u %u,%u\n", __func__, keyix, keyix+64, keyix+32, keyix+32+64); - return keyix; + *txkeyix = keyix; + *rxkeyix = keyix+32; + return 1; } } DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__); - return IEEE80211_KEYIX_NONE; + return 0; #undef N } /* * Allocate a single key cache slot. */ -static u_int16_t -key_alloc_single(struct ath_softc *sc) +static int +key_alloc_single(struct ath_softc *sc, + ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix) { #define N(a) (sizeof(a)/sizeof(a[0])) u_int i, keyix; @@ -1426,11 +1432,12 @@ key_alloc_single(struct ath_softc *sc) setbit(sc->sc_keymap, keyix); DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: key %u\n", __func__, keyix); - return keyix; + *txkeyix = *rxkeyix = keyix; + return 1; } } DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of space\n", __func__); - return IEEE80211_KEYIX_NONE; + return 0; #undef N } @@ -1444,7 +1451,8 @@ key_alloc_single(struct ath_softc *sc) * 64 entries. */ static int -ath_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k) +ath_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k, + ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) { struct ath_softc *sc = ic->ic_ifp->if_softc; @@ -1460,21 +1468,19 @@ ath_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k) * multi-station operation. */ if ((k->wk_flags & IEEE80211_KEY_GROUP) && !sc->sc_mcastkey) { - u_int keyix; - if (!(&ic->ic_nw_keys[0] <= k && k < &ic->ic_nw_keys[IEEE80211_WEP_NKID])) { /* should not happen */ DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: bogus group key\n", __func__); - return IEEE80211_KEYIX_NONE; + return 0; } - keyix = k - ic->ic_nw_keys; /* * XXX we pre-allocate the global keys so * have no way to check if they've already been allocated. */ - return keyix; + *keyix = *rxkeyix = k - ic->ic_nw_keys; + return 1; } /* @@ -1486,12 +1492,12 @@ ath_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k) * those requests to slot 0. */ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { - return key_alloc_single(sc); + return key_alloc_single(sc, keyix, rxkeyix); } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) { - return key_alloc_2pair(sc); + return key_alloc_2pair(sc, keyix, rxkeyix); } else { - return key_alloc_single(sc); + return key_alloc_single(sc, keyix, rxkeyix); } } @@ -1504,32 +1510,17 @@ ath_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k) struct ath_softc *sc = ic->ic_ifp->if_softc; struct ath_hal *ah = sc->sc_ah; const struct ieee80211_cipher *cip = k->wk_cipher; - struct ieee80211_node *ni; u_int keyix = k->wk_keyix; DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix); ath_hal_keyreset(ah, keyix); /* - * Check the key->node map and flush any ref. - */ - ni = sc->sc_keyixmap[keyix]; - if (ni != NULL) { - ieee80211_free_node(ni); - sc->sc_keyixmap[keyix] = NULL; - } - /* * Handle split tx/rx keying required for TKIP with h/w MIC. */ if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && - (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) { + (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) ath_hal_keyreset(ah, keyix+32); /* RX key */ - ni = sc->sc_keyixmap[keyix+32]; - if (ni != NULL) { /* as above... */ - ieee80211_free_node(ni); - sc->sc_keyixmap[keyix+32] = NULL; - } - } if (keyix >= IEEE80211_WEP_NKID) { /* * Don't touch keymap entries for global keys so @@ -2821,50 +2812,22 @@ rx_accept: /* * Locate the node for sender, track state, and then * pass the (referenced) node up to the 802.11 layer - * for its use. If the sender is unknown spam the - * frame; it'll be dropped where it's not wanted. + * for its use. */ - if (ds->ds_rxstat.rs_keyix != HAL_RXKEYIX_INVALID && - (ni = sc->sc_keyixmap[ds->ds_rxstat.rs_keyix]) != NULL) { - /* - * Fast path: node is present in the key map; - * grab a reference for processing the frame. - */ - an = ATH_NODE(ieee80211_ref_node(ni)); - ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi); - type = ieee80211_input(ic, m, ni, - ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp); - } else { - /* - * Locate the node for sender, track state, and then - * pass the (referenced) node up to the 802.11 layer - * for its use. - */ - ni = ieee80211_find_rxnode(ic, - mtod(m, const struct ieee80211_frame_min *)); - /* - * Track rx rssi and do any rx antenna management. - */ - an = ATH_NODE(ni); - ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi); - /* - * Send frame up for processing. - */ - type = ieee80211_input(ic, m, ni, - ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp); - if (ni != ic->ic_bss) { - u_int16_t keyix; - /* - * If the station has a key cache slot assigned - * update the key->node mapping table. - */ - keyix = ni->ni_ucastkey.wk_keyix; - if (keyix != IEEE80211_KEYIX_NONE && - sc->sc_keyixmap[keyix] == NULL) - sc->sc_keyixmap[keyix] = - ieee80211_ref_node(ni); - } - } + ni = ieee80211_find_rxnode_withkey(ic, + mtod(m, const struct ieee80211_frame_min *), + ds->ds_rxstat.rs_keyix == HAL_RXKEYIX_INVALID ? + IEEE80211_KEYIX_NONE : ds->ds_rxstat.rs_keyix); + /* + * Track rx rssi and do any rx antenna management. + */ + an = ATH_NODE(ni); + ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi); + /* + * Send frame up for processing. + */ + type = ieee80211_input(ic, m, ni, + ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp); ieee80211_free_node(ni); if (sc->sc_diversity) { /* @@ -4265,10 +4228,9 @@ ath_setup_stationkey(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; struct ath_softc *sc = ic->ic_ifp->if_softc; - u_int16_t keyix; + ieee80211_keyix keyix, rxkeyix; - keyix = ath_key_alloc(ic, &ni->ni_ucastkey); - if (keyix == IEEE80211_KEYIX_NONE) { + if (!ath_key_alloc(ic, &ni->ni_ucastkey, &keyix, &rxkeyix)) { /* * Key cache is full; we'll fall back to doing * the more expensive lookup in software. Note @@ -4276,7 +4238,9 @@ ath_setup_stationkey(struct ieee80211_node *ni) */ /* XXX msg+statistic */ } else { + /* XXX locking? */ ni->ni_ucastkey.wk_keyix = keyix; + ni->ni_ucastkey.wk_rxkeyix = rxkeyix; /* NB: this will create a pass-thru key entry */ ath_keyset(sc, &ni->ni_ucastkey, ni->ni_macaddr, ic->ic_bss); } |