1*4f272a5eSJohn Baldwin /*- 2*4f272a5eSJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause 3*4f272a5eSJohn Baldwin * 4*4f272a5eSJohn Baldwin * Copyright (c) 2025 Chelsio Communications 5*4f272a5eSJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 6*4f272a5eSJohn Baldwin * 7*4f272a5eSJohn Baldwin * Redistribution and use in source and binary forms, with or without 8*4f272a5eSJohn Baldwin * modification, are permitted provided that the following conditions 9*4f272a5eSJohn Baldwin * are met: 10*4f272a5eSJohn Baldwin * 1. Redistributions of source code must retain the above copyright 11*4f272a5eSJohn Baldwin * notice, this list of conditions and the following disclaimer. 12*4f272a5eSJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 13*4f272a5eSJohn Baldwin * notice, this list of conditions and the following disclaimer in the 14*4f272a5eSJohn Baldwin * documentation and/or other materials provided with the distribution. 15*4f272a5eSJohn Baldwin * 16*4f272a5eSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*4f272a5eSJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*4f272a5eSJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*4f272a5eSJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*4f272a5eSJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*4f272a5eSJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*4f272a5eSJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*4f272a5eSJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*4f272a5eSJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*4f272a5eSJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*4f272a5eSJohn Baldwin * SUCH DAMAGE. 27*4f272a5eSJohn Baldwin */ 28*4f272a5eSJohn Baldwin 29*4f272a5eSJohn Baldwin #include "opt_inet.h" 30*4f272a5eSJohn Baldwin #include "opt_inet6.h" 31*4f272a5eSJohn Baldwin #include "opt_kern_tls.h" 32*4f272a5eSJohn Baldwin 33*4f272a5eSJohn Baldwin #include <sys/cdefs.h> 34*4f272a5eSJohn Baldwin __FBSDID("$FreeBSD$"); 35*4f272a5eSJohn Baldwin 36*4f272a5eSJohn Baldwin #include <sys/param.h> 37*4f272a5eSJohn Baldwin #include <sys/ktr.h> 38*4f272a5eSJohn Baldwin #include <sys/ktls.h> 39*4f272a5eSJohn Baldwin #include <sys/sglist.h> 40*4f272a5eSJohn Baldwin #include <sys/socket.h> 41*4f272a5eSJohn Baldwin #include <sys/socketvar.h> 42*4f272a5eSJohn Baldwin #include <sys/sockbuf.h> 43*4f272a5eSJohn Baldwin #include <netinet/in.h> 44*4f272a5eSJohn Baldwin #include <netinet/in_pcb.h> 45*4f272a5eSJohn Baldwin #include <netinet/ip.h> 46*4f272a5eSJohn Baldwin #include <netinet/ip6.h> 47*4f272a5eSJohn Baldwin #include <netinet/tcp_var.h> 48*4f272a5eSJohn Baldwin #include <opencrypto/cryptodev.h> 49*4f272a5eSJohn Baldwin #include <opencrypto/xform.h> 50*4f272a5eSJohn Baldwin 51*4f272a5eSJohn Baldwin #include "common/common.h" 52*4f272a5eSJohn Baldwin #include "common/t4_regs.h" 53*4f272a5eSJohn Baldwin #include "common/t4_regs_values.h" 54*4f272a5eSJohn Baldwin #include "common/t4_tcb.h" 55*4f272a5eSJohn Baldwin #include "t4_l2t.h" 56*4f272a5eSJohn Baldwin #include "t4_clip.h" 57*4f272a5eSJohn Baldwin #include "t4_mp_ring.h" 58*4f272a5eSJohn Baldwin #include "crypto/t4_crypto.h" 59*4f272a5eSJohn Baldwin 60*4f272a5eSJohn Baldwin #if defined(INET) || defined(INET6) 61*4f272a5eSJohn Baldwin 62*4f272a5eSJohn Baldwin #define TLS_HEADER_LENGTH 5 63*4f272a5eSJohn Baldwin 64*4f272a5eSJohn Baldwin struct tls_scmd { 65*4f272a5eSJohn Baldwin __be32 seqno_numivs; 66*4f272a5eSJohn Baldwin __be32 ivgen_hdrlen; 67*4f272a5eSJohn Baldwin }; 68*4f272a5eSJohn Baldwin 69*4f272a5eSJohn Baldwin struct tlspcb { 70*4f272a5eSJohn Baldwin struct m_snd_tag com; 71*4f272a5eSJohn Baldwin struct vi_info *vi; /* virtual interface */ 72*4f272a5eSJohn Baldwin struct adapter *sc; 73*4f272a5eSJohn Baldwin struct sge_txq *txq; 74*4f272a5eSJohn Baldwin 75*4f272a5eSJohn Baldwin int tx_key_addr; 76*4f272a5eSJohn Baldwin bool inline_key; 77*4f272a5eSJohn Baldwin unsigned char enc_mode; 78*4f272a5eSJohn Baldwin 79*4f272a5eSJohn Baldwin struct tls_scmd scmd0; 80*4f272a5eSJohn Baldwin struct tls_scmd scmd0_short; 81*4f272a5eSJohn Baldwin 82*4f272a5eSJohn Baldwin unsigned int tx_key_info_size; 83*4f272a5eSJohn Baldwin 84*4f272a5eSJohn Baldwin uint16_t prev_mss; 85*4f272a5eSJohn Baldwin 86*4f272a5eSJohn Baldwin /* Only used outside of setup and teardown when using inline keys. */ 87*4f272a5eSJohn Baldwin struct tls_keyctx keyctx; 88*4f272a5eSJohn Baldwin }; 89*4f272a5eSJohn Baldwin 90*4f272a5eSJohn Baldwin static void t7_tls_tag_free(struct m_snd_tag *mst); 91*4f272a5eSJohn Baldwin static int ktls_setup_keys(struct tlspcb *tlsp, 92*4f272a5eSJohn Baldwin const struct ktls_session *tls, struct sge_txq *txq); 93*4f272a5eSJohn Baldwin 94*4f272a5eSJohn Baldwin static const struct if_snd_tag_sw t7_tls_tag_sw = { 95*4f272a5eSJohn Baldwin .snd_tag_free = t7_tls_tag_free, 96*4f272a5eSJohn Baldwin .type = IF_SND_TAG_TYPE_TLS 97*4f272a5eSJohn Baldwin }; 98*4f272a5eSJohn Baldwin 99*4f272a5eSJohn Baldwin static inline struct tlspcb * 100*4f272a5eSJohn Baldwin mst_to_tls(struct m_snd_tag *t) 101*4f272a5eSJohn Baldwin { 102*4f272a5eSJohn Baldwin return (__containerof(t, struct tlspcb, com)); 103*4f272a5eSJohn Baldwin } 104*4f272a5eSJohn Baldwin 105*4f272a5eSJohn Baldwin static struct tlspcb * 106*4f272a5eSJohn Baldwin alloc_tlspcb(struct ifnet *ifp, struct vi_info *vi, int flags) 107*4f272a5eSJohn Baldwin { 108*4f272a5eSJohn Baldwin struct port_info *pi = vi->pi; 109*4f272a5eSJohn Baldwin struct adapter *sc = pi->adapter; 110*4f272a5eSJohn Baldwin struct tlspcb *tlsp; 111*4f272a5eSJohn Baldwin 112*4f272a5eSJohn Baldwin tlsp = malloc(sizeof(*tlsp), M_CXGBE, M_ZERO | flags); 113*4f272a5eSJohn Baldwin if (tlsp == NULL) 114*4f272a5eSJohn Baldwin return (NULL); 115*4f272a5eSJohn Baldwin 116*4f272a5eSJohn Baldwin m_snd_tag_init(&tlsp->com, ifp, &t7_tls_tag_sw); 117*4f272a5eSJohn Baldwin tlsp->vi = vi; 118*4f272a5eSJohn Baldwin tlsp->sc = sc; 119*4f272a5eSJohn Baldwin tlsp->tx_key_addr = -1; 120*4f272a5eSJohn Baldwin 121*4f272a5eSJohn Baldwin return (tlsp); 122*4f272a5eSJohn Baldwin } 123*4f272a5eSJohn Baldwin 124*4f272a5eSJohn Baldwin int 125*4f272a5eSJohn Baldwin t7_tls_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params, 126*4f272a5eSJohn Baldwin struct m_snd_tag **pt) 127*4f272a5eSJohn Baldwin { 128*4f272a5eSJohn Baldwin const struct ktls_session *tls; 129*4f272a5eSJohn Baldwin struct tlspcb *tlsp; 130*4f272a5eSJohn Baldwin struct adapter *sc; 131*4f272a5eSJohn Baldwin struct vi_info *vi; 132*4f272a5eSJohn Baldwin struct inpcb *inp; 133*4f272a5eSJohn Baldwin struct sge_txq *txq; 134*4f272a5eSJohn Baldwin int error, explicit_iv_size, keyid, mac_first; 135*4f272a5eSJohn Baldwin 136*4f272a5eSJohn Baldwin tls = params->tls.tls; 137*4f272a5eSJohn Baldwin 138*4f272a5eSJohn Baldwin /* Only TLS 1.1 and TLS 1.2 are currently supported. */ 139*4f272a5eSJohn Baldwin if (tls->params.tls_vmajor != TLS_MAJOR_VER_ONE || 140*4f272a5eSJohn Baldwin tls->params.tls_vminor < TLS_MINOR_VER_ONE || 141*4f272a5eSJohn Baldwin tls->params.tls_vminor > TLS_MINOR_VER_TWO) 142*4f272a5eSJohn Baldwin return (EPROTONOSUPPORT); 143*4f272a5eSJohn Baldwin 144*4f272a5eSJohn Baldwin /* Sanity check values in *tls. */ 145*4f272a5eSJohn Baldwin switch (tls->params.cipher_algorithm) { 146*4f272a5eSJohn Baldwin case CRYPTO_AES_CBC: 147*4f272a5eSJohn Baldwin /* XXX: Explicitly ignore any provided IV. */ 148*4f272a5eSJohn Baldwin switch (tls->params.cipher_key_len) { 149*4f272a5eSJohn Baldwin case 128 / 8: 150*4f272a5eSJohn Baldwin case 192 / 8: 151*4f272a5eSJohn Baldwin case 256 / 8: 152*4f272a5eSJohn Baldwin break; 153*4f272a5eSJohn Baldwin default: 154*4f272a5eSJohn Baldwin return (EINVAL); 155*4f272a5eSJohn Baldwin } 156*4f272a5eSJohn Baldwin switch (tls->params.auth_algorithm) { 157*4f272a5eSJohn Baldwin case CRYPTO_SHA1_HMAC: 158*4f272a5eSJohn Baldwin case CRYPTO_SHA2_256_HMAC: 159*4f272a5eSJohn Baldwin case CRYPTO_SHA2_384_HMAC: 160*4f272a5eSJohn Baldwin break; 161*4f272a5eSJohn Baldwin default: 162*4f272a5eSJohn Baldwin return (EPROTONOSUPPORT); 163*4f272a5eSJohn Baldwin } 164*4f272a5eSJohn Baldwin explicit_iv_size = AES_BLOCK_LEN; 165*4f272a5eSJohn Baldwin mac_first = 1; 166*4f272a5eSJohn Baldwin break; 167*4f272a5eSJohn Baldwin case CRYPTO_AES_NIST_GCM_16: 168*4f272a5eSJohn Baldwin if (tls->params.iv_len != SALT_SIZE) 169*4f272a5eSJohn Baldwin return (EINVAL); 170*4f272a5eSJohn Baldwin switch (tls->params.cipher_key_len) { 171*4f272a5eSJohn Baldwin case 128 / 8: 172*4f272a5eSJohn Baldwin case 192 / 8: 173*4f272a5eSJohn Baldwin case 256 / 8: 174*4f272a5eSJohn Baldwin break; 175*4f272a5eSJohn Baldwin default: 176*4f272a5eSJohn Baldwin return (EINVAL); 177*4f272a5eSJohn Baldwin } 178*4f272a5eSJohn Baldwin explicit_iv_size = 8; 179*4f272a5eSJohn Baldwin mac_first = 0; 180*4f272a5eSJohn Baldwin break; 181*4f272a5eSJohn Baldwin default: 182*4f272a5eSJohn Baldwin return (EPROTONOSUPPORT); 183*4f272a5eSJohn Baldwin } 184*4f272a5eSJohn Baldwin 185*4f272a5eSJohn Baldwin vi = if_getsoftc(ifp); 186*4f272a5eSJohn Baldwin sc = vi->adapter; 187*4f272a5eSJohn Baldwin 188*4f272a5eSJohn Baldwin tlsp = alloc_tlspcb(ifp, vi, M_WAITOK); 189*4f272a5eSJohn Baldwin 190*4f272a5eSJohn Baldwin if (sc->tlst.inline_keys) 191*4f272a5eSJohn Baldwin keyid = -1; 192*4f272a5eSJohn Baldwin else 193*4f272a5eSJohn Baldwin keyid = t4_alloc_tls_keyid(sc); 194*4f272a5eSJohn Baldwin if (keyid < 0) { 195*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p using immediate key ctx", __func__, 196*4f272a5eSJohn Baldwin tlsp); 197*4f272a5eSJohn Baldwin tlsp->inline_key = true; 198*4f272a5eSJohn Baldwin } else { 199*4f272a5eSJohn Baldwin tlsp->tx_key_addr = keyid; 200*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p allocated TX key addr %#x", __func__, 201*4f272a5eSJohn Baldwin tlsp, tlsp->tx_key_addr); 202*4f272a5eSJohn Baldwin } 203*4f272a5eSJohn Baldwin 204*4f272a5eSJohn Baldwin inp = params->tls.inp; 205*4f272a5eSJohn Baldwin INP_RLOCK(inp); 206*4f272a5eSJohn Baldwin if (inp->inp_flags & INP_DROPPED) { 207*4f272a5eSJohn Baldwin INP_RUNLOCK(inp); 208*4f272a5eSJohn Baldwin error = ECONNRESET; 209*4f272a5eSJohn Baldwin goto failed; 210*4f272a5eSJohn Baldwin } 211*4f272a5eSJohn Baldwin 212*4f272a5eSJohn Baldwin txq = &sc->sge.txq[vi->first_txq]; 213*4f272a5eSJohn Baldwin if (inp->inp_flowtype != M_HASHTYPE_NONE) 214*4f272a5eSJohn Baldwin txq += ((inp->inp_flowid % (vi->ntxq - vi->rsrv_noflowq)) + 215*4f272a5eSJohn Baldwin vi->rsrv_noflowq); 216*4f272a5eSJohn Baldwin tlsp->txq = txq; 217*4f272a5eSJohn Baldwin INP_RUNLOCK(inp); 218*4f272a5eSJohn Baldwin 219*4f272a5eSJohn Baldwin error = ktls_setup_keys(tlsp, tls, txq); 220*4f272a5eSJohn Baldwin if (error) 221*4f272a5eSJohn Baldwin goto failed; 222*4f272a5eSJohn Baldwin 223*4f272a5eSJohn Baldwin tlsp->enc_mode = t4_tls_cipher_mode(tls); 224*4f272a5eSJohn Baldwin tlsp->tx_key_info_size = t4_tls_key_info_size(tls); 225*4f272a5eSJohn Baldwin 226*4f272a5eSJohn Baldwin /* The SCMD fields used when encrypting a full TLS record. */ 227*4f272a5eSJohn Baldwin tlsp->scmd0.seqno_numivs = htobe32(V_SCMD_SEQ_NO_CTRL(3) | 228*4f272a5eSJohn Baldwin V_SCMD_PROTO_VERSION(t4_tls_proto_ver(tls)) | 229*4f272a5eSJohn Baldwin V_SCMD_ENC_DEC_CTRL(SCMD_ENCDECCTRL_ENCRYPT) | 230*4f272a5eSJohn Baldwin V_SCMD_CIPH_AUTH_SEQ_CTRL((mac_first == 0)) | 231*4f272a5eSJohn Baldwin V_SCMD_CIPH_MODE(tlsp->enc_mode) | 232*4f272a5eSJohn Baldwin V_SCMD_AUTH_MODE(t4_tls_auth_mode(tls)) | 233*4f272a5eSJohn Baldwin V_SCMD_HMAC_CTRL(t4_tls_hmac_ctrl(tls)) | 234*4f272a5eSJohn Baldwin V_SCMD_IV_SIZE(explicit_iv_size / 2) | V_SCMD_NUM_IVS(1)); 235*4f272a5eSJohn Baldwin 236*4f272a5eSJohn Baldwin tlsp->scmd0.ivgen_hdrlen = V_SCMD_IV_GEN_CTRL(0) | 237*4f272a5eSJohn Baldwin V_SCMD_TLS_FRAG_ENABLE(0); 238*4f272a5eSJohn Baldwin if (tlsp->inline_key) 239*4f272a5eSJohn Baldwin tlsp->scmd0.ivgen_hdrlen |= V_SCMD_KEY_CTX_INLINE(1); 240*4f272a5eSJohn Baldwin 241*4f272a5eSJohn Baldwin /* 242*4f272a5eSJohn Baldwin * The SCMD fields used when encrypting a partial TLS record 243*4f272a5eSJohn Baldwin * (no trailer and possibly a truncated payload). 244*4f272a5eSJohn Baldwin */ 245*4f272a5eSJohn Baldwin tlsp->scmd0_short.seqno_numivs = V_SCMD_SEQ_NO_CTRL(0) | 246*4f272a5eSJohn Baldwin V_SCMD_PROTO_VERSION(SCMD_PROTO_VERSION_GENERIC) | 247*4f272a5eSJohn Baldwin V_SCMD_ENC_DEC_CTRL(SCMD_ENCDECCTRL_ENCRYPT) | 248*4f272a5eSJohn Baldwin V_SCMD_CIPH_AUTH_SEQ_CTRL((mac_first == 0)) | 249*4f272a5eSJohn Baldwin V_SCMD_AUTH_MODE(SCMD_AUTH_MODE_NOP) | 250*4f272a5eSJohn Baldwin V_SCMD_HMAC_CTRL(SCMD_HMAC_CTRL_NOP) | 251*4f272a5eSJohn Baldwin V_SCMD_IV_SIZE(AES_BLOCK_LEN / 2) | V_SCMD_NUM_IVS(0); 252*4f272a5eSJohn Baldwin if (tlsp->enc_mode == SCMD_CIPH_MODE_AES_GCM) 253*4f272a5eSJohn Baldwin tlsp->scmd0_short.seqno_numivs |= 254*4f272a5eSJohn Baldwin V_SCMD_CIPH_MODE(SCMD_CIPH_MODE_AES_CTR); 255*4f272a5eSJohn Baldwin else 256*4f272a5eSJohn Baldwin tlsp->scmd0_short.seqno_numivs |= 257*4f272a5eSJohn Baldwin V_SCMD_CIPH_MODE(tlsp->enc_mode); 258*4f272a5eSJohn Baldwin tlsp->scmd0_short.seqno_numivs = 259*4f272a5eSJohn Baldwin htobe32(tlsp->scmd0_short.seqno_numivs); 260*4f272a5eSJohn Baldwin 261*4f272a5eSJohn Baldwin tlsp->scmd0_short.ivgen_hdrlen = V_SCMD_IV_GEN_CTRL(0) | 262*4f272a5eSJohn Baldwin V_SCMD_TLS_FRAG_ENABLE(0) | V_SCMD_AADIVDROP(1); 263*4f272a5eSJohn Baldwin if (tlsp->inline_key) 264*4f272a5eSJohn Baldwin tlsp->scmd0_short.ivgen_hdrlen |= V_SCMD_KEY_CTX_INLINE(1); 265*4f272a5eSJohn Baldwin 266*4f272a5eSJohn Baldwin TXQ_LOCK(txq); 267*4f272a5eSJohn Baldwin if (tlsp->enc_mode == SCMD_CIPH_MODE_AES_GCM) 268*4f272a5eSJohn Baldwin txq->kern_tls_gcm++; 269*4f272a5eSJohn Baldwin else 270*4f272a5eSJohn Baldwin txq->kern_tls_cbc++; 271*4f272a5eSJohn Baldwin TXQ_UNLOCK(txq); 272*4f272a5eSJohn Baldwin *pt = &tlsp->com; 273*4f272a5eSJohn Baldwin return (0); 274*4f272a5eSJohn Baldwin 275*4f272a5eSJohn Baldwin failed: 276*4f272a5eSJohn Baldwin m_snd_tag_rele(&tlsp->com); 277*4f272a5eSJohn Baldwin return (error); 278*4f272a5eSJohn Baldwin } 279*4f272a5eSJohn Baldwin 280*4f272a5eSJohn Baldwin static int 281*4f272a5eSJohn Baldwin ktls_setup_keys(struct tlspcb *tlsp, const struct ktls_session *tls, 282*4f272a5eSJohn Baldwin struct sge_txq *txq) 283*4f272a5eSJohn Baldwin { 284*4f272a5eSJohn Baldwin struct tls_key_req *kwr; 285*4f272a5eSJohn Baldwin struct tls_keyctx *kctx; 286*4f272a5eSJohn Baldwin void *items[1]; 287*4f272a5eSJohn Baldwin struct mbuf *m; 288*4f272a5eSJohn Baldwin int error; 289*4f272a5eSJohn Baldwin 290*4f272a5eSJohn Baldwin /* 291*4f272a5eSJohn Baldwin * Store the salt and keys in the key context. For 292*4f272a5eSJohn Baldwin * connections with an inline key, this key context is passed 293*4f272a5eSJohn Baldwin * as immediate data in each work request. For connections 294*4f272a5eSJohn Baldwin * storing the key in DDR, a work request is used to store a 295*4f272a5eSJohn Baldwin * copy of the key context in DDR. 296*4f272a5eSJohn Baldwin */ 297*4f272a5eSJohn Baldwin t4_tls_key_ctx(tls, KTLS_TX, &tlsp->keyctx); 298*4f272a5eSJohn Baldwin if (tlsp->inline_key) 299*4f272a5eSJohn Baldwin return (0); 300*4f272a5eSJohn Baldwin 301*4f272a5eSJohn Baldwin /* Populate key work request. */ 302*4f272a5eSJohn Baldwin m = alloc_wr_mbuf(TLS_KEY_WR_SZ, M_NOWAIT); 303*4f272a5eSJohn Baldwin if (m == NULL) { 304*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p failed to alloc WR mbuf", __func__, 305*4f272a5eSJohn Baldwin tlsp); 306*4f272a5eSJohn Baldwin return (ENOMEM); 307*4f272a5eSJohn Baldwin } 308*4f272a5eSJohn Baldwin m->m_pkthdr.snd_tag = m_snd_tag_ref(&tlsp->com); 309*4f272a5eSJohn Baldwin m->m_pkthdr.csum_flags |= CSUM_SND_TAG; 310*4f272a5eSJohn Baldwin kwr = mtod(m, void *); 311*4f272a5eSJohn Baldwin memset(kwr, 0, TLS_KEY_WR_SZ); 312*4f272a5eSJohn Baldwin 313*4f272a5eSJohn Baldwin t4_write_tlskey_wr(tls, KTLS_TX, 0, 0, tlsp->tx_key_addr, kwr); 314*4f272a5eSJohn Baldwin kctx = (struct tls_keyctx *)(kwr + 1); 315*4f272a5eSJohn Baldwin memcpy(kctx, &tlsp->keyctx, sizeof(*kctx)); 316*4f272a5eSJohn Baldwin 317*4f272a5eSJohn Baldwin /* 318*4f272a5eSJohn Baldwin * Place the key work request in the transmit queue. It 319*4f272a5eSJohn Baldwin * should be sent to the NIC before any TLS packets using this 320*4f272a5eSJohn Baldwin * session. 321*4f272a5eSJohn Baldwin */ 322*4f272a5eSJohn Baldwin items[0] = m; 323*4f272a5eSJohn Baldwin error = mp_ring_enqueue(txq->r, items, 1, 1); 324*4f272a5eSJohn Baldwin if (error) 325*4f272a5eSJohn Baldwin m_free(m); 326*4f272a5eSJohn Baldwin else 327*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p sent key WR", __func__, tlsp); 328*4f272a5eSJohn Baldwin return (error); 329*4f272a5eSJohn Baldwin } 330*4f272a5eSJohn Baldwin 331*4f272a5eSJohn Baldwin static u_int 332*4f272a5eSJohn Baldwin ktls_base_wr_size(struct tlspcb *tlsp) 333*4f272a5eSJohn Baldwin { 334*4f272a5eSJohn Baldwin u_int wr_len; 335*4f272a5eSJohn Baldwin 336*4f272a5eSJohn Baldwin wr_len = sizeof(struct fw_ulptx_wr); // 16 337*4f272a5eSJohn Baldwin wr_len += sizeof(struct ulp_txpkt); // 8 338*4f272a5eSJohn Baldwin wr_len += sizeof(struct ulptx_idata); // 8 339*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_tx_sec_pdu);// 32 340*4f272a5eSJohn Baldwin if (tlsp->inline_key) 341*4f272a5eSJohn Baldwin wr_len += tlsp->tx_key_info_size; 342*4f272a5eSJohn Baldwin else { 343*4f272a5eSJohn Baldwin wr_len += sizeof(struct ulptx_sc_memrd);// 8 344*4f272a5eSJohn Baldwin wr_len += sizeof(struct ulptx_idata); // 8 345*4f272a5eSJohn Baldwin } 346*4f272a5eSJohn Baldwin /* SplitMode CPL_RX_PHYS_DSGL here if needed. */ 347*4f272a5eSJohn Baldwin /* CPL_TX_*_LSO here if needed. */ 348*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_tx_pkt_core);// 16 349*4f272a5eSJohn Baldwin return (wr_len); 350*4f272a5eSJohn Baldwin } 351*4f272a5eSJohn Baldwin 352*4f272a5eSJohn Baldwin static u_int 353*4f272a5eSJohn Baldwin ktls_sgl_size(u_int nsegs) 354*4f272a5eSJohn Baldwin { 355*4f272a5eSJohn Baldwin u_int wr_len; 356*4f272a5eSJohn Baldwin 357*4f272a5eSJohn Baldwin /* First segment is part of ulptx_sgl. */ 358*4f272a5eSJohn Baldwin nsegs--; 359*4f272a5eSJohn Baldwin 360*4f272a5eSJohn Baldwin wr_len = sizeof(struct ulptx_sgl); 361*4f272a5eSJohn Baldwin wr_len += 8 * ((3 * nsegs) / 2 + (nsegs & 1)); 362*4f272a5eSJohn Baldwin return (wr_len); 363*4f272a5eSJohn Baldwin } 364*4f272a5eSJohn Baldwin 365*4f272a5eSJohn Baldwin /* 366*4f272a5eSJohn Baldwin * A request that doesn't need to generate the TLS trailer is a short 367*4f272a5eSJohn Baldwin * record. For these requests, part of the TLS record payload is 368*4f272a5eSJohn Baldwin * encrypted without invoking the MAC. 369*4f272a5eSJohn Baldwin * 370*4f272a5eSJohn Baldwin * Returns true if this record should be sent as a short record. In 371*4f272a5eSJohn Baldwin * either case, the remaining outputs describe the how much of the 372*4f272a5eSJohn Baldwin * TLS record to send as input to the crypto block and the amount of 373*4f272a5eSJohn Baldwin * crypto output to trim via SplitMode: 374*4f272a5eSJohn Baldwin * 375*4f272a5eSJohn Baldwin * *header_len - Number of bytes of TLS header to pass as immediate 376*4f272a5eSJohn Baldwin * data 377*4f272a5eSJohn Baldwin * 378*4f272a5eSJohn Baldwin * *offset - Start offset of TLS record payload to pass as DSGL data 379*4f272a5eSJohn Baldwin * 380*4f272a5eSJohn Baldwin * *plen - Length of TLS record payload to pass as DSGL data 381*4f272a5eSJohn Baldwin * 382*4f272a5eSJohn Baldwin * *leading_waste - amount of non-packet-header bytes to drop at the 383*4f272a5eSJohn Baldwin * start of the crypto output 384*4f272a5eSJohn Baldwin * 385*4f272a5eSJohn Baldwin * *trailing_waste - amount of crypto output to drop from the end 386*4f272a5eSJohn Baldwin */ 387*4f272a5eSJohn Baldwin static bool 388*4f272a5eSJohn Baldwin ktls_is_short_record(struct tlspcb *tlsp, struct mbuf *m_tls, 389*4f272a5eSJohn Baldwin u_int tlen, u_int *header_len, u_int *offset, u_int *plen, 390*4f272a5eSJohn Baldwin u_int *leading_waste, u_int *trailing_waste) 391*4f272a5eSJohn Baldwin { 392*4f272a5eSJohn Baldwin const struct tls_record_layer *hdr; 393*4f272a5eSJohn Baldwin u_int new_tlen, rlen; 394*4f272a5eSJohn Baldwin 395*4f272a5eSJohn Baldwin MPASS(tlen > m_tls->m_epg_hdrlen); 396*4f272a5eSJohn Baldwin 397*4f272a5eSJohn Baldwin hdr = (void *)m_tls->m_epg_hdr; 398*4f272a5eSJohn Baldwin rlen = TLS_HEADER_LENGTH + ntohs(hdr->tls_length); 399*4f272a5eSJohn Baldwin 400*4f272a5eSJohn Baldwin /* 401*4f272a5eSJohn Baldwin * Default to sending the full record as input to the crypto 402*4f272a5eSJohn Baldwin * engine and relying on SplitMode to drop any waste. 403*4f272a5eSJohn Baldwin */ 404*4f272a5eSJohn Baldwin *header_len = m_tls->m_epg_hdrlen; 405*4f272a5eSJohn Baldwin *offset = 0; 406*4f272a5eSJohn Baldwin *plen = rlen - (m_tls->m_epg_hdrlen + m_tls->m_epg_trllen); 407*4f272a5eSJohn Baldwin *leading_waste = mtod(m_tls, vm_offset_t); 408*4f272a5eSJohn Baldwin *trailing_waste = rlen - tlen; 409*4f272a5eSJohn Baldwin if (!tlsp->sc->tlst.short_records) 410*4f272a5eSJohn Baldwin return (false); 411*4f272a5eSJohn Baldwin 412*4f272a5eSJohn Baldwin if (tlsp->enc_mode == SCMD_CIPH_MODE_AES_CBC) { 413*4f272a5eSJohn Baldwin /* 414*4f272a5eSJohn Baldwin * For AES-CBC we have to send input from the start of 415*4f272a5eSJohn Baldwin * the TLS record payload that is a multiple of the 416*4f272a5eSJohn Baldwin * block size. new_tlen rounds up tlen to the end of 417*4f272a5eSJohn Baldwin * the containing AES block. If this last block 418*4f272a5eSJohn Baldwin * overlaps with the trailer, send the full record to 419*4f272a5eSJohn Baldwin * generate the MAC. 420*4f272a5eSJohn Baldwin */ 421*4f272a5eSJohn Baldwin new_tlen = TLS_HEADER_LENGTH + 422*4f272a5eSJohn Baldwin roundup2(tlen - TLS_HEADER_LENGTH, AES_BLOCK_LEN); 423*4f272a5eSJohn Baldwin if (rlen - new_tlen < m_tls->m_epg_trllen) 424*4f272a5eSJohn Baldwin return (false); 425*4f272a5eSJohn Baldwin 426*4f272a5eSJohn Baldwin *trailing_waste = new_tlen - tlen; 427*4f272a5eSJohn Baldwin *plen = new_tlen - m_tls->m_epg_hdrlen; 428*4f272a5eSJohn Baldwin } else { 429*4f272a5eSJohn Baldwin /* 430*4f272a5eSJohn Baldwin * For AES-GCM we have to send the full record if 431*4f272a5eSJohn Baldwin * the end overlaps with the trailer. Otherwise, we 432*4f272a5eSJohn Baldwin * can use AES-CTR to encrypt a partial PDU. 433*4f272a5eSJohn Baldwin */ 434*4f272a5eSJohn Baldwin if (rlen - tlen < m_tls->m_epg_trllen) 435*4f272a5eSJohn Baldwin return (false); 436*4f272a5eSJohn Baldwin 437*4f272a5eSJohn Baldwin /* 438*4f272a5eSJohn Baldwin * The last record can be partially encrypted via 439*4f272a5eSJohn Baldwin * AES-CTR without any trailing waste. 440*4f272a5eSJohn Baldwin */ 441*4f272a5eSJohn Baldwin *trailing_waste = 0; 442*4f272a5eSJohn Baldwin *plen = tlen - m_tls->m_epg_hdrlen; 443*4f272a5eSJohn Baldwin 444*4f272a5eSJohn Baldwin /* 445*4f272a5eSJohn Baldwin * In addition, with AES-CTR, we can minimize leading 446*4f272a5eSJohn Baldwin * waste by starting encryption at the start of the 447*4f272a5eSJohn Baldwin * closest AES block. 448*4f272a5eSJohn Baldwin */ 449*4f272a5eSJohn Baldwin if (mtod(m_tls, vm_offset_t) >= m_tls->m_epg_hdrlen) { 450*4f272a5eSJohn Baldwin *header_len = 0; 451*4f272a5eSJohn Baldwin *offset = rounddown2(mtod(m_tls, vm_offset_t) - 452*4f272a5eSJohn Baldwin m_tls->m_epg_hdrlen, AES_BLOCK_LEN); 453*4f272a5eSJohn Baldwin *plen -= *offset; 454*4f272a5eSJohn Baldwin *leading_waste -= (m_tls->m_epg_hdrlen + *offset); 455*4f272a5eSJohn Baldwin } 456*4f272a5eSJohn Baldwin } 457*4f272a5eSJohn Baldwin return (true); 458*4f272a5eSJohn Baldwin } 459*4f272a5eSJohn Baldwin 460*4f272a5eSJohn Baldwin static int 461*4f272a5eSJohn Baldwin ktls_wr_len(struct tlspcb *tlsp, struct mbuf *m, struct mbuf *m_tls, 462*4f272a5eSJohn Baldwin int *nsegsp) 463*4f272a5eSJohn Baldwin { 464*4f272a5eSJohn Baldwin u_int header_len, imm_len, offset, plen, tlen, wr_len; 465*4f272a5eSJohn Baldwin u_int leading_waste, trailing_waste; 466*4f272a5eSJohn Baldwin bool short_record; 467*4f272a5eSJohn Baldwin 468*4f272a5eSJohn Baldwin M_ASSERTEXTPG(m_tls); 469*4f272a5eSJohn Baldwin 470*4f272a5eSJohn Baldwin /* 471*4f272a5eSJohn Baldwin * The relative offset of the last byte to send from the TLS 472*4f272a5eSJohn Baldwin * record. 473*4f272a5eSJohn Baldwin */ 474*4f272a5eSJohn Baldwin tlen = mtod(m_tls, vm_offset_t) + m_tls->m_len; 475*4f272a5eSJohn Baldwin if (tlen <= m_tls->m_epg_hdrlen) { 476*4f272a5eSJohn Baldwin /* 477*4f272a5eSJohn Baldwin * For requests that only want to send the TLS header, 478*4f272a5eSJohn Baldwin * send a tunnelled packet as immediate data. 479*4f272a5eSJohn Baldwin */ 480*4f272a5eSJohn Baldwin wr_len = sizeof(struct fw_eth_tx_pkt_wr) + 481*4f272a5eSJohn Baldwin sizeof(struct cpl_tx_pkt_core) + 482*4f272a5eSJohn Baldwin roundup2(m->m_len + m_tls->m_len, 16); 483*4f272a5eSJohn Baldwin if (wr_len > SGE_MAX_WR_LEN) { 484*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, 485*4f272a5eSJohn Baldwin "%s: %p TLS header-only packet too long (len %d)", 486*4f272a5eSJohn Baldwin __func__, tlsp, m->m_len + m_tls->m_len); 487*4f272a5eSJohn Baldwin } 488*4f272a5eSJohn Baldwin 489*4f272a5eSJohn Baldwin /* This should always be the last TLS record in a chain. */ 490*4f272a5eSJohn Baldwin MPASS(m_tls->m_next == NULL); 491*4f272a5eSJohn Baldwin *nsegsp = 0; 492*4f272a5eSJohn Baldwin return (wr_len); 493*4f272a5eSJohn Baldwin } 494*4f272a5eSJohn Baldwin 495*4f272a5eSJohn Baldwin short_record = ktls_is_short_record(tlsp, m_tls, tlen, &header_len, 496*4f272a5eSJohn Baldwin &offset, &plen, &leading_waste, &trailing_waste); 497*4f272a5eSJohn Baldwin 498*4f272a5eSJohn Baldwin /* Calculate the size of the work request. */ 499*4f272a5eSJohn Baldwin wr_len = ktls_base_wr_size(tlsp); 500*4f272a5eSJohn Baldwin 501*4f272a5eSJohn Baldwin if (leading_waste != 0 || trailing_waste != 0) { 502*4f272a5eSJohn Baldwin /* 503*4f272a5eSJohn Baldwin * Partial records might require a SplitMode 504*4f272a5eSJohn Baldwin * CPL_RX_PHYS_DSGL. 505*4f272a5eSJohn Baldwin */ 506*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_t7_rx_phys_dsgl); 507*4f272a5eSJohn Baldwin } 508*4f272a5eSJohn Baldwin 509*4f272a5eSJohn Baldwin /* Budget for an LSO header even if we don't use it. */ 510*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_tx_pkt_lso_core); 511*4f272a5eSJohn Baldwin 512*4f272a5eSJohn Baldwin /* 513*4f272a5eSJohn Baldwin * Headers (including the TLS header) are always sent as 514*4f272a5eSJohn Baldwin * immediate data. Short records include a raw AES IV as 515*4f272a5eSJohn Baldwin * immediate data. 516*4f272a5eSJohn Baldwin */ 517*4f272a5eSJohn Baldwin imm_len = m->m_len + header_len; 518*4f272a5eSJohn Baldwin if (short_record) 519*4f272a5eSJohn Baldwin imm_len += AES_BLOCK_LEN; 520*4f272a5eSJohn Baldwin wr_len += roundup2(imm_len, 16); 521*4f272a5eSJohn Baldwin 522*4f272a5eSJohn Baldwin /* TLS record payload via DSGL. */ 523*4f272a5eSJohn Baldwin *nsegsp = sglist_count_mbuf_epg(m_tls, m_tls->m_epg_hdrlen + offset, 524*4f272a5eSJohn Baldwin plen); 525*4f272a5eSJohn Baldwin wr_len += ktls_sgl_size(*nsegsp); 526*4f272a5eSJohn Baldwin 527*4f272a5eSJohn Baldwin wr_len = roundup2(wr_len, 16); 528*4f272a5eSJohn Baldwin return (wr_len); 529*4f272a5eSJohn Baldwin } 530*4f272a5eSJohn Baldwin 531*4f272a5eSJohn Baldwin int 532*4f272a5eSJohn Baldwin t7_ktls_parse_pkt(struct mbuf *m) 533*4f272a5eSJohn Baldwin { 534*4f272a5eSJohn Baldwin struct tlspcb *tlsp; 535*4f272a5eSJohn Baldwin struct ether_header *eh; 536*4f272a5eSJohn Baldwin struct ip *ip; 537*4f272a5eSJohn Baldwin struct ip6_hdr *ip6; 538*4f272a5eSJohn Baldwin struct tcphdr *tcp; 539*4f272a5eSJohn Baldwin struct mbuf *m_tls; 540*4f272a5eSJohn Baldwin void *items[1]; 541*4f272a5eSJohn Baldwin int nsegs; 542*4f272a5eSJohn Baldwin u_int wr_len, tot_len; 543*4f272a5eSJohn Baldwin uint16_t eh_type; 544*4f272a5eSJohn Baldwin 545*4f272a5eSJohn Baldwin /* 546*4f272a5eSJohn Baldwin * Locate headers in initial mbuf. 547*4f272a5eSJohn Baldwin * 548*4f272a5eSJohn Baldwin * XXX: This assumes all of the headers are in the initial mbuf. 549*4f272a5eSJohn Baldwin * Could perhaps use m_advance() like parse_pkt() if that turns 550*4f272a5eSJohn Baldwin * out to not be true. 551*4f272a5eSJohn Baldwin */ 552*4f272a5eSJohn Baldwin M_ASSERTPKTHDR(m); 553*4f272a5eSJohn Baldwin MPASS(m->m_pkthdr.snd_tag != NULL); 554*4f272a5eSJohn Baldwin tlsp = mst_to_tls(m->m_pkthdr.snd_tag); 555*4f272a5eSJohn Baldwin 556*4f272a5eSJohn Baldwin if (m->m_len <= sizeof(*eh) + sizeof(*ip)) { 557*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p header mbuf too short", __func__, tlsp); 558*4f272a5eSJohn Baldwin return (EINVAL); 559*4f272a5eSJohn Baldwin } 560*4f272a5eSJohn Baldwin eh = mtod(m, struct ether_header *); 561*4f272a5eSJohn Baldwin eh_type = ntohs(eh->ether_type); 562*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_VLAN) { 563*4f272a5eSJohn Baldwin struct ether_vlan_header *evh = (void *)eh; 564*4f272a5eSJohn Baldwin 565*4f272a5eSJohn Baldwin eh_type = ntohs(evh->evl_proto); 566*4f272a5eSJohn Baldwin m->m_pkthdr.l2hlen = sizeof(*evh); 567*4f272a5eSJohn Baldwin } else 568*4f272a5eSJohn Baldwin m->m_pkthdr.l2hlen = sizeof(*eh); 569*4f272a5eSJohn Baldwin 570*4f272a5eSJohn Baldwin switch (eh_type) { 571*4f272a5eSJohn Baldwin case ETHERTYPE_IP: 572*4f272a5eSJohn Baldwin ip = (struct ip *)(eh + 1); 573*4f272a5eSJohn Baldwin if (ip->ip_p != IPPROTO_TCP) { 574*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p mbuf not IPPROTO_TCP", __func__, 575*4f272a5eSJohn Baldwin tlsp); 576*4f272a5eSJohn Baldwin return (EINVAL); 577*4f272a5eSJohn Baldwin } 578*4f272a5eSJohn Baldwin m->m_pkthdr.l3hlen = ip->ip_hl * 4; 579*4f272a5eSJohn Baldwin break; 580*4f272a5eSJohn Baldwin case ETHERTYPE_IPV6: 581*4f272a5eSJohn Baldwin ip6 = (struct ip6_hdr *)(eh + 1); 582*4f272a5eSJohn Baldwin if (ip6->ip6_nxt != IPPROTO_TCP) { 583*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p, mbuf not IPPROTO_TCP (%u)", 584*4f272a5eSJohn Baldwin __func__, tlsp, ip6->ip6_nxt); 585*4f272a5eSJohn Baldwin return (EINVAL); 586*4f272a5eSJohn Baldwin } 587*4f272a5eSJohn Baldwin m->m_pkthdr.l3hlen = sizeof(struct ip6_hdr); 588*4f272a5eSJohn Baldwin break; 589*4f272a5eSJohn Baldwin default: 590*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p mbuf not ETHERTYPE_IP{,V6}", __func__, 591*4f272a5eSJohn Baldwin tlsp); 592*4f272a5eSJohn Baldwin return (EINVAL); 593*4f272a5eSJohn Baldwin } 594*4f272a5eSJohn Baldwin if (m->m_len < m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen + 595*4f272a5eSJohn Baldwin sizeof(*tcp)) { 596*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p header mbuf too short (2)", __func__, 597*4f272a5eSJohn Baldwin tlsp); 598*4f272a5eSJohn Baldwin return (EINVAL); 599*4f272a5eSJohn Baldwin } 600*4f272a5eSJohn Baldwin tcp = (struct tcphdr *)((char *)(eh + 1) + m->m_pkthdr.l3hlen); 601*4f272a5eSJohn Baldwin m->m_pkthdr.l4hlen = tcp->th_off * 4; 602*4f272a5eSJohn Baldwin 603*4f272a5eSJohn Baldwin /* Bail if there is TCP payload before the TLS record. */ 604*4f272a5eSJohn Baldwin if (m->m_len != m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen + 605*4f272a5eSJohn Baldwin m->m_pkthdr.l4hlen) { 606*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, 607*4f272a5eSJohn Baldwin "%s: %p header mbuf bad length (%d + %d + %d != %d)", 608*4f272a5eSJohn Baldwin __func__, tlsp, m->m_pkthdr.l2hlen, m->m_pkthdr.l3hlen, 609*4f272a5eSJohn Baldwin m->m_pkthdr.l4hlen, m->m_len); 610*4f272a5eSJohn Baldwin return (EINVAL); 611*4f272a5eSJohn Baldwin } 612*4f272a5eSJohn Baldwin 613*4f272a5eSJohn Baldwin /* Assume all headers are in 'm' for now. */ 614*4f272a5eSJohn Baldwin MPASS(m->m_next != NULL); 615*4f272a5eSJohn Baldwin MPASS(m->m_next->m_flags & M_EXTPG); 616*4f272a5eSJohn Baldwin 617*4f272a5eSJohn Baldwin tot_len = 0; 618*4f272a5eSJohn Baldwin 619*4f272a5eSJohn Baldwin /* 620*4f272a5eSJohn Baldwin * Each of the remaining mbufs in the chain should reference a 621*4f272a5eSJohn Baldwin * TLS record. 622*4f272a5eSJohn Baldwin */ 623*4f272a5eSJohn Baldwin for (m_tls = m->m_next; m_tls != NULL; m_tls = m_tls->m_next) { 624*4f272a5eSJohn Baldwin MPASS(m_tls->m_flags & M_EXTPG); 625*4f272a5eSJohn Baldwin 626*4f272a5eSJohn Baldwin wr_len = ktls_wr_len(tlsp, m, m_tls, &nsegs); 627*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 628*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p wr_len %d nsegs %d", __func__, tlsp, 629*4f272a5eSJohn Baldwin wr_len, nsegs); 630*4f272a5eSJohn Baldwin #endif 631*4f272a5eSJohn Baldwin if (wr_len > SGE_MAX_WR_LEN || nsegs > TX_SGL_SEGS) 632*4f272a5eSJohn Baldwin return (EFBIG); 633*4f272a5eSJohn Baldwin tot_len += roundup2(wr_len, EQ_ESIZE); 634*4f272a5eSJohn Baldwin 635*4f272a5eSJohn Baldwin /* 636*4f272a5eSJohn Baldwin * Store 'nsegs' for the first TLS record in the 637*4f272a5eSJohn Baldwin * header mbuf's metadata. 638*4f272a5eSJohn Baldwin */ 639*4f272a5eSJohn Baldwin if (m_tls == m->m_next) 640*4f272a5eSJohn Baldwin set_mbuf_nsegs(m, nsegs); 641*4f272a5eSJohn Baldwin } 642*4f272a5eSJohn Baldwin 643*4f272a5eSJohn Baldwin MPASS(tot_len != 0); 644*4f272a5eSJohn Baldwin 645*4f272a5eSJohn Baldwin set_mbuf_len16(m, tot_len / 16); 646*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 647*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p len16 %d nsegs %d", __func__, tlsp, 648*4f272a5eSJohn Baldwin mbuf_len16(m), mbuf_nsegs(m)); 649*4f272a5eSJohn Baldwin #endif 650*4f272a5eSJohn Baldwin items[0] = m; 651*4f272a5eSJohn Baldwin return (mp_ring_enqueue(tlsp->txq->r, items, 1, 256)); 652*4f272a5eSJohn Baldwin } 653*4f272a5eSJohn Baldwin 654*4f272a5eSJohn Baldwin static inline bool 655*4f272a5eSJohn Baldwin needs_vlan_insertion(struct mbuf *m) 656*4f272a5eSJohn Baldwin { 657*4f272a5eSJohn Baldwin 658*4f272a5eSJohn Baldwin M_ASSERTPKTHDR(m); 659*4f272a5eSJohn Baldwin 660*4f272a5eSJohn Baldwin return (m->m_flags & M_VLANTAG); 661*4f272a5eSJohn Baldwin } 662*4f272a5eSJohn Baldwin 663*4f272a5eSJohn Baldwin static inline uint64_t 664*4f272a5eSJohn Baldwin pkt_ctrl1(struct sge_txq *txq, struct mbuf *m, uint16_t eh_type) 665*4f272a5eSJohn Baldwin { 666*4f272a5eSJohn Baldwin uint64_t ctrl1; 667*4f272a5eSJohn Baldwin 668*4f272a5eSJohn Baldwin /* Checksums are always offloaded */ 669*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_IP) { 670*4f272a5eSJohn Baldwin ctrl1 = V_TXPKT_CSUM_TYPE(TX_CSUM_TCPIP) | 671*4f272a5eSJohn Baldwin V_T6_TXPKT_ETHHDR_LEN(m->m_pkthdr.l2hlen - ETHER_HDR_LEN) | 672*4f272a5eSJohn Baldwin V_TXPKT_IPHDR_LEN(m->m_pkthdr.l3hlen); 673*4f272a5eSJohn Baldwin } else { 674*4f272a5eSJohn Baldwin MPASS(m->m_pkthdr.l3hlen == sizeof(struct ip6_hdr)); 675*4f272a5eSJohn Baldwin ctrl1 = V_TXPKT_CSUM_TYPE(TX_CSUM_TCPIP6) | 676*4f272a5eSJohn Baldwin V_T6_TXPKT_ETHHDR_LEN(m->m_pkthdr.l2hlen - ETHER_HDR_LEN) | 677*4f272a5eSJohn Baldwin V_TXPKT_IPHDR_LEN(m->m_pkthdr.l3hlen); 678*4f272a5eSJohn Baldwin } 679*4f272a5eSJohn Baldwin txq->txcsum++; 680*4f272a5eSJohn Baldwin 681*4f272a5eSJohn Baldwin /* VLAN tag insertion */ 682*4f272a5eSJohn Baldwin if (needs_vlan_insertion(m)) { 683*4f272a5eSJohn Baldwin ctrl1 |= F_TXPKT_VLAN_VLD | 684*4f272a5eSJohn Baldwin V_TXPKT_VLAN(m->m_pkthdr.ether_vtag); 685*4f272a5eSJohn Baldwin txq->vlan_insertion++; 686*4f272a5eSJohn Baldwin } 687*4f272a5eSJohn Baldwin 688*4f272a5eSJohn Baldwin return (ctrl1); 689*4f272a5eSJohn Baldwin } 690*4f272a5eSJohn Baldwin 691*4f272a5eSJohn Baldwin static inline void * 692*4f272a5eSJohn Baldwin write_lso_cpl(void *cpl, struct mbuf *m0, uint16_t mss, uint16_t eh_type, 693*4f272a5eSJohn Baldwin int total_len) 694*4f272a5eSJohn Baldwin { 695*4f272a5eSJohn Baldwin struct cpl_tx_pkt_lso_core *lso; 696*4f272a5eSJohn Baldwin uint32_t ctrl; 697*4f272a5eSJohn Baldwin 698*4f272a5eSJohn Baldwin KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0 && 699*4f272a5eSJohn Baldwin m0->m_pkthdr.l4hlen > 0, 700*4f272a5eSJohn Baldwin ("%s: mbuf %p needs TSO but missing header lengths", 701*4f272a5eSJohn Baldwin __func__, m0)); 702*4f272a5eSJohn Baldwin 703*4f272a5eSJohn Baldwin ctrl = V_LSO_OPCODE(CPL_TX_PKT_LSO) | 704*4f272a5eSJohn Baldwin F_LSO_FIRST_SLICE | F_LSO_LAST_SLICE | 705*4f272a5eSJohn Baldwin V_LSO_ETHHDR_LEN((m0->m_pkthdr.l2hlen - ETHER_HDR_LEN) >> 2) | 706*4f272a5eSJohn Baldwin V_LSO_IPHDR_LEN(m0->m_pkthdr.l3hlen >> 2) | 707*4f272a5eSJohn Baldwin V_LSO_TCPHDR_LEN(m0->m_pkthdr.l4hlen >> 2); 708*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_IPV6) 709*4f272a5eSJohn Baldwin ctrl |= F_LSO_IPV6; 710*4f272a5eSJohn Baldwin 711*4f272a5eSJohn Baldwin lso = cpl; 712*4f272a5eSJohn Baldwin lso->lso_ctrl = htobe32(ctrl); 713*4f272a5eSJohn Baldwin lso->ipid_ofst = htobe16(0); 714*4f272a5eSJohn Baldwin lso->mss = htobe16(mss); 715*4f272a5eSJohn Baldwin lso->seqno_offset = htobe32(0); 716*4f272a5eSJohn Baldwin lso->len = htobe32(total_len); 717*4f272a5eSJohn Baldwin 718*4f272a5eSJohn Baldwin return (lso + 1); 719*4f272a5eSJohn Baldwin } 720*4f272a5eSJohn Baldwin 721*4f272a5eSJohn Baldwin static inline void * 722*4f272a5eSJohn Baldwin write_split_mode_rx_phys(void *dst, struct mbuf *m, struct mbuf *m_tls, 723*4f272a5eSJohn Baldwin u_int crypto_hdr_len, u_int leading_waste, u_int trailing_waste) 724*4f272a5eSJohn Baldwin { 725*4f272a5eSJohn Baldwin struct cpl_t7_rx_phys_dsgl *cpl; 726*4f272a5eSJohn Baldwin uint16_t *len; 727*4f272a5eSJohn Baldwin uint8_t numsge; 728*4f272a5eSJohn Baldwin 729*4f272a5eSJohn Baldwin /* Forward first (3) and third (1) segments. */ 730*4f272a5eSJohn Baldwin numsge = 0xa; 731*4f272a5eSJohn Baldwin 732*4f272a5eSJohn Baldwin cpl = dst; 733*4f272a5eSJohn Baldwin cpl->ot.opcode = CPL_RX_PHYS_DSGL; 734*4f272a5eSJohn Baldwin cpl->PhysAddrFields_lo_to_NumSGE = 735*4f272a5eSJohn Baldwin htobe32(F_CPL_T7_RX_PHYS_DSGL_SPLITMODE | 736*4f272a5eSJohn Baldwin V_CPL_T7_RX_PHYS_DSGL_NUMSGE(numsge)); 737*4f272a5eSJohn Baldwin 738*4f272a5eSJohn Baldwin len = (uint16_t *)(cpl->RSSCopy); 739*4f272a5eSJohn Baldwin 740*4f272a5eSJohn Baldwin /* 741*4f272a5eSJohn Baldwin * First segment always contains packet headers as well as 742*4f272a5eSJohn Baldwin * transmit-related CPLs. 743*4f272a5eSJohn Baldwin */ 744*4f272a5eSJohn Baldwin len[0] = htobe16(crypto_hdr_len); 745*4f272a5eSJohn Baldwin 746*4f272a5eSJohn Baldwin /* 747*4f272a5eSJohn Baldwin * Second segment is "gap" of data to drop at the front of the 748*4f272a5eSJohn Baldwin * TLS record. 749*4f272a5eSJohn Baldwin */ 750*4f272a5eSJohn Baldwin len[1] = htobe16(leading_waste); 751*4f272a5eSJohn Baldwin 752*4f272a5eSJohn Baldwin /* Third segment is how much of the TLS record to send. */ 753*4f272a5eSJohn Baldwin len[2] = htobe16(m_tls->m_len); 754*4f272a5eSJohn Baldwin 755*4f272a5eSJohn Baldwin /* Fourth segment is how much data to drop at the end. */ 756*4f272a5eSJohn Baldwin len[3] = htobe16(trailing_waste); 757*4f272a5eSJohn Baldwin 758*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 759*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: forward %u skip %u forward %u skip %u", 760*4f272a5eSJohn Baldwin __func__, be16toh(len[0]), be16toh(len[1]), be16toh(len[2]), 761*4f272a5eSJohn Baldwin be16toh(len[3])); 762*4f272a5eSJohn Baldwin #endif 763*4f272a5eSJohn Baldwin return (cpl + 1); 764*4f272a5eSJohn Baldwin } 765*4f272a5eSJohn Baldwin 766*4f272a5eSJohn Baldwin /* 767*4f272a5eSJohn Baldwin * If the SGL ends on an address that is not 16 byte aligned, this function will 768*4f272a5eSJohn Baldwin * add a 0 filled flit at the end. 769*4f272a5eSJohn Baldwin */ 770*4f272a5eSJohn Baldwin static void 771*4f272a5eSJohn Baldwin write_gl_to_buf(struct sglist *gl, caddr_t to) 772*4f272a5eSJohn Baldwin { 773*4f272a5eSJohn Baldwin struct sglist_seg *seg; 774*4f272a5eSJohn Baldwin __be64 *flitp; 775*4f272a5eSJohn Baldwin struct ulptx_sgl *usgl; 776*4f272a5eSJohn Baldwin int i, nflits, nsegs; 777*4f272a5eSJohn Baldwin 778*4f272a5eSJohn Baldwin KASSERT(((uintptr_t)to & 0xf) == 0, 779*4f272a5eSJohn Baldwin ("%s: SGL must start at a 16 byte boundary: %p", __func__, to)); 780*4f272a5eSJohn Baldwin 781*4f272a5eSJohn Baldwin nsegs = gl->sg_nseg; 782*4f272a5eSJohn Baldwin MPASS(nsegs > 0); 783*4f272a5eSJohn Baldwin 784*4f272a5eSJohn Baldwin nflits = (3 * (nsegs - 1)) / 2 + ((nsegs - 1) & 1) + 2; 785*4f272a5eSJohn Baldwin flitp = (__be64 *)to; 786*4f272a5eSJohn Baldwin seg = &gl->sg_segs[0]; 787*4f272a5eSJohn Baldwin usgl = (void *)flitp; 788*4f272a5eSJohn Baldwin 789*4f272a5eSJohn Baldwin usgl->cmd_nsge = htobe32(V_ULPTX_CMD(ULP_TX_SC_DSGL) | 790*4f272a5eSJohn Baldwin V_ULPTX_NSGE(nsegs)); 791*4f272a5eSJohn Baldwin usgl->len0 = htobe32(seg->ss_len); 792*4f272a5eSJohn Baldwin usgl->addr0 = htobe64(seg->ss_paddr); 793*4f272a5eSJohn Baldwin seg++; 794*4f272a5eSJohn Baldwin 795*4f272a5eSJohn Baldwin for (i = 0; i < nsegs - 1; i++, seg++) { 796*4f272a5eSJohn Baldwin usgl->sge[i / 2].len[i & 1] = htobe32(seg->ss_len); 797*4f272a5eSJohn Baldwin usgl->sge[i / 2].addr[i & 1] = htobe64(seg->ss_paddr); 798*4f272a5eSJohn Baldwin } 799*4f272a5eSJohn Baldwin if (i & 1) 800*4f272a5eSJohn Baldwin usgl->sge[i / 2].len[1] = htobe32(0); 801*4f272a5eSJohn Baldwin flitp += nflits; 802*4f272a5eSJohn Baldwin 803*4f272a5eSJohn Baldwin if (nflits & 1) { 804*4f272a5eSJohn Baldwin MPASS(((uintptr_t)flitp) & 0xf); 805*4f272a5eSJohn Baldwin *flitp++ = 0; 806*4f272a5eSJohn Baldwin } 807*4f272a5eSJohn Baldwin 808*4f272a5eSJohn Baldwin MPASS((((uintptr_t)flitp) & 0xf) == 0); 809*4f272a5eSJohn Baldwin } 810*4f272a5eSJohn Baldwin 811*4f272a5eSJohn Baldwin static inline void 812*4f272a5eSJohn Baldwin copy_to_txd(struct sge_eq *eq, caddr_t from, caddr_t *to, int len) 813*4f272a5eSJohn Baldwin { 814*4f272a5eSJohn Baldwin 815*4f272a5eSJohn Baldwin MPASS((uintptr_t)(*to) >= (uintptr_t)&eq->desc[0]); 816*4f272a5eSJohn Baldwin MPASS((uintptr_t)(*to) < (uintptr_t)&eq->desc[eq->sidx]); 817*4f272a5eSJohn Baldwin 818*4f272a5eSJohn Baldwin if (__predict_true((uintptr_t)(*to) + len <= 819*4f272a5eSJohn Baldwin (uintptr_t)&eq->desc[eq->sidx])) { 820*4f272a5eSJohn Baldwin bcopy(from, *to, len); 821*4f272a5eSJohn Baldwin (*to) += len; 822*4f272a5eSJohn Baldwin if ((uintptr_t)(*to) == (uintptr_t)&eq->desc[eq->sidx]) 823*4f272a5eSJohn Baldwin (*to) = (caddr_t)eq->desc; 824*4f272a5eSJohn Baldwin } else { 825*4f272a5eSJohn Baldwin int portion = (uintptr_t)&eq->desc[eq->sidx] - (uintptr_t)(*to); 826*4f272a5eSJohn Baldwin 827*4f272a5eSJohn Baldwin bcopy(from, *to, portion); 828*4f272a5eSJohn Baldwin from += portion; 829*4f272a5eSJohn Baldwin portion = len - portion; /* remaining */ 830*4f272a5eSJohn Baldwin bcopy(from, (void *)eq->desc, portion); 831*4f272a5eSJohn Baldwin (*to) = (caddr_t)eq->desc + portion; 832*4f272a5eSJohn Baldwin } 833*4f272a5eSJohn Baldwin } 834*4f272a5eSJohn Baldwin 835*4f272a5eSJohn Baldwin static int 836*4f272a5eSJohn Baldwin ktls_write_tunnel_packet(struct sge_txq *txq, void *dst, struct mbuf *m, 837*4f272a5eSJohn Baldwin struct mbuf *m_tls, u_int available, tcp_seq tcp_seqno, u_int pidx, 838*4f272a5eSJohn Baldwin uint16_t eh_type) 839*4f272a5eSJohn Baldwin { 840*4f272a5eSJohn Baldwin struct tx_sdesc *txsd; 841*4f272a5eSJohn Baldwin struct fw_eth_tx_pkt_wr *wr; 842*4f272a5eSJohn Baldwin struct cpl_tx_pkt_core *cpl; 843*4f272a5eSJohn Baldwin uint32_t ctrl; 844*4f272a5eSJohn Baldwin int len16, ndesc, pktlen; 845*4f272a5eSJohn Baldwin struct ether_header *eh; 846*4f272a5eSJohn Baldwin struct ip *ip, newip; 847*4f272a5eSJohn Baldwin struct ip6_hdr *ip6, newip6; 848*4f272a5eSJohn Baldwin struct tcphdr *tcp, newtcp; 849*4f272a5eSJohn Baldwin caddr_t out; 850*4f272a5eSJohn Baldwin 851*4f272a5eSJohn Baldwin TXQ_LOCK_ASSERT_OWNED(txq); 852*4f272a5eSJohn Baldwin M_ASSERTPKTHDR(m); 853*4f272a5eSJohn Baldwin 854*4f272a5eSJohn Baldwin /* Locate the template TLS header. */ 855*4f272a5eSJohn Baldwin M_ASSERTEXTPG(m_tls); 856*4f272a5eSJohn Baldwin 857*4f272a5eSJohn Baldwin /* This should always be the last TLS record in a chain. */ 858*4f272a5eSJohn Baldwin MPASS(m_tls->m_next == NULL); 859*4f272a5eSJohn Baldwin 860*4f272a5eSJohn Baldwin wr = dst; 861*4f272a5eSJohn Baldwin pktlen = m->m_len + m_tls->m_len; 862*4f272a5eSJohn Baldwin ctrl = sizeof(struct cpl_tx_pkt_core) + pktlen; 863*4f272a5eSJohn Baldwin len16 = howmany(sizeof(struct fw_eth_tx_pkt_wr) + ctrl, 16); 864*4f272a5eSJohn Baldwin ndesc = tx_len16_to_desc(len16); 865*4f272a5eSJohn Baldwin MPASS(ndesc <= available); 866*4f272a5eSJohn Baldwin 867*4f272a5eSJohn Baldwin /* Firmware work request header */ 868*4f272a5eSJohn Baldwin /* TODO: Handle VF work request. */ 869*4f272a5eSJohn Baldwin wr->op_immdlen = htobe32(V_FW_WR_OP(FW_ETH_TX_PKT_WR) | 870*4f272a5eSJohn Baldwin V_FW_ETH_TX_PKT_WR_IMMDLEN(ctrl)); 871*4f272a5eSJohn Baldwin 872*4f272a5eSJohn Baldwin ctrl = V_FW_WR_LEN16(len16); 873*4f272a5eSJohn Baldwin wr->equiq_to_len16 = htobe32(ctrl); 874*4f272a5eSJohn Baldwin wr->r3 = 0; 875*4f272a5eSJohn Baldwin 876*4f272a5eSJohn Baldwin cpl = (void *)(wr + 1); 877*4f272a5eSJohn Baldwin 878*4f272a5eSJohn Baldwin /* CPL header */ 879*4f272a5eSJohn Baldwin cpl->ctrl0 = txq->cpl_ctrl0; 880*4f272a5eSJohn Baldwin cpl->pack = 0; 881*4f272a5eSJohn Baldwin cpl->len = htobe16(pktlen); 882*4f272a5eSJohn Baldwin 883*4f272a5eSJohn Baldwin out = (void *)(cpl + 1); 884*4f272a5eSJohn Baldwin 885*4f272a5eSJohn Baldwin /* Copy over Ethernet header. */ 886*4f272a5eSJohn Baldwin eh = mtod(m, struct ether_header *); 887*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)eh, &out, m->m_pkthdr.l2hlen); 888*4f272a5eSJohn Baldwin 889*4f272a5eSJohn Baldwin /* Fixup length in IP header and copy out. */ 890*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_IP) { 891*4f272a5eSJohn Baldwin ip = (void *)((char *)eh + m->m_pkthdr.l2hlen); 892*4f272a5eSJohn Baldwin newip = *ip; 893*4f272a5eSJohn Baldwin newip.ip_len = htons(pktlen - m->m_pkthdr.l2hlen); 894*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)&newip, &out, sizeof(newip)); 895*4f272a5eSJohn Baldwin if (m->m_pkthdr.l3hlen > sizeof(*ip)) 896*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)(ip + 1), &out, 897*4f272a5eSJohn Baldwin m->m_pkthdr.l3hlen - sizeof(*ip)); 898*4f272a5eSJohn Baldwin } else { 899*4f272a5eSJohn Baldwin ip6 = (void *)((char *)eh + m->m_pkthdr.l2hlen); 900*4f272a5eSJohn Baldwin newip6 = *ip6; 901*4f272a5eSJohn Baldwin newip6.ip6_plen = htons(pktlen - m->m_pkthdr.l2hlen - 902*4f272a5eSJohn Baldwin sizeof(*ip6)); 903*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)&newip6, &out, sizeof(newip6)); 904*4f272a5eSJohn Baldwin MPASS(m->m_pkthdr.l3hlen == sizeof(*ip6)); 905*4f272a5eSJohn Baldwin } 906*4f272a5eSJohn Baldwin cpl->ctrl1 = htobe64(pkt_ctrl1(txq, m, eh_type)); 907*4f272a5eSJohn Baldwin 908*4f272a5eSJohn Baldwin /* Set sequence number in TCP header. */ 909*4f272a5eSJohn Baldwin tcp = (void *)((char *)eh + m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen); 910*4f272a5eSJohn Baldwin newtcp = *tcp; 911*4f272a5eSJohn Baldwin newtcp.th_seq = htonl(tcp_seqno); 912*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)&newtcp, &out, sizeof(newtcp)); 913*4f272a5eSJohn Baldwin 914*4f272a5eSJohn Baldwin /* Copy rest of TCP header. */ 915*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (caddr_t)(tcp + 1), &out, m->m_len - 916*4f272a5eSJohn Baldwin (m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen + sizeof(*tcp))); 917*4f272a5eSJohn Baldwin 918*4f272a5eSJohn Baldwin /* Copy the subset of the TLS header requested. */ 919*4f272a5eSJohn Baldwin copy_to_txd(&txq->eq, (char *)m_tls->m_epg_hdr + 920*4f272a5eSJohn Baldwin mtod(m_tls, vm_offset_t), &out, m_tls->m_len); 921*4f272a5eSJohn Baldwin txq->imm_wrs++; 922*4f272a5eSJohn Baldwin 923*4f272a5eSJohn Baldwin txq->txpkt_wrs++; 924*4f272a5eSJohn Baldwin 925*4f272a5eSJohn Baldwin txq->kern_tls_header++; 926*4f272a5eSJohn Baldwin 927*4f272a5eSJohn Baldwin txsd = &txq->sdesc[pidx]; 928*4f272a5eSJohn Baldwin txsd->m = m; 929*4f272a5eSJohn Baldwin txsd->desc_used = ndesc; 930*4f272a5eSJohn Baldwin 931*4f272a5eSJohn Baldwin return (ndesc); 932*4f272a5eSJohn Baldwin } 933*4f272a5eSJohn Baldwin 934*4f272a5eSJohn Baldwin static int 935*4f272a5eSJohn Baldwin ktls_write_tls_wr(struct tlspcb *tlsp, struct sge_txq *txq, 936*4f272a5eSJohn Baldwin void *dst, struct mbuf *m, struct tcphdr *tcp, struct mbuf *m_tls, 937*4f272a5eSJohn Baldwin u_int available, tcp_seq tcp_seqno, u_int pidx, uint16_t eh_type, 938*4f272a5eSJohn Baldwin uint16_t mss) 939*4f272a5eSJohn Baldwin { 940*4f272a5eSJohn Baldwin struct sge_eq *eq = &txq->eq; 941*4f272a5eSJohn Baldwin struct tx_sdesc *txsd; 942*4f272a5eSJohn Baldwin struct fw_ulptx_wr *wr; 943*4f272a5eSJohn Baldwin struct ulp_txpkt *txpkt; 944*4f272a5eSJohn Baldwin struct ulptx_sc_memrd *memrd; 945*4f272a5eSJohn Baldwin struct ulptx_idata *idata; 946*4f272a5eSJohn Baldwin struct cpl_tx_sec_pdu *sec_pdu; 947*4f272a5eSJohn Baldwin struct cpl_tx_pkt_core *tx_pkt; 948*4f272a5eSJohn Baldwin const struct tls_record_layer *hdr; 949*4f272a5eSJohn Baldwin struct ip *ip; 950*4f272a5eSJohn Baldwin struct ip6_hdr *ip6; 951*4f272a5eSJohn Baldwin struct tcphdr *newtcp; 952*4f272a5eSJohn Baldwin char *iv, *out; 953*4f272a5eSJohn Baldwin u_int aad_start, aad_stop; 954*4f272a5eSJohn Baldwin u_int auth_start, auth_stop, auth_insert; 955*4f272a5eSJohn Baldwin u_int cipher_start, cipher_stop, iv_offset; 956*4f272a5eSJohn Baldwin u_int header_len, imm_len, ndesc, nsegs, offset, plen, tlen, wr_len; 957*4f272a5eSJohn Baldwin u_int cpl_len, crypto_hdr_len, post_key_context_len; 958*4f272a5eSJohn Baldwin u_int leading_waste, trailing_waste; 959*4f272a5eSJohn Baldwin u_short ip_len; 960*4f272a5eSJohn Baldwin bool last_wr, need_lso, short_record, split_mode, using_scratch; 961*4f272a5eSJohn Baldwin 962*4f272a5eSJohn Baldwin MPASS(tlsp->txq == txq); 963*4f272a5eSJohn Baldwin M_ASSERTEXTPG(m_tls); 964*4f272a5eSJohn Baldwin 965*4f272a5eSJohn Baldwin /* 966*4f272a5eSJohn Baldwin * The relative offset of the last byte to send from the TLS 967*4f272a5eSJohn Baldwin * record. 968*4f272a5eSJohn Baldwin */ 969*4f272a5eSJohn Baldwin tlen = mtod(m_tls, vm_offset_t) + m_tls->m_len; 970*4f272a5eSJohn Baldwin if (tlen <= m_tls->m_epg_hdrlen) { 971*4f272a5eSJohn Baldwin /* 972*4f272a5eSJohn Baldwin * For requests that only want to send the TLS header, 973*4f272a5eSJohn Baldwin * send a tunnelled packet as immediate data. 974*4f272a5eSJohn Baldwin */ 975*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 976*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: %p header-only TLS record %u", __func__, 977*4f272a5eSJohn Baldwin tlsp, (u_int)m_tls->m_epg_seqno); 978*4f272a5eSJohn Baldwin #endif 979*4f272a5eSJohn Baldwin return (ktls_write_tunnel_packet(txq, dst, m, m_tls, available, 980*4f272a5eSJohn Baldwin tcp_seqno, pidx, eh_type)); 981*4f272a5eSJohn Baldwin } 982*4f272a5eSJohn Baldwin 983*4f272a5eSJohn Baldwin /* Locate the TLS header. */ 984*4f272a5eSJohn Baldwin hdr = (void *)m_tls->m_epg_hdr; 985*4f272a5eSJohn Baldwin 986*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 987*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: offset %lu len %u TCP seq %u TLS record %u", 988*4f272a5eSJohn Baldwin __func__, mtod(m_tls, vm_offset_t), m_tls->m_len, tcp_seqno, 989*4f272a5eSJohn Baldwin (u_int)m_tls->m_epg_seqno); 990*4f272a5eSJohn Baldwin #endif 991*4f272a5eSJohn Baldwin 992*4f272a5eSJohn Baldwin short_record = ktls_is_short_record(tlsp, m_tls, tlen, &header_len, 993*4f272a5eSJohn Baldwin &offset, &plen, &leading_waste, &trailing_waste); 994*4f272a5eSJohn Baldwin if (short_record) { 995*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 996*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, 997*4f272a5eSJohn Baldwin "%s: %p short TLS record %u hdr %u offs %u plen %u", 998*4f272a5eSJohn Baldwin __func__, tlsp, (u_int)m_tls->m_epg_seqno, header_len, 999*4f272a5eSJohn Baldwin offset, plen); 1000*4f272a5eSJohn Baldwin #endif 1001*4f272a5eSJohn Baldwin } 1002*4f272a5eSJohn Baldwin 1003*4f272a5eSJohn Baldwin if ((short_record || trailing_waste != 0) && m_tls->m_next == NULL && 1004*4f272a5eSJohn Baldwin (tcp->th_flags & TH_FIN) != 0) { 1005*4f272a5eSJohn Baldwin txq->kern_tls_fin_short++; 1006*4f272a5eSJohn Baldwin #ifdef INVARIANTS 1007*4f272a5eSJohn Baldwin panic("%s: FIN on short TLS record", __func__); 1008*4f272a5eSJohn Baldwin #endif 1009*4f272a5eSJohn Baldwin } 1010*4f272a5eSJohn Baldwin 1011*4f272a5eSJohn Baldwin /* Use cached value for first record in chain. */ 1012*4f272a5eSJohn Baldwin if (m->m_next == m_tls) 1013*4f272a5eSJohn Baldwin nsegs = mbuf_nsegs(m); 1014*4f272a5eSJohn Baldwin else 1015*4f272a5eSJohn Baldwin nsegs = sglist_count_mbuf_epg(m_tls, 1016*4f272a5eSJohn Baldwin m_tls->m_epg_hdrlen + offset, plen); 1017*4f272a5eSJohn Baldwin 1018*4f272a5eSJohn Baldwin /* Final work request for this mbuf chain? */ 1019*4f272a5eSJohn Baldwin last_wr = (m_tls->m_next == NULL); 1020*4f272a5eSJohn Baldwin 1021*4f272a5eSJohn Baldwin /* Determine if we need an LSO header. */ 1022*4f272a5eSJohn Baldwin need_lso = (m_tls->m_len > mss); 1023*4f272a5eSJohn Baldwin 1024*4f272a5eSJohn Baldwin /* Calculate the size of the TLS work request. */ 1025*4f272a5eSJohn Baldwin wr_len = ktls_base_wr_size(tlsp); 1026*4f272a5eSJohn Baldwin 1027*4f272a5eSJohn Baldwin /* 1028*4f272a5eSJohn Baldwin * SplitMode is required if there is any thing we need to trim 1029*4f272a5eSJohn Baldwin * from the crypto output, either at the front or end of the 1030*4f272a5eSJohn Baldwin * record. Note that short records might not need trimming. 1031*4f272a5eSJohn Baldwin */ 1032*4f272a5eSJohn Baldwin split_mode = leading_waste != 0 || trailing_waste != 0; 1033*4f272a5eSJohn Baldwin if (split_mode) { 1034*4f272a5eSJohn Baldwin /* 1035*4f272a5eSJohn Baldwin * Partial records require a SplitMode 1036*4f272a5eSJohn Baldwin * CPL_RX_PHYS_DSGL. 1037*4f272a5eSJohn Baldwin */ 1038*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_t7_rx_phys_dsgl); 1039*4f272a5eSJohn Baldwin } 1040*4f272a5eSJohn Baldwin 1041*4f272a5eSJohn Baldwin if (need_lso) 1042*4f272a5eSJohn Baldwin wr_len += sizeof(struct cpl_tx_pkt_lso_core); 1043*4f272a5eSJohn Baldwin 1044*4f272a5eSJohn Baldwin imm_len = m->m_len + header_len; 1045*4f272a5eSJohn Baldwin if (short_record) 1046*4f272a5eSJohn Baldwin imm_len += AES_BLOCK_LEN; 1047*4f272a5eSJohn Baldwin wr_len += roundup2(imm_len, 16); 1048*4f272a5eSJohn Baldwin wr_len += ktls_sgl_size(nsegs); 1049*4f272a5eSJohn Baldwin 1050*4f272a5eSJohn Baldwin wr_len = roundup2(wr_len, 16); 1051*4f272a5eSJohn Baldwin ndesc = howmany(wr_len, EQ_ESIZE); 1052*4f272a5eSJohn Baldwin MPASS(ndesc <= available); 1053*4f272a5eSJohn Baldwin 1054*4f272a5eSJohn Baldwin /* 1055*4f272a5eSJohn Baldwin * Use the per-txq scratch pad if near the end of the ring to 1056*4f272a5eSJohn Baldwin * simplify handling of wrap-around. 1057*4f272a5eSJohn Baldwin */ 1058*4f272a5eSJohn Baldwin using_scratch = (eq->sidx - pidx < ndesc); 1059*4f272a5eSJohn Baldwin if (using_scratch) 1060*4f272a5eSJohn Baldwin wr = (void *)txq->ss; 1061*4f272a5eSJohn Baldwin else 1062*4f272a5eSJohn Baldwin wr = dst; 1063*4f272a5eSJohn Baldwin 1064*4f272a5eSJohn Baldwin /* FW_ULPTX_WR */ 1065*4f272a5eSJohn Baldwin wr->op_to_compl = htobe32(V_FW_WR_OP(FW_ULPTX_WR)); 1066*4f272a5eSJohn Baldwin wr->flowid_len16 = htobe32(F_FW_ULPTX_WR_DATA | 1067*4f272a5eSJohn Baldwin V_FW_WR_LEN16(wr_len / 16)); 1068*4f272a5eSJohn Baldwin wr->cookie = 0; 1069*4f272a5eSJohn Baldwin 1070*4f272a5eSJohn Baldwin /* ULP_TXPKT */ 1071*4f272a5eSJohn Baldwin txpkt = (void *)(wr + 1); 1072*4f272a5eSJohn Baldwin txpkt->cmd_dest = htobe32(V_ULPTX_CMD(ULP_TX_PKT) | 1073*4f272a5eSJohn Baldwin V_ULP_TXPKT_DATAMODIFY(0) | 1074*4f272a5eSJohn Baldwin V_T7_ULP_TXPKT_CHANNELID(tlsp->vi->pi->port_id) | 1075*4f272a5eSJohn Baldwin V_ULP_TXPKT_DEST(0) | 1076*4f272a5eSJohn Baldwin V_ULP_TXPKT_FID(txq->eq.cntxt_id) | V_ULP_TXPKT_RO(1)); 1077*4f272a5eSJohn Baldwin txpkt->len = htobe32(howmany(wr_len - sizeof(*wr), 16)); 1078*4f272a5eSJohn Baldwin 1079*4f272a5eSJohn Baldwin /* ULPTX_IDATA sub-command */ 1080*4f272a5eSJohn Baldwin idata = (void *)(txpkt + 1); 1081*4f272a5eSJohn Baldwin idata->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM) | 1082*4f272a5eSJohn Baldwin V_ULP_TX_SC_MORE(1)); 1083*4f272a5eSJohn Baldwin idata->len = sizeof(struct cpl_tx_sec_pdu); 1084*4f272a5eSJohn Baldwin 1085*4f272a5eSJohn Baldwin /* 1086*4f272a5eSJohn Baldwin * After the key context comes CPL_RX_PHYS_DSGL, CPL_TX_*, and 1087*4f272a5eSJohn Baldwin * immediate data containing headers. When using an inline 1088*4f272a5eSJohn Baldwin * key, these are counted as part of this ULPTX_IDATA. When 1089*4f272a5eSJohn Baldwin * reading the key from memory, these are part of a separate 1090*4f272a5eSJohn Baldwin * ULPTX_IDATA. 1091*4f272a5eSJohn Baldwin */ 1092*4f272a5eSJohn Baldwin cpl_len = sizeof(struct cpl_tx_pkt_core); 1093*4f272a5eSJohn Baldwin if (need_lso) 1094*4f272a5eSJohn Baldwin cpl_len += sizeof(struct cpl_tx_pkt_lso_core); 1095*4f272a5eSJohn Baldwin if (split_mode) 1096*4f272a5eSJohn Baldwin cpl_len += sizeof(struct cpl_t7_rx_phys_dsgl); 1097*4f272a5eSJohn Baldwin post_key_context_len = cpl_len + imm_len; 1098*4f272a5eSJohn Baldwin 1099*4f272a5eSJohn Baldwin if (tlsp->inline_key) 1100*4f272a5eSJohn Baldwin idata->len += tlsp->tx_key_info_size + post_key_context_len; 1101*4f272a5eSJohn Baldwin idata->len = htobe32(idata->len); 1102*4f272a5eSJohn Baldwin 1103*4f272a5eSJohn Baldwin /* CPL_TX_SEC_PDU */ 1104*4f272a5eSJohn Baldwin sec_pdu = (void *)(idata + 1); 1105*4f272a5eSJohn Baldwin 1106*4f272a5eSJohn Baldwin /* 1107*4f272a5eSJohn Baldwin * Packet headers are passed through unchanged by the crypto 1108*4f272a5eSJohn Baldwin * engine by marking them as header data in SCMD0. 1109*4f272a5eSJohn Baldwin */ 1110*4f272a5eSJohn Baldwin crypto_hdr_len = m->m_len; 1111*4f272a5eSJohn Baldwin 1112*4f272a5eSJohn Baldwin /* 1113*4f272a5eSJohn Baldwin * For short records, the TLS header is counted as header data 1114*4f272a5eSJohn Baldwin * in SCMD0 and the IV is next, followed by a cipher region for 1115*4f272a5eSJohn Baldwin * the payload. 1116*4f272a5eSJohn Baldwin */ 1117*4f272a5eSJohn Baldwin if (short_record) { 1118*4f272a5eSJohn Baldwin aad_start = 0; 1119*4f272a5eSJohn Baldwin aad_stop = 0; 1120*4f272a5eSJohn Baldwin iv_offset = 1; 1121*4f272a5eSJohn Baldwin auth_start = 0; 1122*4f272a5eSJohn Baldwin auth_stop = 0; 1123*4f272a5eSJohn Baldwin auth_insert = 0; 1124*4f272a5eSJohn Baldwin cipher_start = AES_BLOCK_LEN + 1; 1125*4f272a5eSJohn Baldwin cipher_stop = 0; 1126*4f272a5eSJohn Baldwin 1127*4f272a5eSJohn Baldwin sec_pdu->pldlen = htobe32(AES_BLOCK_LEN + plen); 1128*4f272a5eSJohn Baldwin 1129*4f272a5eSJohn Baldwin /* 1130*4f272a5eSJohn Baldwin * For short records, the TLS header is treated as 1131*4f272a5eSJohn Baldwin * header data. 1132*4f272a5eSJohn Baldwin */ 1133*4f272a5eSJohn Baldwin crypto_hdr_len += header_len; 1134*4f272a5eSJohn Baldwin 1135*4f272a5eSJohn Baldwin /* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */ 1136*4f272a5eSJohn Baldwin sec_pdu->seqno_numivs = tlsp->scmd0_short.seqno_numivs; 1137*4f272a5eSJohn Baldwin sec_pdu->ivgen_hdrlen = htobe32( 1138*4f272a5eSJohn Baldwin tlsp->scmd0_short.ivgen_hdrlen | 1139*4f272a5eSJohn Baldwin V_SCMD_HDR_LEN(crypto_hdr_len)); 1140*4f272a5eSJohn Baldwin 1141*4f272a5eSJohn Baldwin txq->kern_tls_short++; 1142*4f272a5eSJohn Baldwin } else { 1143*4f272a5eSJohn Baldwin /* 1144*4f272a5eSJohn Baldwin * AAD is TLS header. IV is after AAD. The cipher region 1145*4f272a5eSJohn Baldwin * starts after the IV. See comments in ccr_authenc() and 1146*4f272a5eSJohn Baldwin * ccr_gmac() in t4_crypto.c regarding cipher and auth 1147*4f272a5eSJohn Baldwin * start/stop values. 1148*4f272a5eSJohn Baldwin */ 1149*4f272a5eSJohn Baldwin aad_start = 1; 1150*4f272a5eSJohn Baldwin aad_stop = TLS_HEADER_LENGTH; 1151*4f272a5eSJohn Baldwin iv_offset = TLS_HEADER_LENGTH + 1; 1152*4f272a5eSJohn Baldwin cipher_start = m_tls->m_epg_hdrlen + 1; 1153*4f272a5eSJohn Baldwin if (tlsp->enc_mode == SCMD_CIPH_MODE_AES_GCM) { 1154*4f272a5eSJohn Baldwin cipher_stop = 0; 1155*4f272a5eSJohn Baldwin auth_start = cipher_start; 1156*4f272a5eSJohn Baldwin auth_stop = 0; 1157*4f272a5eSJohn Baldwin auth_insert = 0; 1158*4f272a5eSJohn Baldwin } else { 1159*4f272a5eSJohn Baldwin cipher_stop = 0; 1160*4f272a5eSJohn Baldwin auth_start = cipher_start; 1161*4f272a5eSJohn Baldwin auth_stop = 0; 1162*4f272a5eSJohn Baldwin auth_insert = 0; 1163*4f272a5eSJohn Baldwin } 1164*4f272a5eSJohn Baldwin 1165*4f272a5eSJohn Baldwin sec_pdu->pldlen = htobe32(m_tls->m_epg_hdrlen + plen); 1166*4f272a5eSJohn Baldwin 1167*4f272a5eSJohn Baldwin /* These two flits are actually a CPL_TLS_TX_SCMD_FMT. */ 1168*4f272a5eSJohn Baldwin sec_pdu->seqno_numivs = tlsp->scmd0.seqno_numivs; 1169*4f272a5eSJohn Baldwin sec_pdu->ivgen_hdrlen = htobe32(tlsp->scmd0.ivgen_hdrlen | 1170*4f272a5eSJohn Baldwin V_SCMD_HDR_LEN(crypto_hdr_len)); 1171*4f272a5eSJohn Baldwin 1172*4f272a5eSJohn Baldwin if (split_mode) 1173*4f272a5eSJohn Baldwin txq->kern_tls_partial++; 1174*4f272a5eSJohn Baldwin else 1175*4f272a5eSJohn Baldwin txq->kern_tls_full++; 1176*4f272a5eSJohn Baldwin } 1177*4f272a5eSJohn Baldwin sec_pdu->op_ivinsrtofst = htobe32( 1178*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_OPCODE(CPL_TX_SEC_PDU) | 1179*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_CPLLEN(cpl_len / 8) | 1180*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_PLACEHOLDER(0) | 1181*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_IVINSRTOFST(iv_offset)); 1182*4f272a5eSJohn Baldwin sec_pdu->aadstart_cipherstop_hi = htobe32( 1183*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_AADSTART(aad_start) | 1184*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_AADSTOP(aad_stop) | 1185*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_CIPHERSTART(cipher_start) | 1186*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_CIPHERSTOP_HI(cipher_stop >> 4)); 1187*4f272a5eSJohn Baldwin sec_pdu->cipherstop_lo_authinsert = htobe32( 1188*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_CIPHERSTOP_LO(cipher_stop & 0xf) | 1189*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_AUTHSTART(auth_start) | 1190*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_AUTHSTOP(auth_stop) | 1191*4f272a5eSJohn Baldwin V_CPL_TX_SEC_PDU_AUTHINSERT(auth_insert)); 1192*4f272a5eSJohn Baldwin 1193*4f272a5eSJohn Baldwin sec_pdu->scmd1 = htobe64(m_tls->m_epg_seqno); 1194*4f272a5eSJohn Baldwin 1195*4f272a5eSJohn Baldwin /* Key context */ 1196*4f272a5eSJohn Baldwin out = (void *)(sec_pdu + 1); 1197*4f272a5eSJohn Baldwin if (tlsp->inline_key) { 1198*4f272a5eSJohn Baldwin memcpy(out, &tlsp->keyctx, tlsp->tx_key_info_size); 1199*4f272a5eSJohn Baldwin out += tlsp->tx_key_info_size; 1200*4f272a5eSJohn Baldwin } else { 1201*4f272a5eSJohn Baldwin /* ULPTX_SC_MEMRD to read key context. */ 1202*4f272a5eSJohn Baldwin memrd = (void *)out; 1203*4f272a5eSJohn Baldwin memrd->cmd_to_len = htobe32(V_ULPTX_CMD(ULP_TX_SC_MEMRD) | 1204*4f272a5eSJohn Baldwin V_ULP_TX_SC_MORE(1) | 1205*4f272a5eSJohn Baldwin V_ULPTX_LEN16(tlsp->tx_key_info_size >> 4)); 1206*4f272a5eSJohn Baldwin memrd->addr = htobe32(tlsp->tx_key_addr >> 5); 1207*4f272a5eSJohn Baldwin 1208*4f272a5eSJohn Baldwin /* ULPTX_IDATA for CPL_TX_* and headers. */ 1209*4f272a5eSJohn Baldwin idata = (void *)(memrd + 1); 1210*4f272a5eSJohn Baldwin idata->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_IMM) | 1211*4f272a5eSJohn Baldwin V_ULP_TX_SC_MORE(1)); 1212*4f272a5eSJohn Baldwin idata->len = htobe32(post_key_context_len); 1213*4f272a5eSJohn Baldwin 1214*4f272a5eSJohn Baldwin out = (void *)(idata + 1); 1215*4f272a5eSJohn Baldwin } 1216*4f272a5eSJohn Baldwin 1217*4f272a5eSJohn Baldwin /* CPL_RX_PHYS_DSGL */ 1218*4f272a5eSJohn Baldwin if (split_mode) { 1219*4f272a5eSJohn Baldwin out = write_split_mode_rx_phys(out, m, m_tls, cpl_len - 1220*4f272a5eSJohn Baldwin sizeof(struct cpl_t7_rx_phys_dsgl) + m->m_len, 1221*4f272a5eSJohn Baldwin leading_waste, trailing_waste); 1222*4f272a5eSJohn Baldwin } 1223*4f272a5eSJohn Baldwin 1224*4f272a5eSJohn Baldwin /* CPL_TX_PKT_LSO */ 1225*4f272a5eSJohn Baldwin if (need_lso) { 1226*4f272a5eSJohn Baldwin out = write_lso_cpl(out, m, mss, eh_type, m->m_len + 1227*4f272a5eSJohn Baldwin m_tls->m_len); 1228*4f272a5eSJohn Baldwin txq->tso_wrs++; 1229*4f272a5eSJohn Baldwin } 1230*4f272a5eSJohn Baldwin 1231*4f272a5eSJohn Baldwin /* CPL_TX_PKT_XT */ 1232*4f272a5eSJohn Baldwin tx_pkt = (void *)out; 1233*4f272a5eSJohn Baldwin tx_pkt->ctrl0 = txq->cpl_ctrl0; 1234*4f272a5eSJohn Baldwin tx_pkt->ctrl1 = htobe64(pkt_ctrl1(txq, m, eh_type)); 1235*4f272a5eSJohn Baldwin tx_pkt->pack = 0; 1236*4f272a5eSJohn Baldwin tx_pkt->len = htobe16(m->m_len + m_tls->m_len); 1237*4f272a5eSJohn Baldwin 1238*4f272a5eSJohn Baldwin /* Copy the packet headers. */ 1239*4f272a5eSJohn Baldwin out = (void *)(tx_pkt + 1); 1240*4f272a5eSJohn Baldwin memcpy(out, mtod(m, char *), m->m_len); 1241*4f272a5eSJohn Baldwin 1242*4f272a5eSJohn Baldwin /* Modify the packet length in the IP header. */ 1243*4f272a5eSJohn Baldwin ip_len = m->m_len + m_tls->m_len - m->m_pkthdr.l2hlen; 1244*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_IP) { 1245*4f272a5eSJohn Baldwin ip = (void *)(out + m->m_pkthdr.l2hlen); 1246*4f272a5eSJohn Baldwin be16enc(&ip->ip_len, ip_len); 1247*4f272a5eSJohn Baldwin } else { 1248*4f272a5eSJohn Baldwin ip6 = (void *)(out + m->m_pkthdr.l2hlen); 1249*4f272a5eSJohn Baldwin be16enc(&ip6->ip6_plen, ip_len - sizeof(*ip6)); 1250*4f272a5eSJohn Baldwin } 1251*4f272a5eSJohn Baldwin 1252*4f272a5eSJohn Baldwin /* Modify sequence number and flags in TCP header. */ 1253*4f272a5eSJohn Baldwin newtcp = (void *)(out + m->m_pkthdr.l2hlen + m->m_pkthdr.l3hlen); 1254*4f272a5eSJohn Baldwin be32enc(&newtcp->th_seq, tcp_seqno); 1255*4f272a5eSJohn Baldwin if (!last_wr) 1256*4f272a5eSJohn Baldwin newtcp->th_flags = tcp->th_flags & ~(TH_PUSH | TH_FIN); 1257*4f272a5eSJohn Baldwin out += m->m_len; 1258*4f272a5eSJohn Baldwin 1259*4f272a5eSJohn Baldwin /* Populate the TLS header */ 1260*4f272a5eSJohn Baldwin memcpy(out, m_tls->m_epg_hdr, header_len); 1261*4f272a5eSJohn Baldwin out += header_len; 1262*4f272a5eSJohn Baldwin 1263*4f272a5eSJohn Baldwin /* AES IV for a short record. */ 1264*4f272a5eSJohn Baldwin if (short_record) { 1265*4f272a5eSJohn Baldwin iv = out; 1266*4f272a5eSJohn Baldwin if (tlsp->enc_mode == SCMD_CIPH_MODE_AES_GCM) { 1267*4f272a5eSJohn Baldwin memcpy(iv, tlsp->keyctx.u.txhdr.txsalt, SALT_SIZE); 1268*4f272a5eSJohn Baldwin memcpy(iv + 4, hdr + 1, 8); 1269*4f272a5eSJohn Baldwin be32enc(iv + 12, 2 + offset / AES_BLOCK_LEN); 1270*4f272a5eSJohn Baldwin } else 1271*4f272a5eSJohn Baldwin memcpy(iv, hdr + 1, AES_BLOCK_LEN); 1272*4f272a5eSJohn Baldwin out += AES_BLOCK_LEN; 1273*4f272a5eSJohn Baldwin } 1274*4f272a5eSJohn Baldwin 1275*4f272a5eSJohn Baldwin if (imm_len % 16 != 0) { 1276*4f272a5eSJohn Baldwin if (imm_len % 8 != 0) { 1277*4f272a5eSJohn Baldwin /* Zero pad to an 8-byte boundary. */ 1278*4f272a5eSJohn Baldwin memset(out, 0, 8 - (imm_len % 8)); 1279*4f272a5eSJohn Baldwin out += 8 - (imm_len % 8); 1280*4f272a5eSJohn Baldwin } 1281*4f272a5eSJohn Baldwin 1282*4f272a5eSJohn Baldwin /* 1283*4f272a5eSJohn Baldwin * Insert a ULP_TX_SC_NOOP if needed so the SGL is 1284*4f272a5eSJohn Baldwin * 16-byte aligned. 1285*4f272a5eSJohn Baldwin */ 1286*4f272a5eSJohn Baldwin if (imm_len % 16 <= 8) { 1287*4f272a5eSJohn Baldwin idata = (void *)out; 1288*4f272a5eSJohn Baldwin idata->cmd_more = htobe32(V_ULPTX_CMD(ULP_TX_SC_NOOP) | 1289*4f272a5eSJohn Baldwin V_ULP_TX_SC_MORE(1)); 1290*4f272a5eSJohn Baldwin idata->len = htobe32(0); 1291*4f272a5eSJohn Baldwin out = (void *)(idata + 1); 1292*4f272a5eSJohn Baldwin } 1293*4f272a5eSJohn Baldwin } 1294*4f272a5eSJohn Baldwin 1295*4f272a5eSJohn Baldwin /* SGL for record payload */ 1296*4f272a5eSJohn Baldwin sglist_reset(txq->gl); 1297*4f272a5eSJohn Baldwin if (sglist_append_mbuf_epg(txq->gl, m_tls, m_tls->m_epg_hdrlen + offset, 1298*4f272a5eSJohn Baldwin plen) != 0) { 1299*4f272a5eSJohn Baldwin #ifdef INVARIANTS 1300*4f272a5eSJohn Baldwin panic("%s: failed to append sglist", __func__); 1301*4f272a5eSJohn Baldwin #endif 1302*4f272a5eSJohn Baldwin } 1303*4f272a5eSJohn Baldwin write_gl_to_buf(txq->gl, out); 1304*4f272a5eSJohn Baldwin 1305*4f272a5eSJohn Baldwin if (using_scratch) { 1306*4f272a5eSJohn Baldwin out = dst; 1307*4f272a5eSJohn Baldwin copy_to_txd(eq, txq->ss, &out, wr_len); 1308*4f272a5eSJohn Baldwin } 1309*4f272a5eSJohn Baldwin 1310*4f272a5eSJohn Baldwin txq->kern_tls_records++; 1311*4f272a5eSJohn Baldwin txq->kern_tls_octets += m_tls->m_len; 1312*4f272a5eSJohn Baldwin if (split_mode) { 1313*4f272a5eSJohn Baldwin txq->kern_tls_splitmode++; 1314*4f272a5eSJohn Baldwin txq->kern_tls_waste += leading_waste + trailing_waste; 1315*4f272a5eSJohn Baldwin } 1316*4f272a5eSJohn Baldwin if (need_lso) 1317*4f272a5eSJohn Baldwin txq->kern_tls_lso++; 1318*4f272a5eSJohn Baldwin 1319*4f272a5eSJohn Baldwin txsd = &txq->sdesc[pidx]; 1320*4f272a5eSJohn Baldwin if (last_wr) 1321*4f272a5eSJohn Baldwin txsd->m = m; 1322*4f272a5eSJohn Baldwin else 1323*4f272a5eSJohn Baldwin txsd->m = NULL; 1324*4f272a5eSJohn Baldwin txsd->desc_used = howmany(wr_len, EQ_ESIZE); 1325*4f272a5eSJohn Baldwin 1326*4f272a5eSJohn Baldwin return (ndesc); 1327*4f272a5eSJohn Baldwin } 1328*4f272a5eSJohn Baldwin 1329*4f272a5eSJohn Baldwin int 1330*4f272a5eSJohn Baldwin t7_ktls_write_wr(struct sge_txq *txq, void *dst, struct mbuf *m, 1331*4f272a5eSJohn Baldwin u_int available) 1332*4f272a5eSJohn Baldwin { 1333*4f272a5eSJohn Baldwin struct sge_eq *eq = &txq->eq; 1334*4f272a5eSJohn Baldwin struct tlspcb *tlsp; 1335*4f272a5eSJohn Baldwin struct tcphdr *tcp; 1336*4f272a5eSJohn Baldwin struct mbuf *m_tls; 1337*4f272a5eSJohn Baldwin struct ether_header *eh; 1338*4f272a5eSJohn Baldwin tcp_seq tcp_seqno; 1339*4f272a5eSJohn Baldwin u_int ndesc, pidx, totdesc; 1340*4f272a5eSJohn Baldwin uint16_t eh_type, mss; 1341*4f272a5eSJohn Baldwin 1342*4f272a5eSJohn Baldwin M_ASSERTPKTHDR(m); 1343*4f272a5eSJohn Baldwin MPASS(m->m_pkthdr.snd_tag != NULL); 1344*4f272a5eSJohn Baldwin tlsp = mst_to_tls(m->m_pkthdr.snd_tag); 1345*4f272a5eSJohn Baldwin 1346*4f272a5eSJohn Baldwin totdesc = 0; 1347*4f272a5eSJohn Baldwin eh = mtod(m, struct ether_header *); 1348*4f272a5eSJohn Baldwin eh_type = ntohs(eh->ether_type); 1349*4f272a5eSJohn Baldwin if (eh_type == ETHERTYPE_VLAN) { 1350*4f272a5eSJohn Baldwin struct ether_vlan_header *evh = (void *)eh; 1351*4f272a5eSJohn Baldwin 1352*4f272a5eSJohn Baldwin eh_type = ntohs(evh->evl_proto); 1353*4f272a5eSJohn Baldwin } 1354*4f272a5eSJohn Baldwin 1355*4f272a5eSJohn Baldwin tcp = (struct tcphdr *)((char *)eh + m->m_pkthdr.l2hlen + 1356*4f272a5eSJohn Baldwin m->m_pkthdr.l3hlen); 1357*4f272a5eSJohn Baldwin pidx = eq->pidx; 1358*4f272a5eSJohn Baldwin 1359*4f272a5eSJohn Baldwin /* Determine MSS. */ 1360*4f272a5eSJohn Baldwin if (m->m_pkthdr.csum_flags & CSUM_TSO) { 1361*4f272a5eSJohn Baldwin mss = m->m_pkthdr.tso_segsz; 1362*4f272a5eSJohn Baldwin tlsp->prev_mss = mss; 1363*4f272a5eSJohn Baldwin } else if (tlsp->prev_mss != 0) 1364*4f272a5eSJohn Baldwin mss = tlsp->prev_mss; 1365*4f272a5eSJohn Baldwin else 1366*4f272a5eSJohn Baldwin mss = if_getmtu(tlsp->vi->ifp) - 1367*4f272a5eSJohn Baldwin (m->m_pkthdr.l3hlen + m->m_pkthdr.l4hlen); 1368*4f272a5eSJohn Baldwin 1369*4f272a5eSJohn Baldwin /* Fetch the starting TCP sequence number for this chain. */ 1370*4f272a5eSJohn Baldwin tcp_seqno = ntohl(tcp->th_seq); 1371*4f272a5eSJohn Baldwin #ifdef VERBOSE_TRACES 1372*4f272a5eSJohn Baldwin CTR(KTR_CXGBE, "%s: pkt len %d TCP seq %u", __func__, m->m_pkthdr.len, 1373*4f272a5eSJohn Baldwin tcp_seqno); 1374*4f272a5eSJohn Baldwin #endif 1375*4f272a5eSJohn Baldwin 1376*4f272a5eSJohn Baldwin /* 1377*4f272a5eSJohn Baldwin * Iterate over each TLS record constructing a work request 1378*4f272a5eSJohn Baldwin * for that record. 1379*4f272a5eSJohn Baldwin */ 1380*4f272a5eSJohn Baldwin for (m_tls = m->m_next; m_tls != NULL; m_tls = m_tls->m_next) { 1381*4f272a5eSJohn Baldwin MPASS(m_tls->m_flags & M_EXTPG); 1382*4f272a5eSJohn Baldwin 1383*4f272a5eSJohn Baldwin ndesc = ktls_write_tls_wr(tlsp, txq, dst, m, tcp, m_tls, 1384*4f272a5eSJohn Baldwin available - totdesc, tcp_seqno, pidx, eh_type, mss); 1385*4f272a5eSJohn Baldwin totdesc += ndesc; 1386*4f272a5eSJohn Baldwin IDXINCR(pidx, ndesc, eq->sidx); 1387*4f272a5eSJohn Baldwin dst = &eq->desc[pidx]; 1388*4f272a5eSJohn Baldwin 1389*4f272a5eSJohn Baldwin tcp_seqno += m_tls->m_len; 1390*4f272a5eSJohn Baldwin } 1391*4f272a5eSJohn Baldwin 1392*4f272a5eSJohn Baldwin MPASS(totdesc <= available); 1393*4f272a5eSJohn Baldwin return (totdesc); 1394*4f272a5eSJohn Baldwin } 1395*4f272a5eSJohn Baldwin 1396*4f272a5eSJohn Baldwin static void 1397*4f272a5eSJohn Baldwin t7_tls_tag_free(struct m_snd_tag *mst) 1398*4f272a5eSJohn Baldwin { 1399*4f272a5eSJohn Baldwin struct adapter *sc; 1400*4f272a5eSJohn Baldwin struct tlspcb *tlsp; 1401*4f272a5eSJohn Baldwin 1402*4f272a5eSJohn Baldwin tlsp = mst_to_tls(mst); 1403*4f272a5eSJohn Baldwin sc = tlsp->sc; 1404*4f272a5eSJohn Baldwin 1405*4f272a5eSJohn Baldwin CTR2(KTR_CXGBE, "%s: %p", __func__, tlsp); 1406*4f272a5eSJohn Baldwin 1407*4f272a5eSJohn Baldwin if (tlsp->tx_key_addr >= 0) 1408*4f272a5eSJohn Baldwin t4_free_tls_keyid(sc, tlsp->tx_key_addr); 1409*4f272a5eSJohn Baldwin 1410*4f272a5eSJohn Baldwin zfree(tlsp, M_CXGBE); 1411*4f272a5eSJohn Baldwin } 1412*4f272a5eSJohn Baldwin 1413*4f272a5eSJohn Baldwin #else 1414*4f272a5eSJohn Baldwin 1415*4f272a5eSJohn Baldwin int 1416*4f272a5eSJohn Baldwin t7_tls_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params, 1417*4f272a5eSJohn Baldwin struct m_snd_tag **pt) 1418*4f272a5eSJohn Baldwin { 1419*4f272a5eSJohn Baldwin return (ENXIO); 1420*4f272a5eSJohn Baldwin } 1421*4f272a5eSJohn Baldwin 1422*4f272a5eSJohn Baldwin int 1423*4f272a5eSJohn Baldwin t7_ktls_parse_pkt(struct mbuf *m) 1424*4f272a5eSJohn Baldwin { 1425*4f272a5eSJohn Baldwin return (EINVAL); 1426*4f272a5eSJohn Baldwin } 1427*4f272a5eSJohn Baldwin 1428*4f272a5eSJohn Baldwin int 1429*4f272a5eSJohn Baldwin t7_ktls_write_wr(struct sge_txq *txq, void *dst, struct mbuf *m, 1430*4f272a5eSJohn Baldwin u_int available) 1431*4f272a5eSJohn Baldwin { 1432*4f272a5eSJohn Baldwin panic("can't happen"); 1433*4f272a5eSJohn Baldwin } 1434*4f272a5eSJohn Baldwin 1435*4f272a5eSJohn Baldwin #endif 1436