Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Jul 2008 16:19:34 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 146210 for review
Message-ID:  <200807291619.m6TGJYed041739@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146210

Change 146210 by sam@sam_ebb on 2008/07/29 16:19:17

	Change callback api to allocate driver resources for a crypto key:
	o de-const the key parameter so drivers can muck with the flags
	o on callback failure don't automatically try to setup s/w crypto;
	  instead the driver must now mark the key entry for s/w crypto and
	  the caller will re-attach the cipher module
	o update drivers to match new api
	
	This change is experimental.  It permits drivers more control over
	fallback to s/w crypto (e.g. based on a limited number of h/w key
	slots).

Affected files ...

.. //depot/projects/vap/sys/dev/ath/if_ath.c#88 edit
.. //depot/projects/vap/sys/dev/mwl/if_mwl.c#12 edit
.. //depot/projects/vap/sys/net80211/ieee80211_crypto.c#19 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#48 edit

Differences ...

==== //depot/projects/vap/sys/dev/ath/if_ath.c#88 (text+ko) ====

@@ -135,7 +135,7 @@
 static int	ath_keyset(struct ath_softc *, const struct ieee80211_key *,
 			struct ieee80211_node *);
 static int	ath_key_alloc(struct ieee80211vap *,
-			const struct ieee80211_key *,
+			struct ieee80211_key *,
 			ieee80211_keyix *, ieee80211_keyix *);
 static int	ath_key_delete(struct ieee80211vap *,
 			const struct ieee80211_key *);
@@ -2397,7 +2397,7 @@
  * 64 entries.
  */
 static int
-ath_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k,
+ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
 {
 	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;

==== //depot/projects/vap/sys/dev/mwl/if_mwl.c#12 (text+ko) ====

@@ -117,7 +117,7 @@
 static void	mwl_chanswitch_proc(void *, int);
 static void	mwl_bawatchdog_proc(void *, int);
 static int	mwl_key_alloc(struct ieee80211vap *,
-			const struct ieee80211_key *,
+			struct ieee80211_key *,
 			ieee80211_keyix *, ieee80211_keyix *);
 static int	mwl_key_delete(struct ieee80211vap *,
 			const struct ieee80211_key *);
@@ -1884,11 +1884,11 @@
 
 /*
  * Allocate a key cache slot for a unicast key.  The
- * firmware handles key allocation so we just return
- * whatever is needed to keep the net80211 layer happy.
+ * firmware handles key allocation and every station is
+ * guaranteed key space so we are always successful.
  */
 static int
-mwl_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k,
+mwl_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
 {
 	struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
@@ -1905,8 +1905,7 @@
 		*keyix = *rxkeyix = k - vap->iv_nw_keys;
 	} else {
 		/*
-		 * Firmware handles key allocation; just set this to
-		 * something so the upper layers are happy.
+		 * Firmware handles key allocation.
 		 */
 		*keyix = *rxkeyix = 0;
 	}

==== //depot/projects/vap/sys/net80211/ieee80211_crypto.c#19 (text+ko) ====

@@ -59,7 +59,7 @@
  * Default "null" key management routines.
  */
 static int
-null_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k,
+null_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
 {
 	if (!(&vap->iv_nw_keys[0] <= k &&
@@ -116,7 +116,7 @@
  */
 static __inline int
 dev_key_alloc(struct ieee80211vap *vap,
-	const struct ieee80211_key *key,
+	struct ieee80211_key *key,
 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
 {
 	return vap->iv_key_alloc(vap, key, keyix, rxkeyix);
@@ -335,15 +335,11 @@
 	 * whether or not it needs to do the cipher work.
 	 */
 	if (key->wk_cipher != cip || key->wk_flags != flags) {
-again:
 		/*
 		 * Fillin the flags so cipher modules can see s/w
 		 * crypto requirements and potentially allocate
 		 * different state and/or attach different method
 		 * pointers.
-		 *
-		 * XXX this is not right when s/w crypto fallback
-		 *     fails and we try to restore previous state.
 		 */
 		key->wk_flags = flags;
 		keyctx = cip->ic_attach(vap, key);
@@ -375,31 +371,39 @@
 	if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) {
 		if (!dev_key_alloc(vap, key, &keyix, &rxkeyix)) {
 			/*
-			 * Driver has no room; fallback to doing crypto
-			 * in the host.  We change the flags and start the
-			 * procedure over.  If we get back here then there's
-			 * no hope and we bail.  Note that this can leave
-			 * the key in a inconsistent state if the caller
-			 * continues to use it.
+			 * Unable to setup driver state.
 			 */
-			if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
-				vap->iv_stats.is_crypto_swfallback++;
-				IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
-				    "%s: no h/w resources for cipher %s, "
-				    "falling back to s/w\n", __func__,
-				    cip->ic_name);
-				oflags = key->wk_flags;
-				flags |= IEEE80211_KEY_SWCRYPT;
-				if (cipher == IEEE80211_CIPHER_TKIP)
-					flags |= IEEE80211_KEY_SWMIC;
-				goto again;
-			}
 			vap->iv_stats.is_crypto_keyfail++;
 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
 			    "%s: unable to setup cipher %s\n",
 			    __func__, cip->ic_name);
 			return 0;
 		}
+		if (key->wk_flags != flags) {
+			/*
+			 * Driver overrode flags we setup; typically because
+			 * resources were unavailable to handle _this_ key.
+			 * Re-attach the cipher context to allow cipher
+			 * modules to handle differing requirements.
+			 */
+			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
+			    "%s: driver override for cipher %s, flags "
+			    "0x%x -> 0x%x\n", __func__, cip->ic_name,
+			    oflags, key->wk_flags);
+			keyctx = cip->ic_attach(vap, key);
+			if (keyctx == NULL) {
+				IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
+				    "%s: unable to attach cipher %s with "
+				    "flags 0x%x\n", __func__, cip->ic_name,
+				    key->wk_flags);
+				key->wk_flags = oflags;	/* restore old flags */
+				vap->iv_stats.is_crypto_attachfail++;
+				return 0;
+			}
+			cipher_detach(key);
+			key->wk_cipher = cip;		/* XXX refcnt? */
+			key->wk_private = keyctx;
+		}
 		key->wk_keyix = keyix;
 		key->wk_rxkeyix = rxkeyix;
 		key->wk_flags |= IEEE80211_KEY_DEVKEY;

==== //depot/projects/vap/sys/net80211/ieee80211_var.h#48 (text+ko) ====

@@ -370,7 +370,7 @@
 	ieee80211_keyix		iv_def_txkey;	/* default/group tx key index */
 	struct ieee80211_key	iv_nw_keys[IEEE80211_WEP_NKID];
 	int			(*iv_key_alloc)(struct ieee80211vap *,
-				    const struct ieee80211_key *,
+				    struct ieee80211_key *,
 				    ieee80211_keyix *, ieee80211_keyix *);
 	int			(*iv_key_delete)(struct ieee80211vap *, 
 				    const struct ieee80211_key *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807291619.m6TGJYed041739>