13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 25139d5d9SMarcin Smoczynski * Copyright(c) 2016-2020 Intel Corporation 3d299106eSSergio Gonzalez Monroy */ 455d4c775SDaniel Mrzyglod #include <sys/types.h> 5d299106eSSergio Gonzalez Monroy #include <netinet/in.h> 6d299106eSSergio Gonzalez Monroy #include <netinet/ip.h> 7d299106eSSergio Gonzalez Monroy 8d299106eSSergio Gonzalez Monroy #include <rte_branch_prediction.h> 9d299106eSSergio Gonzalez Monroy #include <rte_log.h> 10d299106eSSergio Gonzalez Monroy #include <rte_crypto.h> 11ec17993aSAkhil Goyal #include <rte_security.h> 12d299106eSSergio Gonzalez Monroy #include <rte_cryptodev.h> 135139d5d9SMarcin Smoczynski #include <rte_ipsec.h> 14ec17993aSAkhil Goyal #include <rte_ethdev.h> 15d299106eSSergio Gonzalez Monroy #include <rte_mbuf.h> 16d299106eSSergio Gonzalez Monroy #include <rte_hash.h> 17d299106eSSergio Gonzalez Monroy 18d299106eSSergio Gonzalez Monroy #include "ipsec.h" 19c64278c0SSergio Gonzalez Monroy #include "esp.h" 20d299106eSSergio Gonzalez Monroy 210ccfd14bSAnoob Joseph static inline void 220ccfd14bSAnoob Joseph set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec) 230ccfd14bSAnoob Joseph { 240ccfd14bSAnoob Joseph if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 250ccfd14bSAnoob Joseph struct rte_security_ipsec_tunnel_param *tunnel = 260ccfd14bSAnoob Joseph &ipsec->tunnel; 27b1a3ac78SMariusz Drost if (IS_IP4_TUNNEL(sa->flags)) { 280ccfd14bSAnoob Joseph tunnel->type = 290ccfd14bSAnoob Joseph RTE_SECURITY_IPSEC_TUNNEL_IPV4; 300ccfd14bSAnoob Joseph tunnel->ipv4.ttl = IPDEFTTL; 310ccfd14bSAnoob Joseph 320ccfd14bSAnoob Joseph memcpy((uint8_t *)&tunnel->ipv4.src_ip, 330ccfd14bSAnoob Joseph (uint8_t *)&sa->src.ip.ip4, 4); 340ccfd14bSAnoob Joseph 350ccfd14bSAnoob Joseph memcpy((uint8_t *)&tunnel->ipv4.dst_ip, 360ccfd14bSAnoob Joseph (uint8_t *)&sa->dst.ip.ip4, 4); 370d9b0263SAkhil Goyal } else if (IS_IP6_TUNNEL(sa->flags)) { 380d9b0263SAkhil Goyal tunnel->type = 390d9b0263SAkhil Goyal RTE_SECURITY_IPSEC_TUNNEL_IPV6; 400d9b0263SAkhil Goyal tunnel->ipv6.hlimit = IPDEFTTL; 410d9b0263SAkhil Goyal tunnel->ipv6.dscp = 0; 420d9b0263SAkhil Goyal tunnel->ipv6.flabel = 0; 430d9b0263SAkhil Goyal 440d9b0263SAkhil Goyal memcpy((uint8_t *)&tunnel->ipv6.src_addr, 450d9b0263SAkhil Goyal (uint8_t *)&sa->src.ip.ip6.ip6_b, 16); 460d9b0263SAkhil Goyal 470d9b0263SAkhil Goyal memcpy((uint8_t *)&tunnel->ipv6.dst_addr, 480d9b0263SAkhil Goyal (uint8_t *)&sa->dst.ip.ip6.ip6_b, 16); 490ccfd14bSAnoob Joseph } 500d9b0263SAkhil Goyal /* TODO support for Transport */ 510ccfd14bSAnoob Joseph } 520f56ca1aSHemant Agrawal ipsec->replay_win_sz = app_sa_prm.window_size; 530f56ca1aSHemant Agrawal ipsec->options.esn = app_sa_prm.enable_esn; 549a1cc8f1STejasree Kondoj ipsec->options.udp_encap = sa->udp_encap; 550ccfd14bSAnoob Joseph } 560ccfd14bSAnoob Joseph 573e5f4625SKonstantin Ananyev int 58a8ade121SVolodymyr Fialko create_lookaside_session(struct ipsec_ctx *ipsec_ctx_lcore[], 59a8ade121SVolodymyr Fialko struct socket_ctx *skt_ctx, struct ipsec_sa *sa, 604a67af84SMarcin Smoczynski struct rte_ipsec_session *ips) 61d299106eSSergio Gonzalez Monroy { 62a8ade121SVolodymyr Fialko uint16_t cdev_id = RTE_CRYPTO_MAX_DEVS; 63c5aa9617SAkhil Goyal struct rte_cryptodev_info cdev_info; 644e942500SSergio Gonzalez Monroy unsigned long cdev_id_qp = 0; 65d299106eSSergio Gonzalez Monroy struct cdev_key key = { 0 }; 66a8ade121SVolodymyr Fialko struct ipsec_ctx *ipsec_ctx; 67a8ade121SVolodymyr Fialko uint32_t lcore_id; 68a8ade121SVolodymyr Fialko int32_t ret = 0; 69d299106eSSergio Gonzalez Monroy 70a8ade121SVolodymyr Fialko RTE_LCORE_FOREACH(lcore_id) { 71a8ade121SVolodymyr Fialko ipsec_ctx = ipsec_ctx_lcore[lcore_id]; 72d299106eSSergio Gonzalez Monroy 73a8ade121SVolodymyr Fialko /* Core is not bound to any cryptodev, skip it */ 74a8ade121SVolodymyr Fialko if (ipsec_ctx->cdev_map == NULL) 75a8ade121SVolodymyr Fialko continue; 76a8ade121SVolodymyr Fialko 77a8ade121SVolodymyr Fialko /* Looking for cryptodev, which can handle this SA */ 78a8ade121SVolodymyr Fialko key.lcore_id = (uint8_t)lcore_id; 79d299106eSSergio Gonzalez Monroy key.cipher_algo = (uint8_t)sa->cipher_algo; 80d299106eSSergio Gonzalez Monroy key.auth_algo = (uint8_t)sa->auth_algo; 81d00f3890SAviad Yehezkel key.aead_algo = (uint8_t)sa->aead_algo; 82d299106eSSergio Gonzalez Monroy 83d299106eSSergio Gonzalez Monroy ret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key, 84d299106eSSergio Gonzalez Monroy (void **)&cdev_id_qp); 85a8ade121SVolodymyr Fialko if (ret == -ENOENT) 86a8ade121SVolodymyr Fialko continue; 87d299106eSSergio Gonzalez Monroy if (ret < 0) { 88ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 89ec17993aSAkhil Goyal "No cryptodev: core %u, cipher_algo %u, " 90d00f3890SAviad Yehezkel "auth_algo %u, aead_algo %u\n", 91d00f3890SAviad Yehezkel key.lcore_id, 92d00f3890SAviad Yehezkel key.cipher_algo, 93d00f3890SAviad Yehezkel key.auth_algo, 94d00f3890SAviad Yehezkel key.aead_algo); 95a8ade121SVolodymyr Fialko return ret; 96d299106eSSergio Gonzalez Monroy } 97d299106eSSergio Gonzalez Monroy 98a8ade121SVolodymyr Fialko /* Verify that all cores are using same cryptodev for current 99a8ade121SVolodymyr Fialko * algorithm combination, required by SA. 100a8ade121SVolodymyr Fialko * Current cryptodev mapping process will map SA to the first 101a8ade121SVolodymyr Fialko * cryptodev that matches requirements, so it's a double check, 102a8ade121SVolodymyr Fialko * not an additional restriction. 103a8ade121SVolodymyr Fialko */ 104a8ade121SVolodymyr Fialko if (cdev_id == RTE_CRYPTO_MAX_DEVS) 105a8ade121SVolodymyr Fialko cdev_id = ipsec_ctx->tbl[cdev_id_qp].id; 106a8ade121SVolodymyr Fialko else if (cdev_id != ipsec_ctx->tbl[cdev_id_qp].id) { 107a8ade121SVolodymyr Fialko RTE_LOG(ERR, IPSEC, 108a8ade121SVolodymyr Fialko "SA mapping to multiple cryptodevs is " 109a8ade121SVolodymyr Fialko "not supported!"); 110a8ade121SVolodymyr Fialko return -EINVAL; 111a8ade121SVolodymyr Fialko } 112a8ade121SVolodymyr Fialko 113a8ade121SVolodymyr Fialko /* Store per core queue pair information */ 114a8ade121SVolodymyr Fialko sa->cqp[lcore_id] = &ipsec_ctx->tbl[cdev_id_qp]; 115a8ade121SVolodymyr Fialko } 116a8ade121SVolodymyr Fialko if (cdev_id == RTE_CRYPTO_MAX_DEVS) { 117a8ade121SVolodymyr Fialko RTE_LOG(WARNING, IPSEC, "No cores found to handle SA\n"); 118a8ade121SVolodymyr Fialko return 0; 119a8ade121SVolodymyr Fialko } 120a8ade121SVolodymyr Fialko 121a8ade121SVolodymyr Fialko RTE_LOG(DEBUG, IPSEC, "Create session for SA spi %u on cryptodev " 122a8ade121SVolodymyr Fialko "%u\n", sa->spi, cdev_id); 123d299106eSSergio Gonzalez Monroy 1245139d5d9SMarcin Smoczynski if (ips->type != RTE_SECURITY_ACTION_TYPE_NONE && 1255139d5d9SMarcin Smoczynski ips->type != RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) { 126ec17993aSAkhil Goyal struct rte_security_session_conf sess_conf = { 1274a67af84SMarcin Smoczynski .action_type = ips->type, 128ec17993aSAkhil Goyal .protocol = RTE_SECURITY_PROTOCOL_IPSEC, 129376ee1deSRadu Nicolau {.ipsec = { 130ec17993aSAkhil Goyal .spi = sa->spi, 131ec17993aSAkhil Goyal .salt = sa->salt, 132ec17993aSAkhil Goyal .options = { 0 }, 1330f56ca1aSHemant Agrawal .replay_win_sz = 0, 134ec17993aSAkhil Goyal .direction = sa->direction, 135ec17993aSAkhil Goyal .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, 136b1a3ac78SMariusz Drost .mode = (IS_TUNNEL(sa->flags)) ? 137ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_MODE_TUNNEL : 138ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, 139376ee1deSRadu Nicolau } }, 1400ccfd14bSAnoob Joseph .crypto_xform = sa->xforms, 1410ccfd14bSAnoob Joseph .userdata = NULL, 142ec17993aSAkhil Goyal 143ec17993aSAkhil Goyal }; 144ec17993aSAkhil Goyal 1454a67af84SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) { 146ec17993aSAkhil Goyal struct rte_security_ctx *ctx = (struct rte_security_ctx *) 147ec17993aSAkhil Goyal rte_cryptodev_get_sec_ctx( 148a8ade121SVolodymyr Fialko cdev_id); 149ec17993aSAkhil Goyal 1500ccfd14bSAnoob Joseph /* Set IPsec parameters in conf */ 1510ccfd14bSAnoob Joseph set_ipsec_conf(sa, &(sess_conf.ipsec)); 152ec17993aSAkhil Goyal 1534a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(ctx, 154a8ade121SVolodymyr Fialko &sess_conf, skt_ctx->session_pool, 155a8ade121SVolodymyr Fialko skt_ctx->session_priv_pool); 1564a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 157ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 158ec17993aSAkhil Goyal "SEC Session init failed: err: %d\n", ret); 159ec17993aSAkhil Goyal return -1; 160ec17993aSAkhil Goyal } 1618e814e18SVolodymyr Fialko ips->security.ctx = ctx; 1623a690d5aSBernard Iremonger } else { 1633a690d5aSBernard Iremonger RTE_LOG(ERR, IPSEC, "Inline not supported\n"); 1643a690d5aSBernard Iremonger return -1; 1653a690d5aSBernard Iremonger } 1663a690d5aSBernard Iremonger } else { 1675139d5d9SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) { 1685139d5d9SMarcin Smoczynski struct rte_cryptodev_info info; 1695139d5d9SMarcin Smoczynski 1705139d5d9SMarcin Smoczynski rte_cryptodev_info_get(cdev_id, &info); 1715139d5d9SMarcin Smoczynski if (!(info.feature_flags & 1725139d5d9SMarcin Smoczynski RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO)) 1735139d5d9SMarcin Smoczynski return -ENOTSUP; 1745139d5d9SMarcin Smoczynski 1755139d5d9SMarcin Smoczynski } 1768e814e18SVolodymyr Fialko ips->crypto.dev_id = cdev_id; 177*bdce2564SAkhil Goyal ips->crypto.ses = rte_cryptodev_sym_session_create(cdev_id, 178*bdce2564SAkhil Goyal sa->xforms, skt_ctx->session_pool); 1793a690d5aSBernard Iremonger 1808e814e18SVolodymyr Fialko rte_cryptodev_info_get(cdev_id, &cdev_info); 1813a690d5aSBernard Iremonger } 1823a690d5aSBernard Iremonger 1833a690d5aSBernard Iremonger return 0; 1843a690d5aSBernard Iremonger } 1853a690d5aSBernard Iremonger 1863a690d5aSBernard Iremonger int 1874a67af84SMarcin Smoczynski create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa, 1884a67af84SMarcin Smoczynski struct rte_ipsec_session *ips) 1893a690d5aSBernard Iremonger { 1903a690d5aSBernard Iremonger int32_t ret = 0; 1913a690d5aSBernard Iremonger struct rte_security_ctx *sec_ctx; 1923a690d5aSBernard Iremonger struct rte_security_session_conf sess_conf = { 1934a67af84SMarcin Smoczynski .action_type = ips->type, 1943a690d5aSBernard Iremonger .protocol = RTE_SECURITY_PROTOCOL_IPSEC, 1953a690d5aSBernard Iremonger {.ipsec = { 1963a690d5aSBernard Iremonger .spi = sa->spi, 1973a690d5aSBernard Iremonger .salt = sa->salt, 1983a690d5aSBernard Iremonger .options = { 0 }, 1990f56ca1aSHemant Agrawal .replay_win_sz = 0, 2003a690d5aSBernard Iremonger .direction = sa->direction, 2016019feadSRadu Nicolau .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP 2023a690d5aSBernard Iremonger } }, 2033a690d5aSBernard Iremonger .crypto_xform = sa->xforms, 2043a690d5aSBernard Iremonger .userdata = NULL, 2053a690d5aSBernard Iremonger }; 2063a690d5aSBernard Iremonger 2076019feadSRadu Nicolau if (IS_TRANSPORT(sa->flags)) { 2086019feadSRadu Nicolau sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT; 2096019feadSRadu Nicolau if (IS_IP4(sa->flags)) { 2106019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2116019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV4; 2126019feadSRadu Nicolau 2136019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr = 2146019feadSRadu Nicolau sa->src.ip.ip4; 2156019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr = 2166019feadSRadu Nicolau sa->dst.ip.ip4; 2176019feadSRadu Nicolau } else if (IS_IP6(sa->flags)) { 2186019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2196019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV6; 2206019feadSRadu Nicolau 2216019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr, 2226019feadSRadu Nicolau sa->src.ip.ip6.ip6_b, 16); 2236019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr, 2246019feadSRadu Nicolau sa->dst.ip.ip6.ip6_b, 16); 2256019feadSRadu Nicolau } 2266019feadSRadu Nicolau } else if (IS_TUNNEL(sa->flags)) { 2276019feadSRadu Nicolau sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL; 2286019feadSRadu Nicolau 2296019feadSRadu Nicolau if (IS_IP4(sa->flags)) { 2306019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2316019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV4; 2326019feadSRadu Nicolau 2336019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr = 2346019feadSRadu Nicolau sa->src.ip.ip4; 2356019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr = 2366019feadSRadu Nicolau sa->dst.ip.ip4; 2376019feadSRadu Nicolau } else if (IS_IP6(sa->flags)) { 2386019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2396019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV6; 2406019feadSRadu Nicolau 2416019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr, 2426019feadSRadu Nicolau sa->src.ip.ip6.ip6_b, 16); 2436019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr, 2446019feadSRadu Nicolau sa->dst.ip.ip6.ip6_b, 16); 2456019feadSRadu Nicolau } else { 2466019feadSRadu Nicolau RTE_LOG(ERR, IPSEC, "invalid tunnel type\n"); 2476019feadSRadu Nicolau return -1; 2486019feadSRadu Nicolau } 2496019feadSRadu Nicolau } 2506019feadSRadu Nicolau 2519ae86b4cSRadu Nicolau if (sa->udp_encap) { 2529ae86b4cSRadu Nicolau sess_conf.ipsec.options.udp_encap = 1; 2539ae86b4cSRadu Nicolau sess_conf.ipsec.udp.sport = htons(sa->udp.sport); 2549ae86b4cSRadu Nicolau sess_conf.ipsec.udp.dport = htons(sa->udp.dport); 2559ae86b4cSRadu Nicolau } 2569ae86b4cSRadu Nicolau 257560029d5SRadu Nicolau if (sa->esn > 0) { 258560029d5SRadu Nicolau sess_conf.ipsec.options.esn = 1; 259560029d5SRadu Nicolau sess_conf.ipsec.esn.value = sa->esn; 260560029d5SRadu Nicolau } 261560029d5SRadu Nicolau 262560029d5SRadu Nicolau 2633a690d5aSBernard Iremonger RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n", 2643a690d5aSBernard Iremonger sa->spi, sa->portid); 2653a690d5aSBernard Iremonger 2664a67af84SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { 267ec17993aSAkhil Goyal struct rte_flow_error err; 268ec17993aSAkhil Goyal const struct rte_security_capability *sec_cap; 269a4677f78SNélio Laranjeiro int ret = 0; 270ec17993aSAkhil Goyal 2713a690d5aSBernard Iremonger sec_ctx = (struct rte_security_ctx *) 2723a690d5aSBernard Iremonger rte_eth_dev_get_sec_ctx( 2733a690d5aSBernard Iremonger sa->portid); 2743a690d5aSBernard Iremonger if (sec_ctx == NULL) { 2753a690d5aSBernard Iremonger RTE_LOG(ERR, IPSEC, 2763a690d5aSBernard Iremonger " rte_eth_dev_get_sec_ctx failed\n"); 2773a690d5aSBernard Iremonger return -1; 2783a690d5aSBernard Iremonger } 2793a690d5aSBernard Iremonger 2804a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(sec_ctx, 281e30b2833SAkhil Goyal &sess_conf, skt_ctx->session_pool, 282e30b2833SAkhil Goyal skt_ctx->session_priv_pool); 2834a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 284ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 285ec17993aSAkhil Goyal "SEC Session init failed: err: %d\n", ret); 286ec17993aSAkhil Goyal return -1; 287ec17993aSAkhil Goyal } 288ec17993aSAkhil Goyal 2893a690d5aSBernard Iremonger sec_cap = rte_security_capabilities_get(sec_ctx); 290ec17993aSAkhil Goyal 291ec17993aSAkhil Goyal /* iterate until ESP tunnel*/ 2923a690d5aSBernard Iremonger while (sec_cap->action != RTE_SECURITY_ACTION_TYPE_NONE) { 2934a67af84SMarcin Smoczynski if (sec_cap->action == ips->type && 294ec17993aSAkhil Goyal sec_cap->protocol == 295ec17993aSAkhil Goyal RTE_SECURITY_PROTOCOL_IPSEC && 296ec17993aSAkhil Goyal sec_cap->ipsec.mode == 2973a690d5aSBernard Iremonger RTE_SECURITY_IPSEC_SA_MODE_TUNNEL && 298ec17993aSAkhil Goyal sec_cap->ipsec.direction == sa->direction) 299ec17993aSAkhil Goyal break; 300ec17993aSAkhil Goyal sec_cap++; 301ec17993aSAkhil Goyal } 302ec17993aSAkhil Goyal 303ec17993aSAkhil Goyal if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) { 304ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 305ec17993aSAkhil Goyal "No suitable security capability found\n"); 306ec17993aSAkhil Goyal return -1; 307ec17993aSAkhil Goyal } 308ec17993aSAkhil Goyal 3094a67af84SMarcin Smoczynski ips->security.ol_flags = sec_cap->ol_flags; 3104a67af84SMarcin Smoczynski ips->security.ctx = sec_ctx; 311ec17993aSAkhil Goyal sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 312ec17993aSAkhil Goyal 313b1a3ac78SMariusz Drost if (IS_IP6(sa->flags)) { 314b1a3ac78SMariusz Drost sa->pattern[1].mask = &rte_flow_item_ipv6_mask; 315b1a3ac78SMariusz Drost sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 316ec17993aSAkhil Goyal sa->pattern[1].spec = &sa->ipv6_spec; 317b1a3ac78SMariusz Drost 318ec17993aSAkhil Goyal memcpy(sa->ipv6_spec.hdr.dst_addr, 319ec17993aSAkhil Goyal sa->dst.ip.ip6.ip6_b, 16); 320ec17993aSAkhil Goyal memcpy(sa->ipv6_spec.hdr.src_addr, 321ec17993aSAkhil Goyal sa->src.ip.ip6.ip6_b, 16); 322b1a3ac78SMariusz Drost } else if (IS_IP4(sa->flags)) { 323b1a3ac78SMariusz Drost sa->pattern[1].mask = &rte_flow_item_ipv4_mask; 324b1a3ac78SMariusz Drost sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 325ec17993aSAkhil Goyal sa->pattern[1].spec = &sa->ipv4_spec; 326b1a3ac78SMariusz Drost 327ec17993aSAkhil Goyal sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4; 328ec17993aSAkhil Goyal sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4; 329ec17993aSAkhil Goyal } 330ec17993aSAkhil Goyal 3319ae86b4cSRadu Nicolau sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 3329ae86b4cSRadu Nicolau 3339ae86b4cSRadu Nicolau if (sa->udp_encap) { 3349ae86b4cSRadu Nicolau 3359ae86b4cSRadu Nicolau sa->udp_spec.hdr.dst_port = 3369ae86b4cSRadu Nicolau rte_cpu_to_be_16(sa->udp.dport); 3379ae86b4cSRadu Nicolau sa->udp_spec.hdr.src_port = 3389ae86b4cSRadu Nicolau rte_cpu_to_be_16(sa->udp.sport); 3399ae86b4cSRadu Nicolau 3409ae86b4cSRadu Nicolau sa->pattern[2].mask = &rte_flow_item_udp_mask; 3419ae86b4cSRadu Nicolau sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP; 3429ae86b4cSRadu Nicolau sa->pattern[2].spec = &sa->udp_spec; 3439ae86b4cSRadu Nicolau 3449ae86b4cSRadu Nicolau sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP; 3459ae86b4cSRadu Nicolau sa->pattern[3].spec = &sa->esp_spec; 3469ae86b4cSRadu Nicolau sa->pattern[3].mask = &rte_flow_item_esp_mask; 3479ae86b4cSRadu Nicolau 3489ae86b4cSRadu Nicolau sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END; 3499ae86b4cSRadu Nicolau } else { 350ec17993aSAkhil Goyal sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 351ec17993aSAkhil Goyal sa->pattern[2].spec = &sa->esp_spec; 352ec17993aSAkhil Goyal sa->pattern[2].mask = &rte_flow_item_esp_mask; 353ec17993aSAkhil Goyal 354ec17993aSAkhil Goyal sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 3559ae86b4cSRadu Nicolau } 356ec17993aSAkhil Goyal 357ec17993aSAkhil Goyal sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY; 3584a67af84SMarcin Smoczynski sa->action[0].conf = ips->security.ses; 359ec17993aSAkhil Goyal 360ec17993aSAkhil Goyal sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 361ec17993aSAkhil Goyal 362ec17993aSAkhil Goyal sa->attr.egress = (sa->direction == 363ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_DIR_EGRESS); 364a4cde424SNélio Laranjeiro sa->attr.ingress = (sa->direction == 365a4cde424SNélio Laranjeiro RTE_SECURITY_IPSEC_SA_DIR_INGRESS); 366a4677f78SNélio Laranjeiro if (sa->attr.ingress) { 3676019feadSRadu Nicolau uint8_t rss_key[64]; 368a4677f78SNélio Laranjeiro struct rte_eth_rss_conf rss_conf = { 369a4677f78SNélio Laranjeiro .rss_key = rss_key, 3706019feadSRadu Nicolau .rss_key_len = sizeof(rss_key), 371a4677f78SNélio Laranjeiro }; 3720109baf1SMarcin Zapolski struct rte_eth_dev_info dev_info; 373a4677f78SNélio Laranjeiro uint16_t queue[RTE_MAX_QUEUES_PER_PORT]; 37419b3bc47SAdrien Mazarguil struct rte_flow_action_rss action_rss; 375a4677f78SNélio Laranjeiro unsigned int i; 376a4677f78SNélio Laranjeiro unsigned int j; 377a4677f78SNélio Laranjeiro 378513f192bSAnkur Dwivedi /* Don't create flow if default flow is created */ 379513f192bSAnkur Dwivedi if (flow_info_tbl[sa->portid].rx_def_flow) 380513f192bSAnkur Dwivedi return 0; 381513f192bSAnkur Dwivedi 38203ad0e5cSIvan Ilchenko ret = rte_eth_dev_info_get(sa->portid, &dev_info); 38303ad0e5cSIvan Ilchenko if (ret != 0) { 38403ad0e5cSIvan Ilchenko RTE_LOG(ERR, IPSEC, 38503ad0e5cSIvan Ilchenko "Error during getting device (port %u) info: %s\n", 38603ad0e5cSIvan Ilchenko sa->portid, strerror(-ret)); 38703ad0e5cSIvan Ilchenko return ret; 38803ad0e5cSIvan Ilchenko } 38903ad0e5cSIvan Ilchenko 390a4677f78SNélio Laranjeiro sa->action[2].type = RTE_FLOW_ACTION_TYPE_END; 391a4677f78SNélio Laranjeiro /* Try RSS. */ 392a4677f78SNélio Laranjeiro sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS; 393a4677f78SNélio Laranjeiro sa->action[1].conf = &action_rss; 39423742f21SBernard Iremonger ret = rte_eth_dev_rss_hash_conf_get(sa->portid, 39523742f21SBernard Iremonger &rss_conf); 39623742f21SBernard Iremonger if (ret != 0) { 39723742f21SBernard Iremonger RTE_LOG(ERR, IPSEC, 39823742f21SBernard Iremonger "rte_eth_dev_rss_hash_conf_get:ret=%d\n", 39923742f21SBernard Iremonger ret); 40023742f21SBernard Iremonger return -1; 40123742f21SBernard Iremonger } 4023a690d5aSBernard Iremonger for (i = 0, j = 0; i < dev_info.nb_rx_queues; ++i) 40319b3bc47SAdrien Mazarguil queue[j++] = i; 4043a690d5aSBernard Iremonger 405ac8d22deSAdrien Mazarguil action_rss = (struct rte_flow_action_rss){ 406ac8d22deSAdrien Mazarguil .types = rss_conf.rss_hf, 407ac8d22deSAdrien Mazarguil .key_len = rss_conf.rss_key_len, 408ac8d22deSAdrien Mazarguil .queue_num = j, 409ac8d22deSAdrien Mazarguil .key = rss_key, 410ac8d22deSAdrien Mazarguil .queue = queue, 411ac8d22deSAdrien Mazarguil }; 412a4677f78SNélio Laranjeiro ret = rte_flow_validate(sa->portid, &sa->attr, 413a4677f78SNélio Laranjeiro sa->pattern, sa->action, 414a4677f78SNélio Laranjeiro &err); 415a4677f78SNélio Laranjeiro if (!ret) 416a4677f78SNélio Laranjeiro goto flow_create; 417a4677f78SNélio Laranjeiro /* Try Queue. */ 418a4677f78SNélio Laranjeiro sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE; 419a4677f78SNélio Laranjeiro sa->action[1].conf = 420a4677f78SNélio Laranjeiro &(struct rte_flow_action_queue){ 421a4677f78SNélio Laranjeiro .index = 0, 422a4677f78SNélio Laranjeiro }; 423a4677f78SNélio Laranjeiro ret = rte_flow_validate(sa->portid, &sa->attr, 424a4677f78SNélio Laranjeiro sa->pattern, sa->action, 425a4677f78SNélio Laranjeiro &err); 4266138c2daSRadu Nicolau /* Try End. */ 4276138c2daSRadu Nicolau sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 4286138c2daSRadu Nicolau sa->action[1].conf = NULL; 4296138c2daSRadu Nicolau ret = rte_flow_validate(sa->portid, &sa->attr, 4306138c2daSRadu Nicolau sa->pattern, sa->action, 4316138c2daSRadu Nicolau &err); 432a4677f78SNélio Laranjeiro if (ret) 433a4677f78SNélio Laranjeiro goto flow_create_failure; 434a90e6ce6SNélio Laranjeiro } else if (sa->attr.egress && 4354a67af84SMarcin Smoczynski (ips->security.ol_flags & 436a90e6ce6SNélio Laranjeiro RTE_SECURITY_TX_HW_TRAILER_OFFLOAD)) { 437a90e6ce6SNélio Laranjeiro sa->action[1].type = 438a90e6ce6SNélio Laranjeiro RTE_FLOW_ACTION_TYPE_PASSTHRU; 439a90e6ce6SNélio Laranjeiro sa->action[2].type = 440a90e6ce6SNélio Laranjeiro RTE_FLOW_ACTION_TYPE_END; 441a4677f78SNélio Laranjeiro } 442a4677f78SNélio Laranjeiro flow_create: 443ec17993aSAkhil Goyal sa->flow = rte_flow_create(sa->portid, 444ec17993aSAkhil Goyal &sa->attr, sa->pattern, sa->action, &err); 445ec17993aSAkhil Goyal if (sa->flow == NULL) { 446a4677f78SNélio Laranjeiro flow_create_failure: 447ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 448ec17993aSAkhil Goyal "Failed to create ipsec flow msg: %s\n", 449ec17993aSAkhil Goyal err.message); 450ec17993aSAkhil Goyal return -1; 451ec17993aSAkhil Goyal } 4524a67af84SMarcin Smoczynski } else if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) { 4530ccfd14bSAnoob Joseph const struct rte_security_capability *sec_cap; 4540ccfd14bSAnoob Joseph 4553a690d5aSBernard Iremonger sec_ctx = (struct rte_security_ctx *) 4563a690d5aSBernard Iremonger rte_eth_dev_get_sec_ctx(sa->portid); 4573a690d5aSBernard Iremonger 4583a690d5aSBernard Iremonger if (sec_ctx == NULL) { 4590ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 4600ccfd14bSAnoob Joseph "Ethernet device doesn't have security features registered\n"); 4610ccfd14bSAnoob Joseph return -1; 4620ccfd14bSAnoob Joseph } 4630ccfd14bSAnoob Joseph 4640ccfd14bSAnoob Joseph /* Set IPsec parameters in conf */ 4650ccfd14bSAnoob Joseph set_ipsec_conf(sa, &(sess_conf.ipsec)); 4660ccfd14bSAnoob Joseph 4670ccfd14bSAnoob Joseph /* Save SA as userdata for the security session. When 4680ccfd14bSAnoob Joseph * the packet is received, this userdata will be 4690ccfd14bSAnoob Joseph * retrieved using the metadata from the packet. 4700ccfd14bSAnoob Joseph * 471fa4de2ccSAnoob Joseph * The PMD is expected to set similar metadata for other 472fa4de2ccSAnoob Joseph * operations, like rte_eth_event, which are tied to 473fa4de2ccSAnoob Joseph * security session. In such cases, the userdata could 474fa4de2ccSAnoob Joseph * be obtained to uniquely identify the security 475fa4de2ccSAnoob Joseph * parameters denoted. 4760ccfd14bSAnoob Joseph */ 4770ccfd14bSAnoob Joseph 4780ccfd14bSAnoob Joseph sess_conf.userdata = (void *) sa; 4790ccfd14bSAnoob Joseph 4804a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(sec_ctx, 481e30b2833SAkhil Goyal &sess_conf, skt_ctx->session_pool, 482e30b2833SAkhil Goyal skt_ctx->session_priv_pool); 4834a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 4840ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 4850ccfd14bSAnoob Joseph "SEC Session init failed: err: %d\n", ret); 4860ccfd14bSAnoob Joseph return -1; 4870ccfd14bSAnoob Joseph } 4880ccfd14bSAnoob Joseph 4893a690d5aSBernard Iremonger sec_cap = rte_security_capabilities_get(sec_ctx); 4900ccfd14bSAnoob Joseph if (sec_cap == NULL) { 4910ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 4920ccfd14bSAnoob Joseph "No capabilities registered\n"); 4930ccfd14bSAnoob Joseph return -1; 4940ccfd14bSAnoob Joseph } 4950ccfd14bSAnoob Joseph 4960ccfd14bSAnoob Joseph /* iterate until ESP tunnel*/ 4970ccfd14bSAnoob Joseph while (sec_cap->action != 4980ccfd14bSAnoob Joseph RTE_SECURITY_ACTION_TYPE_NONE) { 4994a67af84SMarcin Smoczynski if (sec_cap->action == ips->type && 5000ccfd14bSAnoob Joseph sec_cap->protocol == 5010ccfd14bSAnoob Joseph RTE_SECURITY_PROTOCOL_IPSEC && 5020ccfd14bSAnoob Joseph sec_cap->ipsec.mode == 503b1a3ac78SMariusz Drost sess_conf.ipsec.mode && 5040ccfd14bSAnoob Joseph sec_cap->ipsec.direction == sa->direction) 5050ccfd14bSAnoob Joseph break; 5060ccfd14bSAnoob Joseph sec_cap++; 5070ccfd14bSAnoob Joseph } 5080ccfd14bSAnoob Joseph 5090ccfd14bSAnoob Joseph if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) { 5100ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 5110ccfd14bSAnoob Joseph "No suitable security capability found\n"); 5120ccfd14bSAnoob Joseph return -1; 5130ccfd14bSAnoob Joseph } 5140ccfd14bSAnoob Joseph 5154a67af84SMarcin Smoczynski ips->security.ol_flags = sec_cap->ol_flags; 5164a67af84SMarcin Smoczynski ips->security.ctx = sec_ctx; 517ec17993aSAkhil Goyal } 518d299106eSSergio Gonzalez Monroy 519d299106eSSergio Gonzalez Monroy return 0; 520d299106eSSergio Gonzalez Monroy } 521d299106eSSergio Gonzalez Monroy 5226738c0a9SPraveen Shetty int 5236738c0a9SPraveen Shetty create_ipsec_esp_flow(struct ipsec_sa *sa) 5246738c0a9SPraveen Shetty { 5256738c0a9SPraveen Shetty int ret = 0; 5260b512a92SVolodymyr Fialko struct rte_flow_error err = {}; 5276738c0a9SPraveen Shetty if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 5286738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, 5296738c0a9SPraveen Shetty "No Flow director rule for Egress traffic\n"); 5306738c0a9SPraveen Shetty return -1; 5316738c0a9SPraveen Shetty } 5326738c0a9SPraveen Shetty if (sa->flags == TRANSPORT) { 5336738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, 5346738c0a9SPraveen Shetty "No Flow director rule for transport mode\n"); 5356738c0a9SPraveen Shetty return -1; 5366738c0a9SPraveen Shetty } 5376738c0a9SPraveen Shetty sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; 5386738c0a9SPraveen Shetty sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 5396738c0a9SPraveen Shetty sa->action[0].conf = &(struct rte_flow_action_queue) { 5406738c0a9SPraveen Shetty .index = sa->fdir_qid, 5416738c0a9SPraveen Shetty }; 5426738c0a9SPraveen Shetty sa->attr.egress = 0; 5436738c0a9SPraveen Shetty sa->attr.ingress = 1; 5446738c0a9SPraveen Shetty if (IS_IP6(sa->flags)) { 5456738c0a9SPraveen Shetty sa->pattern[1].mask = &rte_flow_item_ipv6_mask; 5466738c0a9SPraveen Shetty sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 5476738c0a9SPraveen Shetty sa->pattern[1].spec = &sa->ipv6_spec; 5486738c0a9SPraveen Shetty memcpy(sa->ipv6_spec.hdr.dst_addr, 5496738c0a9SPraveen Shetty sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b)); 5506738c0a9SPraveen Shetty memcpy(sa->ipv6_spec.hdr.src_addr, 5516738c0a9SPraveen Shetty sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b)); 5526738c0a9SPraveen Shetty sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 5536738c0a9SPraveen Shetty sa->pattern[2].spec = &sa->esp_spec; 5546738c0a9SPraveen Shetty sa->pattern[2].mask = &rte_flow_item_esp_mask; 5556738c0a9SPraveen Shetty sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 5566738c0a9SPraveen Shetty sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 5576738c0a9SPraveen Shetty } else if (IS_IP4(sa->flags)) { 5586738c0a9SPraveen Shetty sa->pattern[1].mask = &rte_flow_item_ipv4_mask; 5596738c0a9SPraveen Shetty sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 5606738c0a9SPraveen Shetty sa->pattern[1].spec = &sa->ipv4_spec; 5616738c0a9SPraveen Shetty sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4; 5626738c0a9SPraveen Shetty sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4; 5636738c0a9SPraveen Shetty sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 5646738c0a9SPraveen Shetty sa->pattern[2].spec = &sa->esp_spec; 5656738c0a9SPraveen Shetty sa->pattern[2].mask = &rte_flow_item_esp_mask; 5666738c0a9SPraveen Shetty sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 5676738c0a9SPraveen Shetty sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 5686738c0a9SPraveen Shetty } 5696738c0a9SPraveen Shetty sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 5706738c0a9SPraveen Shetty 5716738c0a9SPraveen Shetty ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action, 5726738c0a9SPraveen Shetty &err); 5736738c0a9SPraveen Shetty if (ret < 0) { 5746738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message); 5756738c0a9SPraveen Shetty return ret; 5766738c0a9SPraveen Shetty } 5776738c0a9SPraveen Shetty 5786738c0a9SPraveen Shetty sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern, 5796738c0a9SPraveen Shetty sa->action, &err); 5806738c0a9SPraveen Shetty if (!sa->flow) { 5816738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message); 5826738c0a9SPraveen Shetty return -1; 5836738c0a9SPraveen Shetty } 5846738c0a9SPraveen Shetty 5856738c0a9SPraveen Shetty return 0; 5866738c0a9SPraveen Shetty } 5876738c0a9SPraveen Shetty 588d87152e7SKonstantin Ananyev /* 589d87152e7SKonstantin Ananyev * queue crypto-ops into PMD queue. 590d87152e7SKonstantin Ananyev */ 591d87152e7SKonstantin Ananyev void 592d87152e7SKonstantin Ananyev enqueue_cop_burst(struct cdev_qp *cqp) 593d299106eSSergio Gonzalez Monroy { 594d87152e7SKonstantin Ananyev uint32_t i, len, ret; 595d299106eSSergio Gonzalez Monroy 596d87152e7SKonstantin Ananyev len = cqp->len; 597d87152e7SKonstantin Ananyev ret = rte_cryptodev_enqueue_burst(cqp->id, cqp->qp, cqp->buf, len); 598d87152e7SKonstantin Ananyev if (ret < len) { 5995d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, IPSEC, "Cryptodev %u queue %u:" 600d299106eSSergio Gonzalez Monroy " enqueued %u crypto ops out of %u\n", 601d87152e7SKonstantin Ananyev cqp->id, cqp->qp, ret, len); 602d87152e7SKonstantin Ananyev /* drop packets that we fail to enqueue */ 603d87152e7SKonstantin Ananyev for (i = ret; i < len; i++) 6041329602bSAnoob Joseph free_pkts(&cqp->buf[i]->sym->m_src, 1); 605d299106eSSergio Gonzalez Monroy } 606d299106eSSergio Gonzalez Monroy cqp->in_flight += ret; 607d299106eSSergio Gonzalez Monroy cqp->len = 0; 608d299106eSSergio Gonzalez Monroy } 609d87152e7SKonstantin Ananyev 610d87152e7SKonstantin Ananyev static inline void 611d87152e7SKonstantin Ananyev enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop) 612d87152e7SKonstantin Ananyev { 613d87152e7SKonstantin Ananyev cqp->buf[cqp->len++] = cop; 614d87152e7SKonstantin Ananyev 615d87152e7SKonstantin Ananyev if (cqp->len == MAX_PKT_BURST) 616d87152e7SKonstantin Ananyev enqueue_cop_burst(cqp); 617d299106eSSergio Gonzalez Monroy } 618d299106eSSergio Gonzalez Monroy 619c64278c0SSergio Gonzalez Monroy static inline void 620c64278c0SSergio Gonzalez Monroy ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 621ba66534fSMarcin Smoczynski struct rte_mbuf *pkts[], void *sas[], 622c64278c0SSergio Gonzalez Monroy uint16_t nb_pkts) 623d299106eSSergio Gonzalez Monroy { 624906257e9SSergio Gonzalez Monroy int32_t ret = 0, i; 625d299106eSSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 626ec17993aSAkhil Goyal struct rte_crypto_sym_op *sym_cop; 627d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa; 6284a67af84SMarcin Smoczynski struct rte_ipsec_session *ips; 629d299106eSSergio Gonzalez Monroy 630d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_pkts; i++) { 63185f84767SSergio Gonzalez Monroy if (unlikely(sas[i] == NULL)) { 6321329602bSAnoob Joseph free_pkts(&pkts[i], 1); 63385f84767SSergio Gonzalez Monroy continue; 63485f84767SSergio Gonzalez Monroy } 63585f84767SSergio Gonzalez Monroy 636d299106eSSergio Gonzalez Monroy rte_prefetch0(sas[i]); 637d299106eSSergio Gonzalez Monroy rte_prefetch0(pkts[i]); 638d299106eSSergio Gonzalez Monroy 639d299106eSSergio Gonzalez Monroy priv = get_priv(pkts[i]); 640ba66534fSMarcin Smoczynski sa = ipsec_mask_saptr(sas[i]); 641d299106eSSergio Gonzalez Monroy priv->sa = sa; 642ba66534fSMarcin Smoczynski ips = ipsec_get_primary_session(sa); 643d299106eSSergio Gonzalez Monroy 6444a67af84SMarcin Smoczynski switch (ips->type) { 645ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 646ec17993aSAkhil Goyal priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 647ec17993aSAkhil Goyal priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 648ec17993aSAkhil Goyal 649ec17993aSAkhil Goyal rte_prefetch0(&priv->sym_cop); 650ec17993aSAkhil Goyal 651a8ade121SVolodymyr Fialko if (unlikely(ips->security.ses == NULL)) { 6521329602bSAnoob Joseph free_pkts(&pkts[i], 1); 653ec17993aSAkhil Goyal continue; 654ec17993aSAkhil Goyal } 655ec17993aSAkhil Goyal 6569a1cc8f1STejasree Kondoj if (unlikely((pkts[i]->packet_type & 6579a1cc8f1STejasree Kondoj (RTE_PTYPE_TUNNEL_MASK | 6589a1cc8f1STejasree Kondoj RTE_PTYPE_L4_MASK)) == 6599a1cc8f1STejasree Kondoj MBUF_PTYPE_TUNNEL_ESP_IN_UDP && 6609a1cc8f1STejasree Kondoj sa->udp_encap != 1)) { 6619a1cc8f1STejasree Kondoj free_pkts(&pkts[i], 1); 6629a1cc8f1STejasree Kondoj continue; 6639a1cc8f1STejasree Kondoj } 6649a1cc8f1STejasree Kondoj 665ec17993aSAkhil Goyal sym_cop = get_sym_cop(&priv->cop); 666ec17993aSAkhil Goyal sym_cop->m_src = pkts[i]; 667ec17993aSAkhil Goyal 668ec17993aSAkhil Goyal rte_security_attach_session(&priv->cop, 6694a67af84SMarcin Smoczynski ips->security.ses); 670ec17993aSAkhil Goyal break; 6715139d5d9SMarcin Smoczynski 6725139d5d9SMarcin Smoczynski case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 6735139d5d9SMarcin Smoczynski RTE_LOG(ERR, IPSEC, "CPU crypto is not supported by the" 6745139d5d9SMarcin Smoczynski " legacy mode."); 6751329602bSAnoob Joseph free_pkts(&pkts[i], 1); 6765139d5d9SMarcin Smoczynski continue; 6775139d5d9SMarcin Smoczynski 678ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_NONE: 679ec17993aSAkhil Goyal 680d299106eSSergio Gonzalez Monroy priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 681a60c05b5SSergio Gonzalez Monroy priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 682d299106eSSergio Gonzalez Monroy 683d299106eSSergio Gonzalez Monroy rte_prefetch0(&priv->sym_cop); 684d299106eSSergio Gonzalez Monroy 685a8ade121SVolodymyr Fialko if (unlikely(ips->crypto.ses == NULL)) { 6861329602bSAnoob Joseph free_pkts(&pkts[i], 1); 687d299106eSSergio Gonzalez Monroy continue; 688d299106eSSergio Gonzalez Monroy } 689d299106eSSergio Gonzalez Monroy 690d299106eSSergio Gonzalez Monroy rte_crypto_op_attach_sym_session(&priv->cop, 6914a67af84SMarcin Smoczynski ips->crypto.ses); 692d299106eSSergio Gonzalez Monroy 693c64278c0SSergio Gonzalez Monroy ret = xform_func(pkts[i], sa, &priv->cop); 694d299106eSSergio Gonzalez Monroy if (unlikely(ret)) { 6951329602bSAnoob Joseph free_pkts(&pkts[i], 1); 696d299106eSSergio Gonzalez Monroy continue; 697d299106eSSergio Gonzalez Monroy } 698ec17993aSAkhil Goyal break; 699ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 7004a67af84SMarcin Smoczynski RTE_ASSERT(ips->security.ses != NULL); 7013da37f68SRadu Nicolau ipsec_ctx->ol_pkts[ipsec_ctx->ol_pkts_cnt++] = pkts[i]; 7024a67af84SMarcin Smoczynski if (ips->security.ol_flags & 7034a67af84SMarcin Smoczynski RTE_SECURITY_TX_OLOAD_NEED_MDATA) 7040ccfd14bSAnoob Joseph rte_security_set_pkt_metadata( 7054a67af84SMarcin Smoczynski ips->security.ctx, ips->security.ses, 7064a67af84SMarcin Smoczynski pkts[i], NULL); 7070ccfd14bSAnoob Joseph continue; 708ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 7094a67af84SMarcin Smoczynski RTE_ASSERT(ips->security.ses != NULL); 710ec17993aSAkhil Goyal priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 711ec17993aSAkhil Goyal priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 712ec17993aSAkhil Goyal 713ec17993aSAkhil Goyal rte_prefetch0(&priv->sym_cop); 714ec17993aSAkhil Goyal rte_security_attach_session(&priv->cop, 7154a67af84SMarcin Smoczynski ips->security.ses); 716ec17993aSAkhil Goyal 717ec17993aSAkhil Goyal ret = xform_func(pkts[i], sa, &priv->cop); 718ec17993aSAkhil Goyal if (unlikely(ret)) { 7191329602bSAnoob Joseph free_pkts(&pkts[i], 1); 720ec17993aSAkhil Goyal continue; 721ec17993aSAkhil Goyal } 722ec17993aSAkhil Goyal 7233da37f68SRadu Nicolau ipsec_ctx->ol_pkts[ipsec_ctx->ol_pkts_cnt++] = pkts[i]; 7244a67af84SMarcin Smoczynski if (ips->security.ol_flags & 7254a67af84SMarcin Smoczynski RTE_SECURITY_TX_OLOAD_NEED_MDATA) 726ec17993aSAkhil Goyal rte_security_set_pkt_metadata( 7274a67af84SMarcin Smoczynski ips->security.ctx, ips->security.ses, 7284a67af84SMarcin Smoczynski pkts[i], NULL); 729ec17993aSAkhil Goyal continue; 730ec17993aSAkhil Goyal } 731d299106eSSergio Gonzalez Monroy 732a8ade121SVolodymyr Fialko enqueue_cop(sa->cqp[ipsec_ctx->lcore_id], &priv->cop); 733d299106eSSergio Gonzalez Monroy } 734c64278c0SSergio Gonzalez Monroy } 735d299106eSSergio Gonzalez Monroy 736d87152e7SKonstantin Ananyev static inline int32_t 737d87152e7SKonstantin Ananyev ipsec_inline_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 738d87152e7SKonstantin Ananyev struct rte_mbuf *pkts[], uint16_t max_pkts) 739d87152e7SKonstantin Ananyev { 740d87152e7SKonstantin Ananyev int32_t nb_pkts, ret; 741d87152e7SKonstantin Ananyev struct ipsec_mbuf_metadata *priv; 742d87152e7SKonstantin Ananyev struct ipsec_sa *sa; 743d87152e7SKonstantin Ananyev struct rte_mbuf *pkt; 744d87152e7SKonstantin Ananyev 745d87152e7SKonstantin Ananyev nb_pkts = 0; 746d87152e7SKonstantin Ananyev while (ipsec_ctx->ol_pkts_cnt > 0 && nb_pkts < max_pkts) { 747d87152e7SKonstantin Ananyev pkt = ipsec_ctx->ol_pkts[--ipsec_ctx->ol_pkts_cnt]; 748d87152e7SKonstantin Ananyev rte_prefetch0(pkt); 749d87152e7SKonstantin Ananyev priv = get_priv(pkt); 750d87152e7SKonstantin Ananyev sa = priv->sa; 751d87152e7SKonstantin Ananyev ret = xform_func(pkt, sa, &priv->cop); 752d87152e7SKonstantin Ananyev if (unlikely(ret)) { 7531329602bSAnoob Joseph free_pkts(&pkt, 1); 754d87152e7SKonstantin Ananyev continue; 755d87152e7SKonstantin Ananyev } 756d87152e7SKonstantin Ananyev pkts[nb_pkts++] = pkt; 757d87152e7SKonstantin Ananyev } 758d87152e7SKonstantin Ananyev 759d87152e7SKonstantin Ananyev return nb_pkts; 760d87152e7SKonstantin Ananyev } 761d87152e7SKonstantin Ananyev 762c64278c0SSergio Gonzalez Monroy static inline int 763c64278c0SSergio Gonzalez Monroy ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 764c64278c0SSergio Gonzalez Monroy struct rte_mbuf *pkts[], uint16_t max_pkts) 765c64278c0SSergio Gonzalez Monroy { 766906257e9SSergio Gonzalez Monroy int32_t nb_pkts = 0, ret = 0, i, j, nb_cops; 767c64278c0SSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 768c64278c0SSergio Gonzalez Monroy struct rte_crypto_op *cops[max_pkts]; 769c64278c0SSergio Gonzalez Monroy struct ipsec_sa *sa; 770c64278c0SSergio Gonzalez Monroy struct rte_mbuf *pkt; 771c64278c0SSergio Gonzalez Monroy 772833e36b8SRadu Nicolau for (i = 0; i < ipsec_ctx->nb_qps && nb_pkts < max_pkts; i++) { 773d299106eSSergio Gonzalez Monroy struct cdev_qp *cqp; 774833e36b8SRadu Nicolau 775833e36b8SRadu Nicolau cqp = &ipsec_ctx->tbl[ipsec_ctx->last_qp++]; 776833e36b8SRadu Nicolau if (ipsec_ctx->last_qp == ipsec_ctx->nb_qps) 777833e36b8SRadu Nicolau ipsec_ctx->last_qp %= ipsec_ctx->nb_qps; 778d299106eSSergio Gonzalez Monroy 779833e36b8SRadu Nicolau if (cqp->in_flight == 0) 780d299106eSSergio Gonzalez Monroy continue; 781d299106eSSergio Gonzalez Monroy 782d299106eSSergio Gonzalez Monroy nb_cops = rte_cryptodev_dequeue_burst(cqp->id, cqp->qp, 783d299106eSSergio Gonzalez Monroy cops, max_pkts - nb_pkts); 784d299106eSSergio Gonzalez Monroy 785d299106eSSergio Gonzalez Monroy cqp->in_flight -= nb_cops; 786d299106eSSergio Gonzalez Monroy 787d299106eSSergio Gonzalez Monroy for (j = 0; j < nb_cops; j++) { 788d299106eSSergio Gonzalez Monroy pkt = cops[j]->sym->m_src; 789d299106eSSergio Gonzalez Monroy rte_prefetch0(pkt); 790d299106eSSergio Gonzalez Monroy 791d299106eSSergio Gonzalez Monroy priv = get_priv(pkt); 792d299106eSSergio Gonzalez Monroy sa = priv->sa; 793d299106eSSergio Gonzalez Monroy 79450705e8eSThomas Monjalon RTE_ASSERT(sa != NULL); 795d299106eSSergio Gonzalez Monroy 7964a67af84SMarcin Smoczynski if (ipsec_get_action_type(sa) == 7974a67af84SMarcin Smoczynski RTE_SECURITY_ACTION_TYPE_NONE) { 798c64278c0SSergio Gonzalez Monroy ret = xform_func(pkt, sa, cops[j]); 799ec17993aSAkhil Goyal if (unlikely(ret)) { 8001329602bSAnoob Joseph free_pkts(&pkt, 1); 801ec17993aSAkhil Goyal continue; 802ec17993aSAkhil Goyal } 8034a67af84SMarcin Smoczynski } else if (ipsec_get_action_type(sa) == 80474ac7558SMichael Shamis RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) { 80574ac7558SMichael Shamis if (cops[j]->status) { 8061329602bSAnoob Joseph free_pkts(&pkt, 1); 80774ac7558SMichael Shamis continue; 80874ac7558SMichael Shamis } 809ec17993aSAkhil Goyal } 810d299106eSSergio Gonzalez Monroy pkts[nb_pkts++] = pkt; 811d299106eSSergio Gonzalez Monroy } 812d299106eSSergio Gonzalez Monroy } 813d299106eSSergio Gonzalez Monroy 814d299106eSSergio Gonzalez Monroy /* return packets */ 815d299106eSSergio Gonzalez Monroy return nb_pkts; 816d299106eSSergio Gonzalez Monroy } 817d299106eSSergio Gonzalez Monroy 818d299106eSSergio Gonzalez Monroy uint16_t 819d299106eSSergio Gonzalez Monroy ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 820d299106eSSergio Gonzalez Monroy uint16_t nb_pkts, uint16_t len) 821d299106eSSergio Gonzalez Monroy { 822ba66534fSMarcin Smoczynski void *sas[nb_pkts]; 823d299106eSSergio Gonzalez Monroy 824d299106eSSergio Gonzalez Monroy inbound_sa_lookup(ctx->sa_ctx, pkts, sas, nb_pkts); 825d299106eSSergio Gonzalez Monroy 826c64278c0SSergio Gonzalez Monroy ipsec_enqueue(esp_inbound, ctx, pkts, sas, nb_pkts); 827c64278c0SSergio Gonzalez Monroy 828d87152e7SKonstantin Ananyev return ipsec_inline_dequeue(esp_inbound_post, ctx, pkts, len); 829d87152e7SKonstantin Ananyev } 830d87152e7SKonstantin Ananyev 831d87152e7SKonstantin Ananyev uint16_t 832d87152e7SKonstantin Ananyev ipsec_inbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 833d87152e7SKonstantin Ananyev uint16_t len) 834d87152e7SKonstantin Ananyev { 835c64278c0SSergio Gonzalez Monroy return ipsec_dequeue(esp_inbound_post, ctx, pkts, len); 836d299106eSSergio Gonzalez Monroy } 837d299106eSSergio Gonzalez Monroy 838d299106eSSergio Gonzalez Monroy uint16_t 839d299106eSSergio Gonzalez Monroy ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 840d299106eSSergio Gonzalez Monroy uint32_t sa_idx[], uint16_t nb_pkts, uint16_t len) 841d299106eSSergio Gonzalez Monroy { 842ba66534fSMarcin Smoczynski void *sas[nb_pkts]; 843d299106eSSergio Gonzalez Monroy 844d299106eSSergio Gonzalez Monroy outbound_sa_lookup(ctx->sa_ctx, sa_idx, sas, nb_pkts); 845d299106eSSergio Gonzalez Monroy 846c64278c0SSergio Gonzalez Monroy ipsec_enqueue(esp_outbound, ctx, pkts, sas, nb_pkts); 847c64278c0SSergio Gonzalez Monroy 848d87152e7SKonstantin Ananyev return ipsec_inline_dequeue(esp_outbound_post, ctx, pkts, len); 849d87152e7SKonstantin Ananyev } 850d87152e7SKonstantin Ananyev 851d87152e7SKonstantin Ananyev uint16_t 852d87152e7SKonstantin Ananyev ipsec_outbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 853d87152e7SKonstantin Ananyev uint16_t len) 854d87152e7SKonstantin Ananyev { 855c64278c0SSergio Gonzalez Monroy return ipsec_dequeue(esp_outbound_post, ctx, pkts, len); 856d299106eSSergio Gonzalez Monroy } 857