199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2018-2020 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <rte_ipsec.h> 699a2dd95SBruce Richardson #include <rte_esp.h> 799a2dd95SBruce Richardson #include <rte_ip.h> 801eef590SRadu Nicolau #include <rte_udp.h> 999a2dd95SBruce Richardson #include <rte_errno.h> 1099a2dd95SBruce Richardson #include <rte_cryptodev.h> 1199a2dd95SBruce Richardson 1299a2dd95SBruce Richardson #include "sa.h" 1399a2dd95SBruce Richardson #include "ipsec_sqn.h" 1499a2dd95SBruce Richardson #include "crypto.h" 1599a2dd95SBruce Richardson #include "iph.h" 1699a2dd95SBruce Richardson #include "misc.h" 1799a2dd95SBruce Richardson #include "pad.h" 1899a2dd95SBruce Richardson 1999a2dd95SBruce Richardson #define MBUF_MAX_L2_LEN RTE_LEN2MASK(RTE_MBUF_L2_LEN_BITS, uint64_t) 2099a2dd95SBruce Richardson #define MBUF_MAX_L3_LEN RTE_LEN2MASK(RTE_MBUF_L3_LEN_BITS, uint64_t) 2199a2dd95SBruce Richardson 2299a2dd95SBruce Richardson /* some helper structures */ 2399a2dd95SBruce Richardson struct crypto_xform { 2499a2dd95SBruce Richardson struct rte_crypto_auth_xform *auth; 2599a2dd95SBruce Richardson struct rte_crypto_cipher_xform *cipher; 2699a2dd95SBruce Richardson struct rte_crypto_aead_xform *aead; 2799a2dd95SBruce Richardson }; 2899a2dd95SBruce Richardson 2999a2dd95SBruce Richardson /* 3099a2dd95SBruce Richardson * helper routine, fills internal crypto_xform structure. 3199a2dd95SBruce Richardson */ 3299a2dd95SBruce Richardson static int 3399a2dd95SBruce Richardson fill_crypto_xform(struct crypto_xform *xform, uint64_t type, 3499a2dd95SBruce Richardson const struct rte_ipsec_sa_prm *prm) 3599a2dd95SBruce Richardson { 3699a2dd95SBruce Richardson struct rte_crypto_sym_xform *xf, *xfn; 3799a2dd95SBruce Richardson 3899a2dd95SBruce Richardson memset(xform, 0, sizeof(*xform)); 3999a2dd95SBruce Richardson 4099a2dd95SBruce Richardson xf = prm->crypto_xform; 4199a2dd95SBruce Richardson if (xf == NULL) 4299a2dd95SBruce Richardson return -EINVAL; 4399a2dd95SBruce Richardson 4499a2dd95SBruce Richardson xfn = xf->next; 4599a2dd95SBruce Richardson 4699a2dd95SBruce Richardson /* for AEAD just one xform required */ 4799a2dd95SBruce Richardson if (xf->type == RTE_CRYPTO_SYM_XFORM_AEAD) { 4899a2dd95SBruce Richardson if (xfn != NULL) 4999a2dd95SBruce Richardson return -EINVAL; 5099a2dd95SBruce Richardson xform->aead = &xf->aead; 51c99d2619SRadu Nicolau 52c99d2619SRadu Nicolau /* GMAC has only auth */ 53c99d2619SRadu Nicolau } else if (xf->type == RTE_CRYPTO_SYM_XFORM_AUTH && 54c99d2619SRadu Nicolau xf->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) { 55c99d2619SRadu Nicolau if (xfn != NULL) 56c99d2619SRadu Nicolau return -EINVAL; 57c99d2619SRadu Nicolau xform->auth = &xf->auth; 58c99d2619SRadu Nicolau xform->cipher = &xfn->cipher; 59c99d2619SRadu Nicolau 6099a2dd95SBruce Richardson /* 6199a2dd95SBruce Richardson * CIPHER+AUTH xforms are expected in strict order, 6299a2dd95SBruce Richardson * depending on SA direction: 6399a2dd95SBruce Richardson * inbound: AUTH+CIPHER 6499a2dd95SBruce Richardson * outbound: CIPHER+AUTH 6599a2dd95SBruce Richardson */ 6699a2dd95SBruce Richardson } else if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) { 6799a2dd95SBruce Richardson 6899a2dd95SBruce Richardson /* wrong order or no cipher */ 6999a2dd95SBruce Richardson if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_AUTH || 7099a2dd95SBruce Richardson xfn->type != RTE_CRYPTO_SYM_XFORM_CIPHER) 7199a2dd95SBruce Richardson return -EINVAL; 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson xform->auth = &xf->auth; 7499a2dd95SBruce Richardson xform->cipher = &xfn->cipher; 7599a2dd95SBruce Richardson 7699a2dd95SBruce Richardson } else { 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson /* wrong order or no auth */ 7999a2dd95SBruce Richardson if (xfn == NULL || xf->type != RTE_CRYPTO_SYM_XFORM_CIPHER || 8099a2dd95SBruce Richardson xfn->type != RTE_CRYPTO_SYM_XFORM_AUTH) 8199a2dd95SBruce Richardson return -EINVAL; 8299a2dd95SBruce Richardson 8399a2dd95SBruce Richardson xform->cipher = &xf->cipher; 8499a2dd95SBruce Richardson xform->auth = &xfn->auth; 8599a2dd95SBruce Richardson } 8699a2dd95SBruce Richardson 8799a2dd95SBruce Richardson return 0; 8899a2dd95SBruce Richardson } 8999a2dd95SBruce Richardson 9099a2dd95SBruce Richardson uint64_t 9199a2dd95SBruce Richardson rte_ipsec_sa_type(const struct rte_ipsec_sa *sa) 9299a2dd95SBruce Richardson { 9399a2dd95SBruce Richardson return sa->type; 9499a2dd95SBruce Richardson } 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson /** 9799a2dd95SBruce Richardson * Based on number of buckets calculated required size for the 9899a2dd95SBruce Richardson * structure that holds replay window and sequence number (RSN) information. 9999a2dd95SBruce Richardson */ 10099a2dd95SBruce Richardson static size_t 10199a2dd95SBruce Richardson rsn_size(uint32_t nb_bucket) 10299a2dd95SBruce Richardson { 10399a2dd95SBruce Richardson size_t sz; 10499a2dd95SBruce Richardson struct replay_sqn *rsn; 10599a2dd95SBruce Richardson 10699a2dd95SBruce Richardson sz = sizeof(*rsn) + nb_bucket * sizeof(rsn->window[0]); 10799a2dd95SBruce Richardson sz = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE); 10899a2dd95SBruce Richardson return sz; 10999a2dd95SBruce Richardson } 11099a2dd95SBruce Richardson 11199a2dd95SBruce Richardson /* 11299a2dd95SBruce Richardson * for given size, calculate required number of buckets. 11399a2dd95SBruce Richardson */ 11499a2dd95SBruce Richardson static uint32_t 11599a2dd95SBruce Richardson replay_num_bucket(uint32_t wsz) 11699a2dd95SBruce Richardson { 11799a2dd95SBruce Richardson uint32_t nb; 11899a2dd95SBruce Richardson 11999a2dd95SBruce Richardson nb = rte_align32pow2(RTE_ALIGN_MUL_CEIL(wsz, WINDOW_BUCKET_SIZE) / 12099a2dd95SBruce Richardson WINDOW_BUCKET_SIZE); 12199a2dd95SBruce Richardson nb = RTE_MAX(nb, (uint32_t)WINDOW_BUCKET_MIN); 12299a2dd95SBruce Richardson 12399a2dd95SBruce Richardson return nb; 12499a2dd95SBruce Richardson } 12599a2dd95SBruce Richardson 12699a2dd95SBruce Richardson static int32_t 12799a2dd95SBruce Richardson ipsec_sa_size(uint64_t type, uint32_t *wnd_sz, uint32_t *nb_bucket) 12899a2dd95SBruce Richardson { 12999a2dd95SBruce Richardson uint32_t n, sz, wsz; 13099a2dd95SBruce Richardson 13199a2dd95SBruce Richardson wsz = *wnd_sz; 13299a2dd95SBruce Richardson n = 0; 13399a2dd95SBruce Richardson 13499a2dd95SBruce Richardson if ((type & RTE_IPSEC_SATP_DIR_MASK) == RTE_IPSEC_SATP_DIR_IB) { 13599a2dd95SBruce Richardson 13699a2dd95SBruce Richardson /* 13799a2dd95SBruce Richardson * RFC 4303 recommends 64 as minimum window size. 13899a2dd95SBruce Richardson * there is no point to use ESN mode without SQN window, 13999a2dd95SBruce Richardson * so make sure we have at least 64 window when ESN is enalbed. 14099a2dd95SBruce Richardson */ 14199a2dd95SBruce Richardson wsz = ((type & RTE_IPSEC_SATP_ESN_MASK) == 14299a2dd95SBruce Richardson RTE_IPSEC_SATP_ESN_DISABLE) ? 14399a2dd95SBruce Richardson wsz : RTE_MAX(wsz, (uint32_t)WINDOW_BUCKET_SIZE); 14499a2dd95SBruce Richardson if (wsz != 0) 14599a2dd95SBruce Richardson n = replay_num_bucket(wsz); 14699a2dd95SBruce Richardson } 14799a2dd95SBruce Richardson 14899a2dd95SBruce Richardson if (n > WINDOW_BUCKET_MAX) 14999a2dd95SBruce Richardson return -EINVAL; 15099a2dd95SBruce Richardson 15199a2dd95SBruce Richardson *wnd_sz = wsz; 15299a2dd95SBruce Richardson *nb_bucket = n; 15399a2dd95SBruce Richardson 15499a2dd95SBruce Richardson sz = rsn_size(n); 15599a2dd95SBruce Richardson if ((type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM) 15699a2dd95SBruce Richardson sz *= REPLAY_SQN_NUM; 15799a2dd95SBruce Richardson 15899a2dd95SBruce Richardson sz += sizeof(struct rte_ipsec_sa); 15999a2dd95SBruce Richardson return sz; 16099a2dd95SBruce Richardson } 16199a2dd95SBruce Richardson 16299a2dd95SBruce Richardson void 16399a2dd95SBruce Richardson rte_ipsec_sa_fini(struct rte_ipsec_sa *sa) 16499a2dd95SBruce Richardson { 16599a2dd95SBruce Richardson memset(sa, 0, sa->size); 16699a2dd95SBruce Richardson } 16799a2dd95SBruce Richardson 16899a2dd95SBruce Richardson /* 16999a2dd95SBruce Richardson * Determine expected SA type based on input parameters. 17099a2dd95SBruce Richardson */ 17199a2dd95SBruce Richardson static int 17299a2dd95SBruce Richardson fill_sa_type(const struct rte_ipsec_sa_prm *prm, uint64_t *type) 17399a2dd95SBruce Richardson { 17499a2dd95SBruce Richardson uint64_t tp; 17599a2dd95SBruce Richardson 17699a2dd95SBruce Richardson tp = 0; 17799a2dd95SBruce Richardson 17899a2dd95SBruce Richardson if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_AH) 17999a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_PROTO_AH; 18099a2dd95SBruce Richardson else if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) 18199a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_PROTO_ESP; 18299a2dd95SBruce Richardson else 18399a2dd95SBruce Richardson return -EINVAL; 18499a2dd95SBruce Richardson 18599a2dd95SBruce Richardson if (prm->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) 18699a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_DIR_OB; 18799a2dd95SBruce Richardson else if (prm->ipsec_xform.direction == 18899a2dd95SBruce Richardson RTE_SECURITY_IPSEC_SA_DIR_INGRESS) 18999a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_DIR_IB; 19099a2dd95SBruce Richardson else 19199a2dd95SBruce Richardson return -EINVAL; 19299a2dd95SBruce Richardson 19399a2dd95SBruce Richardson if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 19499a2dd95SBruce Richardson if (prm->ipsec_xform.tunnel.type == 19599a2dd95SBruce Richardson RTE_SECURITY_IPSEC_TUNNEL_IPV4) 19699a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_MODE_TUNLV4; 19799a2dd95SBruce Richardson else if (prm->ipsec_xform.tunnel.type == 19899a2dd95SBruce Richardson RTE_SECURITY_IPSEC_TUNNEL_IPV6) 19999a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_MODE_TUNLV6; 20099a2dd95SBruce Richardson else 20199a2dd95SBruce Richardson return -EINVAL; 20299a2dd95SBruce Richardson 20399a2dd95SBruce Richardson if (prm->tun.next_proto == IPPROTO_IPIP) 20499a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_IPV4; 20599a2dd95SBruce Richardson else if (prm->tun.next_proto == IPPROTO_IPV6) 20699a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_IPV6; 20799a2dd95SBruce Richardson else 20899a2dd95SBruce Richardson return -EINVAL; 20999a2dd95SBruce Richardson } else if (prm->ipsec_xform.mode == 21099a2dd95SBruce Richardson RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) { 21199a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_MODE_TRANS; 21299a2dd95SBruce Richardson if (prm->trs.proto == IPPROTO_IPIP) 21399a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_IPV4; 21499a2dd95SBruce Richardson else if (prm->trs.proto == IPPROTO_IPV6) 21599a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_IPV6; 21699a2dd95SBruce Richardson else 21799a2dd95SBruce Richardson return -EINVAL; 21899a2dd95SBruce Richardson } else 21999a2dd95SBruce Richardson return -EINVAL; 22099a2dd95SBruce Richardson 22101eef590SRadu Nicolau /* check for UDP encapsulation flag */ 22201eef590SRadu Nicolau if (prm->ipsec_xform.options.udp_encap == 1) 22301eef590SRadu Nicolau tp |= RTE_IPSEC_SATP_NATT_ENABLE; 22401eef590SRadu Nicolau 22599a2dd95SBruce Richardson /* check for ESN flag */ 22699a2dd95SBruce Richardson if (prm->ipsec_xform.options.esn == 0) 22799a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_ESN_DISABLE; 22899a2dd95SBruce Richardson else 22999a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_ESN_ENABLE; 23099a2dd95SBruce Richardson 23199a2dd95SBruce Richardson /* check for ECN flag */ 23299a2dd95SBruce Richardson if (prm->ipsec_xform.options.ecn == 0) 23399a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_ECN_DISABLE; 23499a2dd95SBruce Richardson else 23599a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_ECN_ENABLE; 23699a2dd95SBruce Richardson 23799a2dd95SBruce Richardson /* check for DSCP flag */ 23899a2dd95SBruce Richardson if (prm->ipsec_xform.options.copy_dscp == 0) 23999a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_DSCP_DISABLE; 24099a2dd95SBruce Richardson else 24199a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_DSCP_ENABLE; 24299a2dd95SBruce Richardson 24399a2dd95SBruce Richardson /* interpret flags */ 24499a2dd95SBruce Richardson if (prm->flags & RTE_IPSEC_SAFLAG_SQN_ATOM) 24599a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_SQN_ATOM; 24699a2dd95SBruce Richardson else 24799a2dd95SBruce Richardson tp |= RTE_IPSEC_SATP_SQN_RAW; 24899a2dd95SBruce Richardson 24999a2dd95SBruce Richardson *type = tp; 25099a2dd95SBruce Richardson return 0; 25199a2dd95SBruce Richardson } 25299a2dd95SBruce Richardson 25399a2dd95SBruce Richardson /* 25499a2dd95SBruce Richardson * Init ESP inbound specific things. 25599a2dd95SBruce Richardson */ 25699a2dd95SBruce Richardson static void 25799a2dd95SBruce Richardson esp_inb_init(struct rte_ipsec_sa *sa) 25899a2dd95SBruce Richardson { 25999a2dd95SBruce Richardson /* these params may differ with new algorithms support */ 26099a2dd95SBruce Richardson sa->ctp.cipher.offset = sizeof(struct rte_esp_hdr) + sa->iv_len; 26199a2dd95SBruce Richardson sa->ctp.cipher.length = sa->icv_len + sa->ctp.cipher.offset; 26299a2dd95SBruce Richardson 26399a2dd95SBruce Richardson /* 264c99d2619SRadu Nicolau * for AEAD algorithms we can assume that 26599a2dd95SBruce Richardson * auth and cipher offsets would be equal. 26699a2dd95SBruce Richardson */ 26799a2dd95SBruce Richardson switch (sa->algo_type) { 26899a2dd95SBruce Richardson case ALGO_TYPE_AES_GCM: 269c99d2619SRadu Nicolau case ALGO_TYPE_AES_CCM: 270c99d2619SRadu Nicolau case ALGO_TYPE_CHACHA20_POLY1305: 27199a2dd95SBruce Richardson sa->ctp.auth.raw = sa->ctp.cipher.raw; 27299a2dd95SBruce Richardson break; 27399a2dd95SBruce Richardson default: 27499a2dd95SBruce Richardson sa->ctp.auth.offset = 0; 27599a2dd95SBruce Richardson sa->ctp.auth.length = sa->icv_len - sa->sqh_len; 27699a2dd95SBruce Richardson sa->cofs.ofs.cipher.tail = sa->sqh_len; 27799a2dd95SBruce Richardson break; 27899a2dd95SBruce Richardson } 27999a2dd95SBruce Richardson 28099a2dd95SBruce Richardson sa->cofs.ofs.cipher.head = sa->ctp.cipher.offset - sa->ctp.auth.offset; 28199a2dd95SBruce Richardson } 28299a2dd95SBruce Richardson 28399a2dd95SBruce Richardson /* 28499a2dd95SBruce Richardson * Init ESP inbound tunnel specific things. 28599a2dd95SBruce Richardson */ 28699a2dd95SBruce Richardson static void 28799a2dd95SBruce Richardson esp_inb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm) 28899a2dd95SBruce Richardson { 28999a2dd95SBruce Richardson sa->proto = prm->tun.next_proto; 29099a2dd95SBruce Richardson esp_inb_init(sa); 29199a2dd95SBruce Richardson } 29299a2dd95SBruce Richardson 29399a2dd95SBruce Richardson /* 29499a2dd95SBruce Richardson * Init ESP outbound specific things. 29599a2dd95SBruce Richardson */ 29699a2dd95SBruce Richardson static void 2972ed40da8SRadu Nicolau esp_outb_init(struct rte_ipsec_sa *sa, uint32_t hlen, uint64_t sqn) 29899a2dd95SBruce Richardson { 29999a2dd95SBruce Richardson uint8_t algo_type; 30099a2dd95SBruce Richardson 3012ed40da8SRadu Nicolau sa->sqn.outb = sqn > 1 ? sqn : 1; 30299a2dd95SBruce Richardson 30399a2dd95SBruce Richardson algo_type = sa->algo_type; 30499a2dd95SBruce Richardson 30599a2dd95SBruce Richardson /* 30699a2dd95SBruce Richardson * Setup auth and cipher length and offset. 30799a2dd95SBruce Richardson * these params may differ with new algorithms support 30899a2dd95SBruce Richardson */ 30999a2dd95SBruce Richardson 31099a2dd95SBruce Richardson switch (algo_type) { 31199a2dd95SBruce Richardson case ALGO_TYPE_AES_GCM: 312c99d2619SRadu Nicolau case ALGO_TYPE_AES_CCM: 313c99d2619SRadu Nicolau case ALGO_TYPE_CHACHA20_POLY1305: 31499a2dd95SBruce Richardson case ALGO_TYPE_AES_CTR: 31599a2dd95SBruce Richardson case ALGO_TYPE_NULL: 31699a2dd95SBruce Richardson sa->ctp.cipher.offset = hlen + sizeof(struct rte_esp_hdr) + 31799a2dd95SBruce Richardson sa->iv_len; 31899a2dd95SBruce Richardson sa->ctp.cipher.length = 0; 31999a2dd95SBruce Richardson break; 32099a2dd95SBruce Richardson case ALGO_TYPE_AES_CBC: 32199a2dd95SBruce Richardson case ALGO_TYPE_3DES_CBC: 32299a2dd95SBruce Richardson sa->ctp.cipher.offset = hlen + sizeof(struct rte_esp_hdr); 32399a2dd95SBruce Richardson sa->ctp.cipher.length = sa->iv_len; 32499a2dd95SBruce Richardson break; 325c99d2619SRadu Nicolau case ALGO_TYPE_AES_GMAC: 326c99d2619SRadu Nicolau sa->ctp.cipher.offset = 0; 327c99d2619SRadu Nicolau sa->ctp.cipher.length = 0; 328c99d2619SRadu Nicolau break; 32999a2dd95SBruce Richardson } 33099a2dd95SBruce Richardson 33199a2dd95SBruce Richardson /* 332c99d2619SRadu Nicolau * for AEAD algorithms we can assume that 33399a2dd95SBruce Richardson * auth and cipher offsets would be equal. 33499a2dd95SBruce Richardson */ 33599a2dd95SBruce Richardson switch (algo_type) { 33699a2dd95SBruce Richardson case ALGO_TYPE_AES_GCM: 337c99d2619SRadu Nicolau case ALGO_TYPE_AES_CCM: 338c99d2619SRadu Nicolau case ALGO_TYPE_CHACHA20_POLY1305: 33999a2dd95SBruce Richardson sa->ctp.auth.raw = sa->ctp.cipher.raw; 34099a2dd95SBruce Richardson break; 34199a2dd95SBruce Richardson default: 34299a2dd95SBruce Richardson sa->ctp.auth.offset = hlen; 34399a2dd95SBruce Richardson sa->ctp.auth.length = sizeof(struct rte_esp_hdr) + 34499a2dd95SBruce Richardson sa->iv_len + sa->sqh_len; 34599a2dd95SBruce Richardson break; 34699a2dd95SBruce Richardson } 34799a2dd95SBruce Richardson 34899a2dd95SBruce Richardson sa->cofs.ofs.cipher.head = sa->ctp.cipher.offset - sa->ctp.auth.offset; 34999a2dd95SBruce Richardson sa->cofs.ofs.cipher.tail = (sa->ctp.auth.offset + sa->ctp.auth.length) - 35099a2dd95SBruce Richardson (sa->ctp.cipher.offset + sa->ctp.cipher.length); 35199a2dd95SBruce Richardson } 35299a2dd95SBruce Richardson 35399a2dd95SBruce Richardson /* 35499a2dd95SBruce Richardson * Init ESP outbound tunnel specific things. 35599a2dd95SBruce Richardson */ 35699a2dd95SBruce Richardson static void 35799a2dd95SBruce Richardson esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm) 35899a2dd95SBruce Richardson { 35999a2dd95SBruce Richardson sa->proto = prm->tun.next_proto; 36099a2dd95SBruce Richardson sa->hdr_len = prm->tun.hdr_len; 36199a2dd95SBruce Richardson sa->hdr_l3_off = prm->tun.hdr_l3_off; 36299a2dd95SBruce Richardson 36301eef590SRadu Nicolau memcpy(sa->hdr, prm->tun.hdr, prm->tun.hdr_len); 36401eef590SRadu Nicolau 36501eef590SRadu Nicolau /* insert UDP header if UDP encapsulation is inabled */ 36601eef590SRadu Nicolau if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) { 36701eef590SRadu Nicolau struct rte_udp_hdr *udph = (struct rte_udp_hdr *) 36801eef590SRadu Nicolau &sa->hdr[prm->tun.hdr_len]; 36901eef590SRadu Nicolau sa->hdr_len += sizeof(struct rte_udp_hdr); 37001eef590SRadu Nicolau udph->src_port = prm->ipsec_xform.udp.sport; 37101eef590SRadu Nicolau udph->dst_port = prm->ipsec_xform.udp.dport; 37201eef590SRadu Nicolau udph->dgram_cksum = 0; 37301eef590SRadu Nicolau } 37401eef590SRadu Nicolau 37599a2dd95SBruce Richardson /* update l2_len and l3_len fields for outbound mbuf */ 37699a2dd95SBruce Richardson sa->tx_offload.val = rte_mbuf_tx_offload(sa->hdr_l3_off, 37799a2dd95SBruce Richardson sa->hdr_len - sa->hdr_l3_off, 0, 0, 0, 0, 0); 37899a2dd95SBruce Richardson 3792ed40da8SRadu Nicolau esp_outb_init(sa, sa->hdr_len, prm->ipsec_xform.esn.value); 38099a2dd95SBruce Richardson } 38199a2dd95SBruce Richardson 38299a2dd95SBruce Richardson /* 38399a2dd95SBruce Richardson * helper function, init SA structure. 38499a2dd95SBruce Richardson */ 38599a2dd95SBruce Richardson static int 38699a2dd95SBruce Richardson esp_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm, 38799a2dd95SBruce Richardson const struct crypto_xform *cxf) 38899a2dd95SBruce Richardson { 38999a2dd95SBruce Richardson static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK | 39001eef590SRadu Nicolau RTE_IPSEC_SATP_MODE_MASK | 39101eef590SRadu Nicolau RTE_IPSEC_SATP_NATT_MASK; 39299a2dd95SBruce Richardson 39399a2dd95SBruce Richardson if (prm->ipsec_xform.options.ecn) 39499a2dd95SBruce Richardson sa->tos_mask |= RTE_IPV4_HDR_ECN_MASK; 39599a2dd95SBruce Richardson 39699a2dd95SBruce Richardson if (prm->ipsec_xform.options.copy_dscp) 39799a2dd95SBruce Richardson sa->tos_mask |= RTE_IPV4_HDR_DSCP_MASK; 39899a2dd95SBruce Richardson 39999a2dd95SBruce Richardson if (cxf->aead != NULL) { 40099a2dd95SBruce Richardson switch (cxf->aead->algo) { 40199a2dd95SBruce Richardson case RTE_CRYPTO_AEAD_AES_GCM: 40299a2dd95SBruce Richardson /* RFC 4106 */ 40399a2dd95SBruce Richardson sa->aad_len = sizeof(struct aead_gcm_aad); 40499a2dd95SBruce Richardson sa->icv_len = cxf->aead->digest_length; 40599a2dd95SBruce Richardson sa->iv_ofs = cxf->aead->iv.offset; 40699a2dd95SBruce Richardson sa->iv_len = sizeof(uint64_t); 40799a2dd95SBruce Richardson sa->pad_align = IPSEC_PAD_AES_GCM; 40899a2dd95SBruce Richardson sa->algo_type = ALGO_TYPE_AES_GCM; 40999a2dd95SBruce Richardson break; 410c99d2619SRadu Nicolau case RTE_CRYPTO_AEAD_AES_CCM: 411c99d2619SRadu Nicolau /* RFC 4309 */ 412c99d2619SRadu Nicolau sa->aad_len = sizeof(struct aead_ccm_aad); 413c99d2619SRadu Nicolau sa->icv_len = cxf->aead->digest_length; 414c99d2619SRadu Nicolau sa->iv_ofs = cxf->aead->iv.offset; 415c99d2619SRadu Nicolau sa->iv_len = sizeof(uint64_t); 416c99d2619SRadu Nicolau sa->pad_align = IPSEC_PAD_AES_CCM; 417c99d2619SRadu Nicolau sa->algo_type = ALGO_TYPE_AES_CCM; 418c99d2619SRadu Nicolau break; 419c99d2619SRadu Nicolau case RTE_CRYPTO_AEAD_CHACHA20_POLY1305: 420c99d2619SRadu Nicolau /* RFC 7634 & 8439*/ 421c99d2619SRadu Nicolau sa->aad_len = sizeof(struct aead_chacha20_poly1305_aad); 422c99d2619SRadu Nicolau sa->icv_len = cxf->aead->digest_length; 423c99d2619SRadu Nicolau sa->iv_ofs = cxf->aead->iv.offset; 424c99d2619SRadu Nicolau sa->iv_len = sizeof(uint64_t); 425c99d2619SRadu Nicolau sa->pad_align = IPSEC_PAD_CHACHA20_POLY1305; 426c99d2619SRadu Nicolau sa->algo_type = ALGO_TYPE_CHACHA20_POLY1305; 427c99d2619SRadu Nicolau break; 42899a2dd95SBruce Richardson default: 42999a2dd95SBruce Richardson return -EINVAL; 43099a2dd95SBruce Richardson } 431c99d2619SRadu Nicolau } else if (cxf->auth->algo == RTE_CRYPTO_AUTH_AES_GMAC) { 432c99d2619SRadu Nicolau /* RFC 4543 */ 433c99d2619SRadu Nicolau /* AES-GMAC is a special case of auth that needs IV */ 434c99d2619SRadu Nicolau sa->pad_align = IPSEC_PAD_AES_GMAC; 435c99d2619SRadu Nicolau sa->iv_len = sizeof(uint64_t); 436c99d2619SRadu Nicolau sa->icv_len = cxf->auth->digest_length; 437c99d2619SRadu Nicolau sa->iv_ofs = cxf->auth->iv.offset; 438c99d2619SRadu Nicolau sa->algo_type = ALGO_TYPE_AES_GMAC; 439c99d2619SRadu Nicolau 44099a2dd95SBruce Richardson } else { 44199a2dd95SBruce Richardson sa->icv_len = cxf->auth->digest_length; 44299a2dd95SBruce Richardson sa->iv_ofs = cxf->cipher->iv.offset; 44399a2dd95SBruce Richardson 44499a2dd95SBruce Richardson switch (cxf->cipher->algo) { 44599a2dd95SBruce Richardson case RTE_CRYPTO_CIPHER_NULL: 44699a2dd95SBruce Richardson sa->pad_align = IPSEC_PAD_NULL; 44799a2dd95SBruce Richardson sa->iv_len = 0; 44899a2dd95SBruce Richardson sa->algo_type = ALGO_TYPE_NULL; 44999a2dd95SBruce Richardson break; 45099a2dd95SBruce Richardson 45199a2dd95SBruce Richardson case RTE_CRYPTO_CIPHER_AES_CBC: 45299a2dd95SBruce Richardson sa->pad_align = IPSEC_PAD_AES_CBC; 45399a2dd95SBruce Richardson sa->iv_len = IPSEC_MAX_IV_SIZE; 45499a2dd95SBruce Richardson sa->algo_type = ALGO_TYPE_AES_CBC; 45599a2dd95SBruce Richardson break; 45699a2dd95SBruce Richardson 45799a2dd95SBruce Richardson case RTE_CRYPTO_CIPHER_AES_CTR: 45899a2dd95SBruce Richardson /* RFC 3686 */ 45999a2dd95SBruce Richardson sa->pad_align = IPSEC_PAD_AES_CTR; 46099a2dd95SBruce Richardson sa->iv_len = IPSEC_AES_CTR_IV_SIZE; 46199a2dd95SBruce Richardson sa->algo_type = ALGO_TYPE_AES_CTR; 46299a2dd95SBruce Richardson break; 46399a2dd95SBruce Richardson 46499a2dd95SBruce Richardson case RTE_CRYPTO_CIPHER_3DES_CBC: 46599a2dd95SBruce Richardson /* RFC 1851 */ 46699a2dd95SBruce Richardson sa->pad_align = IPSEC_PAD_3DES_CBC; 46799a2dd95SBruce Richardson sa->iv_len = IPSEC_3DES_IV_SIZE; 46899a2dd95SBruce Richardson sa->algo_type = ALGO_TYPE_3DES_CBC; 46999a2dd95SBruce Richardson break; 47099a2dd95SBruce Richardson 47199a2dd95SBruce Richardson default: 47299a2dd95SBruce Richardson return -EINVAL; 47399a2dd95SBruce Richardson } 47499a2dd95SBruce Richardson } 47599a2dd95SBruce Richardson 476c99d2619SRadu Nicolau sa->sqh_len = IS_ESN(sa) ? sizeof(uint32_t) : 0; 47799a2dd95SBruce Richardson sa->udata = prm->userdata; 47899a2dd95SBruce Richardson sa->spi = rte_cpu_to_be_32(prm->ipsec_xform.spi); 47999a2dd95SBruce Richardson sa->salt = prm->ipsec_xform.salt; 48099a2dd95SBruce Richardson 48199a2dd95SBruce Richardson /* preserve all values except l2_len and l3_len */ 48299a2dd95SBruce Richardson sa->tx_offload.msk = 48399a2dd95SBruce Richardson ~rte_mbuf_tx_offload(MBUF_MAX_L2_LEN, MBUF_MAX_L3_LEN, 48499a2dd95SBruce Richardson 0, 0, 0, 0, 0); 48599a2dd95SBruce Richardson 48699a2dd95SBruce Richardson switch (sa->type & msk) { 48799a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4): 48899a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6): 48999a2dd95SBruce Richardson esp_inb_tun_init(sa, prm); 49099a2dd95SBruce Richardson break; 49199a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS): 49299a2dd95SBruce Richardson esp_inb_init(sa); 49399a2dd95SBruce Richardson break; 49401eef590SRadu Nicolau case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4 | 49501eef590SRadu Nicolau RTE_IPSEC_SATP_NATT_ENABLE): 49601eef590SRadu Nicolau case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6 | 49701eef590SRadu Nicolau RTE_IPSEC_SATP_NATT_ENABLE): 49899a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): 49999a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): 50099a2dd95SBruce Richardson esp_outb_tun_init(sa, prm); 50199a2dd95SBruce Richardson break; 50201eef590SRadu Nicolau case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS | 50301eef590SRadu Nicolau RTE_IPSEC_SATP_NATT_ENABLE): 50499a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS): 5052ed40da8SRadu Nicolau esp_outb_init(sa, 0, prm->ipsec_xform.esn.value); 50699a2dd95SBruce Richardson break; 50799a2dd95SBruce Richardson } 50899a2dd95SBruce Richardson 50999a2dd95SBruce Richardson return 0; 51099a2dd95SBruce Richardson } 51199a2dd95SBruce Richardson 51299a2dd95SBruce Richardson /* 51399a2dd95SBruce Richardson * helper function, init SA replay structure. 51499a2dd95SBruce Richardson */ 51599a2dd95SBruce Richardson static void 5162ed40da8SRadu Nicolau fill_sa_replay(struct rte_ipsec_sa *sa, uint32_t wnd_sz, uint32_t nb_bucket, 5172ed40da8SRadu Nicolau uint64_t sqn) 51899a2dd95SBruce Richardson { 51999a2dd95SBruce Richardson sa->replay.win_sz = wnd_sz; 52099a2dd95SBruce Richardson sa->replay.nb_bucket = nb_bucket; 52199a2dd95SBruce Richardson sa->replay.bucket_index_mask = nb_bucket - 1; 52299a2dd95SBruce Richardson sa->sqn.inb.rsn[0] = (struct replay_sqn *)(sa + 1); 5232ed40da8SRadu Nicolau sa->sqn.inb.rsn[0]->sqn = sqn; 5242ed40da8SRadu Nicolau if ((sa->type & RTE_IPSEC_SATP_SQN_MASK) == RTE_IPSEC_SATP_SQN_ATOM) { 52599a2dd95SBruce Richardson sa->sqn.inb.rsn[1] = (struct replay_sqn *) 52699a2dd95SBruce Richardson ((uintptr_t)sa->sqn.inb.rsn[0] + rsn_size(nb_bucket)); 5272ed40da8SRadu Nicolau sa->sqn.inb.rsn[1]->sqn = sqn; 5282ed40da8SRadu Nicolau } 52999a2dd95SBruce Richardson } 53099a2dd95SBruce Richardson 53199a2dd95SBruce Richardson int 53299a2dd95SBruce Richardson rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm) 53399a2dd95SBruce Richardson { 53499a2dd95SBruce Richardson uint64_t type; 53599a2dd95SBruce Richardson uint32_t nb, wsz; 53699a2dd95SBruce Richardson int32_t rc; 53799a2dd95SBruce Richardson 53899a2dd95SBruce Richardson if (prm == NULL) 53999a2dd95SBruce Richardson return -EINVAL; 54099a2dd95SBruce Richardson 54199a2dd95SBruce Richardson /* determine SA type */ 54299a2dd95SBruce Richardson rc = fill_sa_type(prm, &type); 54399a2dd95SBruce Richardson if (rc != 0) 54499a2dd95SBruce Richardson return rc; 54599a2dd95SBruce Richardson 54699a2dd95SBruce Richardson /* determine required size */ 54799a2dd95SBruce Richardson wsz = prm->ipsec_xform.replay_win_sz; 54899a2dd95SBruce Richardson return ipsec_sa_size(type, &wsz, &nb); 54999a2dd95SBruce Richardson } 55099a2dd95SBruce Richardson 55199a2dd95SBruce Richardson int 55299a2dd95SBruce Richardson rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm, 55399a2dd95SBruce Richardson uint32_t size) 55499a2dd95SBruce Richardson { 55599a2dd95SBruce Richardson int32_t rc, sz; 55699a2dd95SBruce Richardson uint32_t nb, wsz; 55799a2dd95SBruce Richardson uint64_t type; 55899a2dd95SBruce Richardson struct crypto_xform cxf; 55999a2dd95SBruce Richardson 56099a2dd95SBruce Richardson if (sa == NULL || prm == NULL) 56199a2dd95SBruce Richardson return -EINVAL; 56299a2dd95SBruce Richardson 56399a2dd95SBruce Richardson /* determine SA type */ 56499a2dd95SBruce Richardson rc = fill_sa_type(prm, &type); 56599a2dd95SBruce Richardson if (rc != 0) 56699a2dd95SBruce Richardson return rc; 56799a2dd95SBruce Richardson 56899a2dd95SBruce Richardson /* determine required size */ 56999a2dd95SBruce Richardson wsz = prm->ipsec_xform.replay_win_sz; 57099a2dd95SBruce Richardson sz = ipsec_sa_size(type, &wsz, &nb); 57199a2dd95SBruce Richardson if (sz < 0) 57299a2dd95SBruce Richardson return sz; 57399a2dd95SBruce Richardson else if (size < (uint32_t)sz) 57499a2dd95SBruce Richardson return -ENOSPC; 57599a2dd95SBruce Richardson 57699a2dd95SBruce Richardson /* only esp is supported right now */ 57799a2dd95SBruce Richardson if (prm->ipsec_xform.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) 57899a2dd95SBruce Richardson return -EINVAL; 57999a2dd95SBruce Richardson 58001eef590SRadu Nicolau if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 58101eef590SRadu Nicolau uint32_t hlen = prm->tun.hdr_len; 58201eef590SRadu Nicolau if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) 58301eef590SRadu Nicolau hlen += sizeof(struct rte_udp_hdr); 58401eef590SRadu Nicolau if (hlen > sizeof(sa->hdr)) 58599a2dd95SBruce Richardson return -EINVAL; 58601eef590SRadu Nicolau } 58799a2dd95SBruce Richardson 58899a2dd95SBruce Richardson rc = fill_crypto_xform(&cxf, type, prm); 58999a2dd95SBruce Richardson if (rc != 0) 59099a2dd95SBruce Richardson return rc; 59199a2dd95SBruce Richardson 59299a2dd95SBruce Richardson /* initialize SA */ 59399a2dd95SBruce Richardson 59499a2dd95SBruce Richardson memset(sa, 0, sz); 59599a2dd95SBruce Richardson sa->type = type; 59699a2dd95SBruce Richardson sa->size = sz; 59799a2dd95SBruce Richardson 59899a2dd95SBruce Richardson /* check for ESN flag */ 59999a2dd95SBruce Richardson sa->sqn_mask = (prm->ipsec_xform.options.esn == 0) ? 60099a2dd95SBruce Richardson UINT32_MAX : UINT64_MAX; 60199a2dd95SBruce Richardson 60299a2dd95SBruce Richardson rc = esp_sa_init(sa, prm, &cxf); 60399a2dd95SBruce Richardson if (rc != 0) 60499a2dd95SBruce Richardson rte_ipsec_sa_fini(sa); 60599a2dd95SBruce Richardson 60699a2dd95SBruce Richardson /* fill replay window related fields */ 60799a2dd95SBruce Richardson if (nb != 0) 6082ed40da8SRadu Nicolau fill_sa_replay(sa, wsz, nb, prm->ipsec_xform.esn.value); 60999a2dd95SBruce Richardson 61099a2dd95SBruce Richardson return sz; 61199a2dd95SBruce Richardson } 61299a2dd95SBruce Richardson 61399a2dd95SBruce Richardson /* 61499a2dd95SBruce Richardson * setup crypto ops for LOOKASIDE_PROTO type of devices. 61599a2dd95SBruce Richardson */ 61699a2dd95SBruce Richardson static inline void 61799a2dd95SBruce Richardson lksd_proto_cop_prepare(const struct rte_ipsec_session *ss, 61899a2dd95SBruce Richardson struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num) 61999a2dd95SBruce Richardson { 62099a2dd95SBruce Richardson uint32_t i; 62199a2dd95SBruce Richardson struct rte_crypto_sym_op *sop; 62299a2dd95SBruce Richardson 62399a2dd95SBruce Richardson for (i = 0; i != num; i++) { 62499a2dd95SBruce Richardson sop = cop[i]->sym; 62599a2dd95SBruce Richardson cop[i]->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 62699a2dd95SBruce Richardson cop[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 62799a2dd95SBruce Richardson cop[i]->sess_type = RTE_CRYPTO_OP_SECURITY_SESSION; 62899a2dd95SBruce Richardson sop->m_src = mb[i]; 62999a2dd95SBruce Richardson __rte_security_attach_session(sop, ss->security.ses); 63099a2dd95SBruce Richardson } 63199a2dd95SBruce Richardson } 63299a2dd95SBruce Richardson 63399a2dd95SBruce Richardson /* 63499a2dd95SBruce Richardson * setup packets and crypto ops for LOOKASIDE_PROTO type of devices. 63599a2dd95SBruce Richardson * Note that for LOOKASIDE_PROTO all packet modifications will be 63699a2dd95SBruce Richardson * performed by PMD/HW. 63799a2dd95SBruce Richardson * SW has only to prepare crypto op. 63899a2dd95SBruce Richardson */ 63999a2dd95SBruce Richardson static uint16_t 64099a2dd95SBruce Richardson lksd_proto_prepare(const struct rte_ipsec_session *ss, 64199a2dd95SBruce Richardson struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num) 64299a2dd95SBruce Richardson { 64399a2dd95SBruce Richardson lksd_proto_cop_prepare(ss, mb, cop, num); 64499a2dd95SBruce Richardson return num; 64599a2dd95SBruce Richardson } 64699a2dd95SBruce Richardson 64799a2dd95SBruce Richardson /* 64899a2dd95SBruce Richardson * simplest pkt process routine: 64999a2dd95SBruce Richardson * all actual processing is already done by HW/PMD, 65099a2dd95SBruce Richardson * just check mbuf ol_flags. 65199a2dd95SBruce Richardson * used for: 65299a2dd95SBruce Richardson * - inbound for RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL 65399a2dd95SBruce Richardson * - inbound/outbound for RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL 65499a2dd95SBruce Richardson * - outbound for RTE_SECURITY_ACTION_TYPE_NONE when ESN is disabled 65599a2dd95SBruce Richardson */ 65699a2dd95SBruce Richardson uint16_t 65799a2dd95SBruce Richardson pkt_flag_process(const struct rte_ipsec_session *ss, 65899a2dd95SBruce Richardson struct rte_mbuf *mb[], uint16_t num) 65999a2dd95SBruce Richardson { 66068977baaSRadu Nicolau uint32_t i, k, bytes; 66199a2dd95SBruce Richardson uint32_t dr[num]; 66299a2dd95SBruce Richardson 66399a2dd95SBruce Richardson RTE_SET_USED(ss); 66499a2dd95SBruce Richardson 66599a2dd95SBruce Richardson k = 0; 66668977baaSRadu Nicolau bytes = 0; 66799a2dd95SBruce Richardson for (i = 0; i != num; i++) { 668*daa02b5cSOlivier Matz if ((mb[i]->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED) == 0) { 66999a2dd95SBruce Richardson k++; 67068977baaSRadu Nicolau bytes += mb[i]->pkt_len; 67168977baaSRadu Nicolau } 67299a2dd95SBruce Richardson else 67399a2dd95SBruce Richardson dr[i - k] = i; 67499a2dd95SBruce Richardson } 67599a2dd95SBruce Richardson 67668977baaSRadu Nicolau ss->sa->statistics.count += k; 67768977baaSRadu Nicolau ss->sa->statistics.bytes += bytes; 67868977baaSRadu Nicolau 67999a2dd95SBruce Richardson /* handle unprocessed mbufs */ 68099a2dd95SBruce Richardson if (k != num) { 68199a2dd95SBruce Richardson rte_errno = EBADMSG; 68299a2dd95SBruce Richardson if (k != 0) 68399a2dd95SBruce Richardson move_bad_mbufs(mb, dr, num, num - k); 68499a2dd95SBruce Richardson } 68599a2dd95SBruce Richardson 68699a2dd95SBruce Richardson return k; 68799a2dd95SBruce Richardson } 68899a2dd95SBruce Richardson 68999a2dd95SBruce Richardson /* 69099a2dd95SBruce Richardson * Select packet processing function for session on LOOKASIDE_NONE 69199a2dd95SBruce Richardson * type of device. 69299a2dd95SBruce Richardson */ 69399a2dd95SBruce Richardson static int 69499a2dd95SBruce Richardson lksd_none_pkt_func_select(const struct rte_ipsec_sa *sa, 69599a2dd95SBruce Richardson struct rte_ipsec_sa_pkt_func *pf) 69699a2dd95SBruce Richardson { 69799a2dd95SBruce Richardson int32_t rc; 69899a2dd95SBruce Richardson 69999a2dd95SBruce Richardson static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK | 70099a2dd95SBruce Richardson RTE_IPSEC_SATP_MODE_MASK; 70199a2dd95SBruce Richardson 70299a2dd95SBruce Richardson rc = 0; 70399a2dd95SBruce Richardson switch (sa->type & msk) { 70499a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4): 70599a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6): 70699a2dd95SBruce Richardson pf->prepare.async = esp_inb_pkt_prepare; 70799a2dd95SBruce Richardson pf->process = esp_inb_tun_pkt_process; 70899a2dd95SBruce Richardson break; 70999a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS): 71099a2dd95SBruce Richardson pf->prepare.async = esp_inb_pkt_prepare; 71199a2dd95SBruce Richardson pf->process = esp_inb_trs_pkt_process; 71299a2dd95SBruce Richardson break; 71399a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): 71499a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): 71599a2dd95SBruce Richardson pf->prepare.async = esp_outb_tun_prepare; 71699a2dd95SBruce Richardson pf->process = (sa->sqh_len != 0) ? 71799a2dd95SBruce Richardson esp_outb_sqh_process : pkt_flag_process; 71899a2dd95SBruce Richardson break; 71999a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS): 72099a2dd95SBruce Richardson pf->prepare.async = esp_outb_trs_prepare; 72199a2dd95SBruce Richardson pf->process = (sa->sqh_len != 0) ? 72299a2dd95SBruce Richardson esp_outb_sqh_process : pkt_flag_process; 72399a2dd95SBruce Richardson break; 72499a2dd95SBruce Richardson default: 72599a2dd95SBruce Richardson rc = -ENOTSUP; 72699a2dd95SBruce Richardson } 72799a2dd95SBruce Richardson 72899a2dd95SBruce Richardson return rc; 72999a2dd95SBruce Richardson } 73099a2dd95SBruce Richardson 73199a2dd95SBruce Richardson static int 73299a2dd95SBruce Richardson cpu_crypto_pkt_func_select(const struct rte_ipsec_sa *sa, 73399a2dd95SBruce Richardson struct rte_ipsec_sa_pkt_func *pf) 73499a2dd95SBruce Richardson { 73599a2dd95SBruce Richardson int32_t rc; 73699a2dd95SBruce Richardson 73799a2dd95SBruce Richardson static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK | 73899a2dd95SBruce Richardson RTE_IPSEC_SATP_MODE_MASK; 73999a2dd95SBruce Richardson 74099a2dd95SBruce Richardson rc = 0; 74199a2dd95SBruce Richardson switch (sa->type & msk) { 74299a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4): 74399a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6): 74499a2dd95SBruce Richardson pf->prepare.sync = cpu_inb_pkt_prepare; 74599a2dd95SBruce Richardson pf->process = esp_inb_tun_pkt_process; 74699a2dd95SBruce Richardson break; 74799a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS): 74899a2dd95SBruce Richardson pf->prepare.sync = cpu_inb_pkt_prepare; 74999a2dd95SBruce Richardson pf->process = esp_inb_trs_pkt_process; 75099a2dd95SBruce Richardson break; 75199a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): 75299a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): 75399a2dd95SBruce Richardson pf->prepare.sync = cpu_outb_tun_pkt_prepare; 75499a2dd95SBruce Richardson pf->process = (sa->sqh_len != 0) ? 75599a2dd95SBruce Richardson esp_outb_sqh_process : pkt_flag_process; 75699a2dd95SBruce Richardson break; 75799a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS): 75899a2dd95SBruce Richardson pf->prepare.sync = cpu_outb_trs_pkt_prepare; 75999a2dd95SBruce Richardson pf->process = (sa->sqh_len != 0) ? 76099a2dd95SBruce Richardson esp_outb_sqh_process : pkt_flag_process; 76199a2dd95SBruce Richardson break; 76299a2dd95SBruce Richardson default: 76399a2dd95SBruce Richardson rc = -ENOTSUP; 76499a2dd95SBruce Richardson } 76599a2dd95SBruce Richardson 76699a2dd95SBruce Richardson return rc; 76799a2dd95SBruce Richardson } 76899a2dd95SBruce Richardson 76999a2dd95SBruce Richardson /* 77099a2dd95SBruce Richardson * Select packet processing function for session on INLINE_CRYPTO 77199a2dd95SBruce Richardson * type of device. 77299a2dd95SBruce Richardson */ 77399a2dd95SBruce Richardson static int 77499a2dd95SBruce Richardson inline_crypto_pkt_func_select(const struct rte_ipsec_sa *sa, 77599a2dd95SBruce Richardson struct rte_ipsec_sa_pkt_func *pf) 77699a2dd95SBruce Richardson { 77799a2dd95SBruce Richardson int32_t rc; 77899a2dd95SBruce Richardson 77999a2dd95SBruce Richardson static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK | 78099a2dd95SBruce Richardson RTE_IPSEC_SATP_MODE_MASK; 78199a2dd95SBruce Richardson 78299a2dd95SBruce Richardson rc = 0; 78399a2dd95SBruce Richardson switch (sa->type & msk) { 78499a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4): 78599a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6): 78699a2dd95SBruce Richardson pf->process = inline_inb_tun_pkt_process; 78799a2dd95SBruce Richardson break; 78899a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS): 78999a2dd95SBruce Richardson pf->process = inline_inb_trs_pkt_process; 79099a2dd95SBruce Richardson break; 79199a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): 79299a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): 79399a2dd95SBruce Richardson pf->process = inline_outb_tun_pkt_process; 79499a2dd95SBruce Richardson break; 79599a2dd95SBruce Richardson case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS): 79699a2dd95SBruce Richardson pf->process = inline_outb_trs_pkt_process; 79799a2dd95SBruce Richardson break; 79899a2dd95SBruce Richardson default: 79999a2dd95SBruce Richardson rc = -ENOTSUP; 80099a2dd95SBruce Richardson } 80199a2dd95SBruce Richardson 80299a2dd95SBruce Richardson return rc; 80399a2dd95SBruce Richardson } 80499a2dd95SBruce Richardson 80599a2dd95SBruce Richardson /* 80699a2dd95SBruce Richardson * Select packet processing function for given session based on SA parameters 80799a2dd95SBruce Richardson * and type of associated with the session device. 80899a2dd95SBruce Richardson */ 80999a2dd95SBruce Richardson int 81099a2dd95SBruce Richardson ipsec_sa_pkt_func_select(const struct rte_ipsec_session *ss, 81199a2dd95SBruce Richardson const struct rte_ipsec_sa *sa, struct rte_ipsec_sa_pkt_func *pf) 81299a2dd95SBruce Richardson { 81399a2dd95SBruce Richardson int32_t rc; 81499a2dd95SBruce Richardson 81599a2dd95SBruce Richardson rc = 0; 81699a2dd95SBruce Richardson pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, NULL }; 81799a2dd95SBruce Richardson 81899a2dd95SBruce Richardson switch (ss->type) { 81999a2dd95SBruce Richardson case RTE_SECURITY_ACTION_TYPE_NONE: 82099a2dd95SBruce Richardson rc = lksd_none_pkt_func_select(sa, pf); 82199a2dd95SBruce Richardson break; 82299a2dd95SBruce Richardson case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 82399a2dd95SBruce Richardson rc = inline_crypto_pkt_func_select(sa, pf); 82499a2dd95SBruce Richardson break; 82599a2dd95SBruce Richardson case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 82699a2dd95SBruce Richardson if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) == 82799a2dd95SBruce Richardson RTE_IPSEC_SATP_DIR_IB) 82899a2dd95SBruce Richardson pf->process = pkt_flag_process; 82999a2dd95SBruce Richardson else 83099a2dd95SBruce Richardson pf->process = inline_proto_outb_pkt_process; 83199a2dd95SBruce Richardson break; 83299a2dd95SBruce Richardson case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 83399a2dd95SBruce Richardson pf->prepare.async = lksd_proto_prepare; 83499a2dd95SBruce Richardson pf->process = pkt_flag_process; 83599a2dd95SBruce Richardson break; 83699a2dd95SBruce Richardson case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 83799a2dd95SBruce Richardson rc = cpu_crypto_pkt_func_select(sa, pf); 83899a2dd95SBruce Richardson break; 83999a2dd95SBruce Richardson default: 84099a2dd95SBruce Richardson rc = -ENOTSUP; 84199a2dd95SBruce Richardson } 84299a2dd95SBruce Richardson 84399a2dd95SBruce Richardson return rc; 84499a2dd95SBruce Richardson } 845