Date: Tue, 27 Dec 2016 06:10:28 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r310624 - head/sys/net80211 Message-ID: <201612270610.uBR6ASrp025710@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Tue Dec 27 06:10:28 2016 New Revision: 310624 URL: https://svnweb.freebsd.org/changeset/base/310624 Log: [net80211] turn the default TX key configuration (for WEP) into a vap callback. The ath10k firmware supports hardware WEP offload, and in native wifi mode (or 802.3 ethernet mode, for that matter) the WEP key isn't actually included in the TX payload from net80211. Instead, a separate firmware command is issued that sets the default TX key to be the specified key. However, net80211 doesn't at all inform the driver layer that this is occuring - it just "expects" to be inserting WEP header information when doing WEP TX, even with hardware encryption. So, to better support the newer world order, turn the default TX key assignment into a VAP method that can be overridden by the driver and ensure its wrapped in a crypto begin/end set. That way it should be correctly atomic from the point of view of keychanges (as long as the driver does the right thing.) It'd be nice if we passed through to the key_set call a flag that says "also make this the default key" - that's captured here by calling the deftxkey method after the key_set method. Maybe I can do that later. Note: this is a net80211 ABI change, and will require a kernel+modules recompile. Happy Holidays, etc. Tested: * ath10k driver port * rtwn_usb, WEP station Modified: head/sys/net80211/ieee80211.c head/sys/net80211/ieee80211_crypto.c head/sys/net80211/ieee80211_crypto.h head/sys/net80211/ieee80211_ioctl.c head/sys/net80211/ieee80211_var.h Modified: head/sys/net80211/ieee80211.c ============================================================================== --- head/sys/net80211/ieee80211.c Tue Dec 27 01:10:28 2016 (r310623) +++ head/sys/net80211/ieee80211.c Tue Dec 27 06:10:28 2016 (r310624) @@ -433,6 +433,22 @@ default_reset(struct ieee80211vap *vap, } /* + * Default for updating the VAP default TX key index. + * + * Drivers that support TX offload as well as hardware encryption offload + * may need to be informed of key index changes separate from the key + * update. + */ +static void +default_update_deftxkey(struct ieee80211vap *vap, ieee80211_keyix kid) +{ + + /* XXX assert validity */ + /* XXX assert we're in a key update block */ + vap->iv_def_txkey = kid; +} + +/* * Add underlying device errors to vap errors. */ static uint64_t @@ -561,6 +577,12 @@ ieee80211_vap_setup(struct ieee80211com */ vap->iv_reset = default_reset; + /* + * Install a default crypto key update method, the driver + * can override this. + */ + vap->iv_update_deftxkey = default_update_deftxkey; + ieee80211_sysctl_vattach(vap); ieee80211_crypto_vattach(vap); ieee80211_node_vattach(vap); Modified: head/sys/net80211/ieee80211_crypto.c ============================================================================== --- head/sys/net80211/ieee80211_crypto.c Tue Dec 27 01:10:28 2016 (r310623) +++ head/sys/net80211/ieee80211_crypto.c Tue Dec 27 06:10:28 2016 (r310624) @@ -787,3 +787,18 @@ ieee80211_crypto_reload_keys(struct ieee */ ieee80211_iterate_nodes(&ic->ic_sta, load_ucastkey, NULL); } + +/* + * Set the default key index for WEP, or KEYIX_NONE for no default TX key. + * + * This should be done as part of a key update block (iv_key_update_begin / + * iv_key_update_end.) + */ +void +ieee80211_crypto_set_deftxkey(struct ieee80211vap *vap, ieee80211_keyix kid) +{ + + /* XXX TODO: assert we're in a key update block */ + + vap->iv_update_deftxkey(vap, kid); +} Modified: head/sys/net80211/ieee80211_crypto.h ============================================================================== --- head/sys/net80211/ieee80211_crypto.h Tue Dec 27 01:10:28 2016 (r310623) +++ head/sys/net80211/ieee80211_crypto.h Tue Dec 27 06:10:28 2016 (r310624) @@ -171,6 +171,8 @@ int ieee80211_crypto_delkey(struct ieee8 int ieee80211_crypto_setkey(struct ieee80211vap *, struct ieee80211_key *); void ieee80211_crypto_delglobalkeys(struct ieee80211vap *); void ieee80211_crypto_reload_keys(struct ieee80211com *); +void ieee80211_crypto_set_deftxkey(struct ieee80211vap *, + ieee80211_keyix kid); /* * Template for a supported cipher. Ciphers register with the Modified: head/sys/net80211/ieee80211_ioctl.c ============================================================================== --- head/sys/net80211/ieee80211_ioctl.c Tue Dec 27 01:10:28 2016 (r310623) +++ head/sys/net80211/ieee80211_ioctl.c Tue Dec 27 06:10:28 2016 (r310624) @@ -855,6 +855,8 @@ ieee80211_ioctl_get80211(struct ieee8021 * Tx power limit is the min of max regulatory * power, any user-set limit, and the max the * radio can do. + * + * TODO: methodize this */ ireq->i_val = 2*ic->ic_curchan->ic_maxregpower; if (ireq->i_val > ic->ic_txpowlimit) @@ -1013,6 +1015,7 @@ ieee80211_ioctl_get80211(struct ieee8021 ireq->i_val |= 2; break; case IEEE80211_IOC_AMPDU_LIMIT: + /* XXX TODO: make this a per-node thing; and leave this as global */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) ireq->i_val = vap->iv_ampdu_rxmax; else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) @@ -1026,6 +1029,7 @@ ieee80211_ioctl_get80211(struct ieee8021 ireq->i_val = vap->iv_ampdu_limit; break; case IEEE80211_IOC_AMPDU_DENSITY: + /* XXX TODO: make this a per-node thing; and leave this as global */ if (vap->iv_opmode == IEEE80211_M_STA && (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) /* @@ -1204,7 +1208,15 @@ ieee80211_ioctl_setkey(struct ieee80211v if (!ieee80211_crypto_setkey(vap, wk)) error = EIO; else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) - vap->iv_def_txkey = kid; + /* + * Inform the driver that this is the default + * transmit key. Now, ideally we'd just set + * a flag in the key update that would + * say "yes, we're the default key", but + * that currently isn't the way the ioctl -> + * key interface works. + */ + ieee80211_crypto_set_deftxkey(vap, kid); } else error = ENXIO; ieee80211_key_update_end(vap); @@ -2687,7 +2699,17 @@ ieee80211_ioctl_set80211(struct ieee8021 if (kid >= IEEE80211_WEP_NKID && (uint16_t) kid != IEEE80211_KEYIX_NONE) return EINVAL; - vap->iv_def_txkey = kid; + /* + * Firmware devices may need to be told about an explicit + * key index here, versus just inferring it from the + * key set / change. Since we may also need to pause + * things like transmit before the key is updated, + * give the driver a chance to flush things by tying + * into key update begin/end. + */ + ieee80211_key_update_begin(vap); + ieee80211_crypto_set_deftxkey(vap, kid); + ieee80211_key_update_end(vap); break; case IEEE80211_IOC_AUTHMODE: switch (ireq->i_val) { @@ -3094,6 +3116,7 @@ ieee80211_ioctl_set80211(struct ieee8021 error = ERESTART; break; case IEEE80211_IOC_AMPDU_LIMIT: + /* XXX TODO: figure out ampdu_limit versus ampdu_rxmax */ if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K <= ireq->i_val && ireq->i_val <= IEEE80211_HTCAP_MAXRXAMPDU_64K)) return EINVAL; Modified: head/sys/net80211/ieee80211_var.h ============================================================================== --- head/sys/net80211/ieee80211_var.h Tue Dec 27 01:10:28 2016 (r310623) +++ head/sys/net80211/ieee80211_var.h Tue Dec 27 06:10:28 2016 (r310624) @@ -470,6 +470,8 @@ struct ieee80211vap { struct ieee80211_appie *iv_appie_wpa; uint8_t *iv_wpa_ie; uint8_t *iv_rsn_ie; + + /* Key management */ uint16_t iv_max_keyix; /* max h/w key index */ ieee80211_keyix iv_def_txkey; /* default/group tx key index */ struct ieee80211_key iv_nw_keys[IEEE80211_WEP_NKID]; @@ -482,6 +484,8 @@ struct ieee80211vap { const struct ieee80211_key *); void (*iv_key_update_begin)(struct ieee80211vap *); void (*iv_key_update_end)(struct ieee80211vap *); + void (*iv_update_deftxkey)(struct ieee80211vap *, + ieee80211_keyix deftxkey); const struct ieee80211_authenticator *iv_auth; /* authenticator glue */ void *iv_ec; /* private auth state */ @@ -536,6 +540,7 @@ struct ieee80211vap { /* 802.3 output method for raw frame xmit */ int (*iv_output)(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); + uint64_t iv_spare[6]; }; MALLOC_DECLARE(M_80211_VAP);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612270610.uBR6ASrp025710>