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