Hi Stefan,
> On 2/08/2019, at 11:13 PM, Stefan Sperling wrote:
>
> This diff enables HW offload for WPA2 CCMP (AES) encrypted unicast
> frames in iwm(4). This is in preparation for Tx aggregation support.
Lightly tested on:
iwm0 at pci1 dev 0 function 0 "Intel Dual Band Wireless AC 7265" rev 0x69, msi
iwm0: hw rev 0x210, fw ver 16.242414.0, address xx:xx:xx:xx:xx:xx
pkg_add -u; download a few big files; ifconfig down; ifconfig up;
change network.
comments inline. supposing the async set keys command is a non-issue then,
for what it’s worth from this 802.11 novice, ok procter@
thanks!
Richard.
> WEP and WPA1/TKIP ciphers are still handled in software, which mirrors
> what the older iwn(4) driver is doing. We don't enable 11n at all with
> those ciphers (see ieee80211_ht_negotiate()), and we won't aggregate
> non-encrypted frames (see ieee80211_can_use_ampdu()).
>
> Based on an initial diff by procter@ and some code from iwn(4).
>
> Tested on 7260, 7265, 8260, and 8265 in bsd.rd upgrade and with pkg_add -u.
>
> ok?
>
> diff refs/heads/master refs/heads/iwm-hwcrypt
> blob - 7add1e9e682ef5e22169ec1e89a182cda1af7e2a
> blob + 839c0a0f8b3a62115ba6d5e15adfa63158475c86
> --- sys/dev/pci/if_iwm.c
> +++ sys/dev/pci/if_iwm.c
> @@ -367,6 +367,8 @@ int iwm_get_signal_strength(struct iwm_softc *,
> struct
> void iwm_rx_rx_phy_cmd(struct iwm_softc *, struct iwm_rx_packet *,
> struct iwm_rx_data *);
> int iwm_get_noise(const struct iwm_statistics_rx_non_phy *);
> +int iwm_ccmp_decap(struct iwm_softc *, struct mbuf *,
> + struct ieee80211_node *);
> void iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *,
> struct iwm_rx_data *);
> void iwm_enable_ht_cck_fallback(struct iwm_softc *, struct iwm_node *);
> @@ -448,6 +450,10 @@ int iwm_disassoc(struct iwm_softc *);
> int iwm_run(struct iwm_softc *);
> int iwm_run_stop(struct iwm_softc *);
> struct ieee80211_node *iwm_node_alloc(struct ieee80211com *);
> +int iwm_set_key(struct ieee80211com *, struct ieee80211_node *,
> + struct ieee80211_key *);
> +void iwm_delete_key(struct ieee80211com *,
> + struct ieee80211_node *, struct ieee80211_key *);
> void iwm_calib_timeout(void *);
> int iwm_media_change(struct ifnet *);
> void iwm_newstate_task(void *);
> @@ -3429,11 +3435,91 @@ iwm_get_noise(const struct iwm_statistics_rx_non_phy *
> return (nbant == 0) ? -127 : (total / nbant) - 107;
> }
>
> +int
> +iwm_ccmp_decap(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node
> *ni)
> +{
> + struct ieee80211com *ic = >sc_ic;
> + struct ieee80211_key *k = >ni_pairwise_key;
> + struct ieee80211_frame *wh;
> + struct ieee80211_rx_ba *ba;
> + uint64_t pn, *prsc;
> + uint8_t *ivp;
> + uint8_t tid;
> + int hdrlen, hasqos;
> +
> + wh = mtod(m, struct ieee80211_frame *);
> + hdrlen = ieee80211_get_hdrlen(wh);
> + ivp = (uint8_t *)wh + hdrlen;
> +
> + /* Check that ExtIV bit is be set. */
> + if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
> + DPRINTF(("CCMP decap ExtIV not set\n"));
> + return 1;
> + }
> + hasqos = ieee80211_has_qos(wh);
> + tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> + ba = hasqos ? >ni_rx_ba[tid] : NULL;
> + prsc = >k_rsc[tid];
> +
> + /* Extract the 48-bit PN from the CCMP header. */
> + pn = (uint64_t)ivp[0] |
> + (uint64_t)ivp[1] << 8 |
> + (uint64_t)ivp[4] << 16 |
> + (uint64_t)ivp[5] << 24 |
> + (uint64_t)ivp[6] << 32 |
> + (uint64_t)ivp[7] << 40;
> + if (pn <= *prsc) {
> + if (hasqos && ba->ba_state == IEEE80211_BA_AGREED) {
> + /*
> + * This is an A-MPDU subframe.
> + * Such frames may be received out of order due to
> + * legitimate retransmissions of failed subframes
> + * in previous A-MPDUs. Duplicates will be handled
> + * in ieee80211_input() as part of A-MPDU reordering.
> + */
> + } else if (ieee80211_has_seq(wh)) {
> + /*
> + * Not necessarily a replayed frame since we did not
> + * check the sequence number of the 802.11 header yet.
> + */
> + int nrxseq, orxseq;
> +
> + nrxseq = letoh16(*(u_int16_t *)wh->i_seq) >>
> + IEEE80211_SEQ_SEQ_SHIFT;
> + if (hasqos)
> + orxseq = ni->ni_qos_rxseqs[tid];
> + else
> + orxseq = ni->ni_rxseq;
> + if (nrxseq < orxseq) {
> + DPRINTF(("CCMP replayed (n=%d < o=%d)\n",
> + nrxseq, orxseq));
> + ic->ic_stats.is_ccmp_replays++;
> +