Skip site navigation (1)Skip section navigation (2)
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>