Jonathan Matthew(jonat...@d14n.org) on 2020.06.05 21:54:30 +1000:
> This enables use of hardware crypto for CCMP in urtwn(4). As with other
> drivers, this reduces cpu usage significantly when moving lots of data.
> I've tested this on an assortment of hardware (RTL8188CUS, RTL8188EU,
> RTL8192EU) with no problems, and this is one of the few things that
> remains constant across a lot of Realtek wifi chips, but some wider
> testing couldn't hurt. Since this touches the code shared with rtwn(4),
> I've also tested that that still works.

Works on 

urtwn0 at uhub2 port 2 configuration 1 interface 0 "Realtek 802.11n NIC" rev 
2.00/0.00 addr 3
urtwn0: MAC/BB RTL8188EU, RF 6052 1T1R, address d4:6e:0e:29:e2:84

usb stick, on armv7.

In a quick test, download of a 10MB large file is faster with your diff, up
from 1MB/s to now 1.6MB/s.

/Benno

> 
> 
> Index: ic/r92creg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/r92creg.h,v
> retrieving revision 1.24
> diff -u -p -r1.24 r92creg.h
> --- ic/r92creg.h      11 Mar 2019 06:19:33 -0000      1.24
> +++ ic/r92creg.h      5 Jun 2020 11:52:21 -0000
> @@ -688,6 +688,16 @@
>  #define R92C_CAMCMD_CLR              0x40000000
>  #define R92C_CAMCMD_POLLING  0x80000000
>  
> +/* Bits for R92C_SECCFG. */
> +#define R92C_SECCFG_TXUCKEY_DEF 0x0001
> +#define R92C_SECCFG_RXUCKEY_DEF      0x0002
> +#define R92C_SECCFG_TXENC_ENA        0x0004
> +#define R92C_SECCFG_RXENC_ENA        0x0008
> +#define R92C_SECCFG_CMP_A2   0x0010
> +#define R92C_SECCFG_MC_SRCH_DIS      0x0020
> +#define R92C_SECCFG_TXBCKEY_DEF 0x0040
> +#define R92C_SECCFG_RXBCKEY_DEF 0x0080
> +
>  /* IMR */
>   
>  /*Beacon DMA interrupt 6 */
> Index: ic/rtwn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/rtwn.c,v
> retrieving revision 1.49
> diff -u -p -r1.49 rtwn.c
> --- ic/rtwn.c 9 Jan 2020 14:35:19 -0000       1.49
> +++ ic/rtwn.c 5 Jun 2020 11:52:22 -0000
> @@ -3154,6 +3154,14 @@ rtwn_init(struct ifnet *ifp)
>       /* Clear per-station keys table. */
>       rtwn_cam_init(sc);
>  
> +     /* Enable decryption / encryption. */
> +     if (sc->chip & RTWN_CHIP_USB) {
> +             rtwn_write_2(sc, R92C_SECCFG,
> +                 R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
> +                 R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXENC_ENA |
> +                 R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF);
> +     }
> +
>       /* Enable hardware sequence numbering. */
>       rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
>  
> @@ -3204,14 +3212,14 @@ rtwn_init(struct ifnet *ifp)
>       ifq_clr_oactive(&ifp->if_snd);
>       ifp->if_flags |= IFF_RUNNING;
>  
> -#ifdef notyet
> -     if (ic->ic_flags & IEEE80211_F_WEPON) {
> +     if ((ic->ic_flags & IEEE80211_F_WEPON) &&
> +         (sc->chip & RTWN_CHIP_USB)) {
>               /* Install WEP keys. */
>               for (i = 0; i < IEEE80211_WEP_NKID; i++)
>                       ic->ic_set_key(ic, NULL, &ic->ic_nw_keys[i]);
>               sc->sc_ops.wait_async(sc->sc_ops.cookie);
>       }
> -#endif
> +
>       if (ic->ic_opmode == IEEE80211_M_MONITOR)
>               ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
>       else
> Index: usb/if_urtwn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/if_urtwn.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 if_urtwn.c
> --- usb/if_urtwn.c    26 May 2020 06:04:30 -0000      1.89
> +++ usb/if_urtwn.c    5 Jun 2020 11:52:22 -0000
> @@ -490,10 +490,8 @@ urtwn_attach(struct device *parent, stru
>  
>       ic->ic_updateslot = urtwn_updateslot;
>       ic->ic_updateedca = urtwn_updateedca;
> -#ifdef notyet
>       ic->ic_set_key = urtwn_set_key;
>       ic->ic_delete_key = urtwn_delete_key;
> -#endif
>       /* Override state transition machine. */
>       ic->ic_newstate = urtwn_newstate;
>  
> @@ -1035,6 +1033,10 @@ urtwn_set_key(struct ieee80211com *ic, s
>       struct urtwn_softc *sc = (struct urtwn_softc *)self;
>       struct urtwn_cmd_key cmd;
>  
> +     /* Only handle keys for CCMP */
> +     if (k->k_cipher != IEEE80211_CIPHER_CCMP)
> +             return ieee80211_set_key(ic, ni, k);
> +
>       /* Defer setting of WEP keys until interface is brought up. */
>       if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
>           (IFF_UP | IFF_RUNNING))
> @@ -1065,6 +1067,12 @@ urtwn_delete_key(struct ieee80211com *ic
>       struct urtwn_softc *sc = (struct urtwn_softc *)self;
>       struct urtwn_cmd_key cmd;
>  
> +     /* Only handle keys for CCMP */
> +     if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
> +             ieee80211_delete_key(ic, ni, k);
> +             return;
> +     }
> +
>       if (!(ic->ic_if.if_flags & IFF_RUNNING) ||
>           ic->ic_state != IEEE80211_S_RUN)
>               return; /* Nothing to do. */
> @@ -1084,6 +1092,52 @@ urtwn_delete_key_cb(struct urtwn_softc *
>       rtwn_delete_key(ic, cmd->ni, &cmd->key);
>  }
>  
> +int
> +urtwn_ccmp_decap(struct urtwn_softc *sc, struct mbuf *m,
> +    struct ieee80211_node *ni)
> +{
> +     struct ieee80211com *ic = &sc->sc_sc.sc_ic;
> +     struct ieee80211_key *k;
> +     struct ieee80211_frame *wh;
> +     uint64_t pn, *prsc;
> +     uint8_t *ivp;
> +     uint8_t tid;
> +     int hdrlen, hasqos;
> +
> +     k = ieee80211_get_rxkey(ic, m, ni);
> +     if (k == NULL)
> +             return 1;
> +
> +     wh = mtod(m, struct ieee80211_frame *);
> +     hdrlen = ieee80211_get_hdrlen(wh);
> +     ivp = (uint8_t *)wh + hdrlen;
> +
> +     /* Check that ExtIV bit is set. */
> +     if (!(ivp[3] & IEEE80211_WEP_EXTIV))
> +             return 1;
> +
> +     hasqos = ieee80211_has_qos(wh);
> +     tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> +     prsc = &k->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) {
> +             ic->ic_stats.is_ccmp_replays++;
> +             return 1;
> +     }
> +     /* Last seen packet number is updated in ieee80211_inputm(). */
> +
> +     /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
> +     m_adj(m, -IEEE80211_CCMP_MICLEN);
> +     return 0;
> +}
> +
>  void
>  urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen,
>      struct mbuf_list *ml)
> @@ -1197,6 +1251,21 @@ urtwn_rx_frame(struct urtwn_softc *sc, u
>       rxi.rxi_flags = 0;
>       rxi.rxi_rssi = rssi;
>       rxi.rxi_tstamp = 0;     /* Unused. */
> +
> +     /* Handle hardware decryption. */
> +     if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL)
> +         && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
> +         (ni->ni_flags & IEEE80211_NODE_RXPROT) &&
> +         ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
> +             if (urtwn_ccmp_decap(sc, m, ni) != 0) {
> +                     ifp->if_ierrors++;
> +                     m_freem(m);
> +                     ieee80211_release_node(ic, ni);
> +                     return;
> +             }
> +             rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
> +     }
> +
>       ieee80211_inputm(ifp, m, ni, &rxi, ml);
>       /* Node is no longer needed. */
>       ieee80211_release_node(ic, ni);
> @@ -1360,37 +1429,28 @@ urtwn_tx_fill_desc(struct urtwn_softc *s
>       struct r92c_tx_desc_usb *txd;
>       struct ieee80211com *ic = &sc->sc_sc.sc_ic;
>       uint8_t raid, type;
> +     uint32_t pktlen;
>  
>       txd = (struct r92c_tx_desc_usb *)*txdp;
>       (*txdp) += sizeof(*txd);
>       memset(txd, 0, sizeof(*txd));
>  
> +     pktlen = m->m_pkthdr.len;
> +     if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {
> +             txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER,
> +                 R92C_TXDW1_CIPHER_AES));
> +             pktlen += IEEE80211_CCMP_HDRLEN;
> +     }
> +
>       type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
>  
>       txd->txdw0 |= htole32(
> -         SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
> +         SM(R92C_TXDW0_PKTLEN, pktlen) |
>           SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
>           R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
>       if (IEEE80211_IS_MULTICAST(wh->i_addr1))
>               txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
>  
> -#ifdef notyet
> -     if (k != NULL) {
> -             switch (k->k_cipher) {
> -             case IEEE80211_CIPHER_WEP40:
> -             case IEEE80211_CIPHER_WEP104:
> -             case IEEE80211_CIPHER_TKIP:
> -                     cipher = R92C_TXDW1_CIPHER_RC4;
> -                     break;
> -             case IEEE80211_CIPHER_CCMP:
> -                     cipher = R92C_TXDW1_CIPHER_AES;
> -                     break;
> -             default:
> -                     cipher = R92C_TXDW1_CIPHER_NONE;
> -             }
> -             txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER, cipher));
> -     }
> -#endif
>       if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
>           type == IEEE80211_FC0_TYPE_DATA) {
>               if (ic->ic_curmode == IEEE80211_MODE_11B ||
> @@ -1413,7 +1473,7 @@ urtwn_tx_fill_desc(struct urtwn_softc *s
>                           SM(R92C_TXDW1_RAID, raid) | R92C_TXDW1_AGGBK);
>               }
>  
> -             if (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
> +             if (pktlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
>                       txd->txdw4 |= htole32(R92C_TXDW4_RTSEN |
>                           R92C_TXDW4_HWRTSEN);
>               } else if (ic->ic_flags & IEEE80211_F_USEPROT) {
> @@ -1468,6 +1528,7 @@ urtwn_tx_fill_desc_gen2(struct urtwn_sof
>       struct r92e_tx_desc_usb *txd;
>       struct ieee80211com *ic = &sc->sc_sc.sc_ic;
>       uint8_t raid, type;
> +     uint32_t pktlen;
>  
>       txd = (struct r92e_tx_desc_usb *)*txdp;
>       (*txdp) += sizeof(*txd);
> @@ -1475,17 +1536,20 @@ urtwn_tx_fill_desc_gen2(struct urtwn_sof
>  
>       type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
>  
> +     pktlen = m->m_pkthdr.len;
> +     if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {
> +             txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER,
> +                 R92C_TXDW1_CIPHER_AES));
> +             pktlen += IEEE80211_CCMP_HDRLEN;
> +     }
> +
>       txd->txdw0 |= htole32(
> -         SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
> +         SM(R92C_TXDW0_PKTLEN, pktlen) |
>           SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
>           R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
>       if (IEEE80211_IS_MULTICAST(wh->i_addr1))
>               txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
>  
> -#ifdef notyet
> -     /* cipher */
> -#endif
> -
>       if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
>           type == IEEE80211_FC0_TYPE_DATA) {
>               if (ic->ic_curmode == IEEE80211_MODE_11B ||
> @@ -1500,7 +1564,7 @@ urtwn_tx_fill_desc_gen2(struct urtwn_sof
>               /* Request TX status report for AMRR */
>               txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT | R88E_TXDW2_AGGBK);
>  
> -             if (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
> +             if (pktlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) {
>                       txd->txdw4 |= htole32(R92C_TXDW4_RTSEN |
>                           R92C_TXDW4_HWRTSEN);
>               } else if (ic->ic_flags & IEEE80211_F_USEPROT) {
> @@ -1549,16 +1613,18 @@ urtwn_tx(void *cookie, struct mbuf *m, s
>       struct usbd_pipe *pipe;
>       uint16_t qos, sum;
>       uint8_t tid, qid;
> -     int i, xferlen, error;
> +     int i, xferlen, error, headerlen;
>       uint8_t *txdp;
>  
>       wh = mtod(m, struct ieee80211_frame *);
>  
>       if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
>               k = ieee80211_get_txkey(ic, wh, ni);
> -             if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
> -                     return (ENOBUFS);
> -             wh = mtod(m, struct ieee80211_frame *);
> +             if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
> +                     if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
> +                             return (ENOBUFS);
> +                     wh = mtod(m, struct ieee80211_frame *);
> +             }
>       }
>  
>       if (ieee80211_has_qos(wh)) {
> @@ -1611,9 +1677,31 @@ urtwn_tx(void *cookie, struct mbuf *m, s
>       }
>  #endif
>  
> -     xferlen = (txdp - data->buf) + m->m_pkthdr.len;
> -     m_copydata(m, 0, m->m_pkthdr.len, txdp);
> -     m_freem(m);
> +     if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) {
> +             xferlen = (txdp - data->buf) + m->m_pkthdr.len + 
> +                 IEEE80211_CCMP_HDRLEN;
> +             headerlen = ieee80211_get_hdrlen(wh);
> +
> +             m_copydata(m, 0, headerlen, txdp);
> +             txdp += headerlen;
> +
> +             k->k_tsc++;
> +             txdp[0] = k->k_tsc;
> +             txdp[1] = k->k_tsc >> 8;
> +             txdp[2] = 0;
> +             txdp[3] = k->k_id | IEEE80211_WEP_EXTIV;
> +             txdp[4] = k->k_tsc >> 16;
> +             txdp[5] = k->k_tsc >> 24;
> +             txdp[6] = k->k_tsc >> 32;
> +             txdp[7] = k->k_tsc >> 40;
> +             txdp += IEEE80211_CCMP_HDRLEN;
> +
> +             m_copydata(m, headerlen, m->m_pkthdr.len - headerlen, txdp);
> +     } else {
> +             xferlen = (txdp - data->buf) + m->m_pkthdr.len;
> +             m_copydata(m, 0, m->m_pkthdr.len, txdp);
> +             m_freem(m);
> +     }
>  
>       data->pipe = pipe;
>       usbd_setup_xfer(data->xfer, pipe, data, data->buf, xferlen,
> 

Reply via email to