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> 96938fc92SVolodymyr Fialko #include <rte_event_crypto_adapter.h> 10d299106eSSergio Gonzalez Monroy #include <rte_log.h> 11d299106eSSergio Gonzalez Monroy #include <rte_crypto.h> 12ec17993aSAkhil Goyal #include <rte_security.h> 13d299106eSSergio Gonzalez Monroy #include <rte_cryptodev.h> 145139d5d9SMarcin Smoczynski #include <rte_ipsec.h> 15ec17993aSAkhil Goyal #include <rte_ethdev.h> 16d299106eSSergio Gonzalez Monroy #include <rte_mbuf.h> 17d299106eSSergio Gonzalez Monroy #include <rte_hash.h> 18d299106eSSergio Gonzalez Monroy 19d299106eSSergio Gonzalez Monroy #include "ipsec.h" 20c64278c0SSergio Gonzalez Monroy #include "esp.h" 21d299106eSSergio Gonzalez Monroy 220ccfd14bSAnoob Joseph static inline void 230ccfd14bSAnoob Joseph set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec) 240ccfd14bSAnoob Joseph { 250ccfd14bSAnoob Joseph if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 260ccfd14bSAnoob Joseph struct rte_security_ipsec_tunnel_param *tunnel = 270ccfd14bSAnoob Joseph &ipsec->tunnel; 28b1a3ac78SMariusz Drost if (IS_IP4_TUNNEL(sa->flags)) { 290ccfd14bSAnoob Joseph tunnel->type = 300ccfd14bSAnoob Joseph RTE_SECURITY_IPSEC_TUNNEL_IPV4; 310ccfd14bSAnoob Joseph tunnel->ipv4.ttl = IPDEFTTL; 320ccfd14bSAnoob Joseph 330ccfd14bSAnoob Joseph memcpy((uint8_t *)&tunnel->ipv4.src_ip, 340ccfd14bSAnoob Joseph (uint8_t *)&sa->src.ip.ip4, 4); 350ccfd14bSAnoob Joseph 360ccfd14bSAnoob Joseph memcpy((uint8_t *)&tunnel->ipv4.dst_ip, 370ccfd14bSAnoob Joseph (uint8_t *)&sa->dst.ip.ip4, 4); 380d9b0263SAkhil Goyal } else if (IS_IP6_TUNNEL(sa->flags)) { 390d9b0263SAkhil Goyal tunnel->type = 400d9b0263SAkhil Goyal RTE_SECURITY_IPSEC_TUNNEL_IPV6; 410d9b0263SAkhil Goyal tunnel->ipv6.hlimit = IPDEFTTL; 420d9b0263SAkhil Goyal tunnel->ipv6.dscp = 0; 430d9b0263SAkhil Goyal tunnel->ipv6.flabel = 0; 440d9b0263SAkhil Goyal 450d9b0263SAkhil Goyal memcpy((uint8_t *)&tunnel->ipv6.src_addr, 460d9b0263SAkhil Goyal (uint8_t *)&sa->src.ip.ip6.ip6_b, 16); 470d9b0263SAkhil Goyal 480d9b0263SAkhil Goyal memcpy((uint8_t *)&tunnel->ipv6.dst_addr, 490d9b0263SAkhil Goyal (uint8_t *)&sa->dst.ip.ip6.ip6_b, 16); 500ccfd14bSAnoob Joseph } 510d9b0263SAkhil Goyal /* TODO support for Transport */ 520ccfd14bSAnoob Joseph } 530f56ca1aSHemant Agrawal ipsec->replay_win_sz = app_sa_prm.window_size; 540f56ca1aSHemant Agrawal ipsec->options.esn = app_sa_prm.enable_esn; 559a1cc8f1STejasree Kondoj ipsec->options.udp_encap = sa->udp_encap; 56*d8d51d4fSRahul Bhansali if (IS_HW_REASSEMBLY_EN(sa->flags)) 57*d8d51d4fSRahul Bhansali ipsec->options.ip_reassembly_en = 1; 580ccfd14bSAnoob Joseph } 590ccfd14bSAnoob Joseph 603e5f4625SKonstantin Ananyev int 61a8ade121SVolodymyr Fialko create_lookaside_session(struct ipsec_ctx *ipsec_ctx_lcore[], 626938fc92SVolodymyr Fialko struct socket_ctx *skt_ctx, const struct eventmode_conf *em_conf, 636938fc92SVolodymyr Fialko struct ipsec_sa *sa, struct rte_ipsec_session *ips) 64d299106eSSergio Gonzalez Monroy { 65a8ade121SVolodymyr Fialko uint16_t cdev_id = RTE_CRYPTO_MAX_DEVS; 666938fc92SVolodymyr Fialko enum rte_crypto_op_sess_type sess_type; 67c5aa9617SAkhil Goyal struct rte_cryptodev_info cdev_info; 686938fc92SVolodymyr Fialko enum rte_crypto_op_type op_type; 694e942500SSergio Gonzalez Monroy unsigned long cdev_id_qp = 0; 70a8ade121SVolodymyr Fialko struct ipsec_ctx *ipsec_ctx; 716938fc92SVolodymyr Fialko struct cdev_key key = { 0 }; 726938fc92SVolodymyr Fialko void *sess = NULL; 73a8ade121SVolodymyr Fialko uint32_t lcore_id; 74a8ade121SVolodymyr Fialko int32_t ret = 0; 75d299106eSSergio Gonzalez Monroy 76a8ade121SVolodymyr Fialko RTE_LCORE_FOREACH(lcore_id) { 77a8ade121SVolodymyr Fialko ipsec_ctx = ipsec_ctx_lcore[lcore_id]; 78d299106eSSergio Gonzalez Monroy 79a8ade121SVolodymyr Fialko /* Core is not bound to any cryptodev, skip it */ 80a8ade121SVolodymyr Fialko if (ipsec_ctx->cdev_map == NULL) 81a8ade121SVolodymyr Fialko continue; 82a8ade121SVolodymyr Fialko 83a8ade121SVolodymyr Fialko /* Looking for cryptodev, which can handle this SA */ 84a8ade121SVolodymyr Fialko key.lcore_id = (uint8_t)lcore_id; 85d299106eSSergio Gonzalez Monroy key.cipher_algo = (uint8_t)sa->cipher_algo; 86d299106eSSergio Gonzalez Monroy key.auth_algo = (uint8_t)sa->auth_algo; 87d00f3890SAviad Yehezkel key.aead_algo = (uint8_t)sa->aead_algo; 88d299106eSSergio Gonzalez Monroy 89d299106eSSergio Gonzalez Monroy ret = rte_hash_lookup_data(ipsec_ctx->cdev_map, &key, 90d299106eSSergio Gonzalez Monroy (void **)&cdev_id_qp); 91a8ade121SVolodymyr Fialko if (ret == -ENOENT) 92a8ade121SVolodymyr Fialko continue; 93d299106eSSergio Gonzalez Monroy if (ret < 0) { 94ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 95ec17993aSAkhil Goyal "No cryptodev: core %u, cipher_algo %u, " 96d00f3890SAviad Yehezkel "auth_algo %u, aead_algo %u\n", 97d00f3890SAviad Yehezkel key.lcore_id, 98d00f3890SAviad Yehezkel key.cipher_algo, 99d00f3890SAviad Yehezkel key.auth_algo, 100d00f3890SAviad Yehezkel key.aead_algo); 101a8ade121SVolodymyr Fialko return ret; 102d299106eSSergio Gonzalez Monroy } 103d299106eSSergio Gonzalez Monroy 104a8ade121SVolodymyr Fialko /* Verify that all cores are using same cryptodev for current 105a8ade121SVolodymyr Fialko * algorithm combination, required by SA. 106a8ade121SVolodymyr Fialko * Current cryptodev mapping process will map SA to the first 107a8ade121SVolodymyr Fialko * cryptodev that matches requirements, so it's a double check, 108a8ade121SVolodymyr Fialko * not an additional restriction. 109a8ade121SVolodymyr Fialko */ 110a8ade121SVolodymyr Fialko if (cdev_id == RTE_CRYPTO_MAX_DEVS) 111a8ade121SVolodymyr Fialko cdev_id = ipsec_ctx->tbl[cdev_id_qp].id; 112a8ade121SVolodymyr Fialko else if (cdev_id != ipsec_ctx->tbl[cdev_id_qp].id) { 113a8ade121SVolodymyr Fialko RTE_LOG(ERR, IPSEC, 114a8ade121SVolodymyr Fialko "SA mapping to multiple cryptodevs is " 115a8ade121SVolodymyr Fialko "not supported!"); 116a8ade121SVolodymyr Fialko return -EINVAL; 117a8ade121SVolodymyr Fialko } 118a8ade121SVolodymyr Fialko 119a8ade121SVolodymyr Fialko /* Store per core queue pair information */ 120a8ade121SVolodymyr Fialko sa->cqp[lcore_id] = &ipsec_ctx->tbl[cdev_id_qp]; 121a8ade121SVolodymyr Fialko } 122a8ade121SVolodymyr Fialko if (cdev_id == RTE_CRYPTO_MAX_DEVS) { 123a8ade121SVolodymyr Fialko RTE_LOG(WARNING, IPSEC, "No cores found to handle SA\n"); 124a8ade121SVolodymyr Fialko return 0; 125a8ade121SVolodymyr Fialko } 126a8ade121SVolodymyr Fialko 127a8ade121SVolodymyr Fialko RTE_LOG(DEBUG, IPSEC, "Create session for SA spi %u on cryptodev " 128a8ade121SVolodymyr Fialko "%u\n", sa->spi, cdev_id); 129d299106eSSergio Gonzalez Monroy 1305139d5d9SMarcin Smoczynski if (ips->type != RTE_SECURITY_ACTION_TYPE_NONE && 1315139d5d9SMarcin Smoczynski ips->type != RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) { 132ec17993aSAkhil Goyal struct rte_security_session_conf sess_conf = { 1334a67af84SMarcin Smoczynski .action_type = ips->type, 134ec17993aSAkhil Goyal .protocol = RTE_SECURITY_PROTOCOL_IPSEC, 135376ee1deSRadu Nicolau {.ipsec = { 136ec17993aSAkhil Goyal .spi = sa->spi, 137ec17993aSAkhil Goyal .salt = sa->salt, 138ec17993aSAkhil Goyal .options = { 0 }, 1390f56ca1aSHemant Agrawal .replay_win_sz = 0, 140ec17993aSAkhil Goyal .direction = sa->direction, 141ec17993aSAkhil Goyal .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, 142b1a3ac78SMariusz Drost .mode = (IS_TUNNEL(sa->flags)) ? 143ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_MODE_TUNNEL : 144ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, 145376ee1deSRadu Nicolau } }, 1460ccfd14bSAnoob Joseph .crypto_xform = sa->xforms, 1470ccfd14bSAnoob Joseph .userdata = NULL, 148ec17993aSAkhil Goyal 149ec17993aSAkhil Goyal }; 150ec17993aSAkhil Goyal 1514a67af84SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) { 152ec17993aSAkhil Goyal struct rte_security_ctx *ctx = (struct rte_security_ctx *) 153ec17993aSAkhil Goyal rte_cryptodev_get_sec_ctx( 154a8ade121SVolodymyr Fialko cdev_id); 155ec17993aSAkhil Goyal 1560ccfd14bSAnoob Joseph /* Set IPsec parameters in conf */ 1570ccfd14bSAnoob Joseph set_ipsec_conf(sa, &(sess_conf.ipsec)); 158ec17993aSAkhil Goyal 1594a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(ctx, 1603f3fc330SAkhil Goyal &sess_conf, skt_ctx->session_pool); 1614a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 162ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 163ec17993aSAkhil Goyal "SEC Session init failed: err: %d\n", ret); 164ec17993aSAkhil Goyal return -1; 165ec17993aSAkhil Goyal } 1668e814e18SVolodymyr Fialko ips->security.ctx = ctx; 1676938fc92SVolodymyr Fialko 1686938fc92SVolodymyr Fialko sess = ips->security.ses; 1696938fc92SVolodymyr Fialko op_type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 1706938fc92SVolodymyr Fialko sess_type = RTE_CRYPTO_OP_SECURITY_SESSION; 1713a690d5aSBernard Iremonger } else { 1723a690d5aSBernard Iremonger RTE_LOG(ERR, IPSEC, "Inline not supported\n"); 1733a690d5aSBernard Iremonger return -1; 1743a690d5aSBernard Iremonger } 1753a690d5aSBernard Iremonger } else { 1765139d5d9SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) { 1775139d5d9SMarcin Smoczynski struct rte_cryptodev_info info; 1785139d5d9SMarcin Smoczynski 1795139d5d9SMarcin Smoczynski rte_cryptodev_info_get(cdev_id, &info); 1805139d5d9SMarcin Smoczynski if (!(info.feature_flags & 1815139d5d9SMarcin Smoczynski RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO)) 1825139d5d9SMarcin Smoczynski return -ENOTSUP; 1835139d5d9SMarcin Smoczynski 1845139d5d9SMarcin Smoczynski } 1858e814e18SVolodymyr Fialko ips->crypto.dev_id = cdev_id; 186bdce2564SAkhil Goyal ips->crypto.ses = rte_cryptodev_sym_session_create(cdev_id, 187bdce2564SAkhil Goyal sa->xforms, skt_ctx->session_pool); 1883a690d5aSBernard Iremonger 1898e814e18SVolodymyr Fialko rte_cryptodev_info_get(cdev_id, &cdev_info); 1903a690d5aSBernard Iremonger } 1913a690d5aSBernard Iremonger 1926938fc92SVolodymyr Fialko /* Setup meta data required by event crypto adapter */ 1936938fc92SVolodymyr Fialko if (em_conf->enable_event_crypto_adapter && sess != NULL) { 1946938fc92SVolodymyr Fialko union rte_event_crypto_metadata m_data; 1956938fc92SVolodymyr Fialko const struct eventdev_params *eventdev_conf; 1966938fc92SVolodymyr Fialko 1976938fc92SVolodymyr Fialko eventdev_conf = &(em_conf->eventdev_config[0]); 1986938fc92SVolodymyr Fialko memset(&m_data, 0, sizeof(m_data)); 1996938fc92SVolodymyr Fialko 2006938fc92SVolodymyr Fialko /* Fill in response information */ 2016938fc92SVolodymyr Fialko m_data.response_info.sched_type = em_conf->ext_params.sched_type; 2026938fc92SVolodymyr Fialko m_data.response_info.op = RTE_EVENT_OP_NEW; 2036938fc92SVolodymyr Fialko m_data.response_info.queue_id = eventdev_conf->ev_cpt_queue_id; 2046938fc92SVolodymyr Fialko 2056938fc92SVolodymyr Fialko /* Fill in request information */ 2066938fc92SVolodymyr Fialko m_data.request_info.cdev_id = cdev_id; 2076938fc92SVolodymyr Fialko m_data.request_info.queue_pair_id = 0; 2086938fc92SVolodymyr Fialko 2096938fc92SVolodymyr Fialko /* Attach meta info to session */ 2106938fc92SVolodymyr Fialko rte_cryptodev_session_event_mdata_set(cdev_id, sess, op_type, 2116938fc92SVolodymyr Fialko sess_type, &m_data, sizeof(m_data)); 2126938fc92SVolodymyr Fialko } 2136938fc92SVolodymyr Fialko 2143a690d5aSBernard Iremonger return 0; 2153a690d5aSBernard Iremonger } 2163a690d5aSBernard Iremonger 2173a690d5aSBernard Iremonger int 2184a67af84SMarcin Smoczynski create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa, 2194a67af84SMarcin Smoczynski struct rte_ipsec_session *ips) 2203a690d5aSBernard Iremonger { 2213a690d5aSBernard Iremonger int32_t ret = 0; 2223a690d5aSBernard Iremonger struct rte_security_ctx *sec_ctx; 2233a690d5aSBernard Iremonger struct rte_security_session_conf sess_conf = { 2244a67af84SMarcin Smoczynski .action_type = ips->type, 2253a690d5aSBernard Iremonger .protocol = RTE_SECURITY_PROTOCOL_IPSEC, 2263a690d5aSBernard Iremonger {.ipsec = { 2273a690d5aSBernard Iremonger .spi = sa->spi, 2283a690d5aSBernard Iremonger .salt = sa->salt, 2293a690d5aSBernard Iremonger .options = { 0 }, 2300f56ca1aSHemant Agrawal .replay_win_sz = 0, 2313a690d5aSBernard Iremonger .direction = sa->direction, 2326019feadSRadu Nicolau .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP 2333a690d5aSBernard Iremonger } }, 2343a690d5aSBernard Iremonger .crypto_xform = sa->xforms, 2353a690d5aSBernard Iremonger .userdata = NULL, 2363a690d5aSBernard Iremonger }; 2373a690d5aSBernard Iremonger 2386019feadSRadu Nicolau if (IS_TRANSPORT(sa->flags)) { 2396019feadSRadu Nicolau sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT; 2406019feadSRadu Nicolau if (IS_IP4(sa->flags)) { 2416019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2426019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV4; 2436019feadSRadu Nicolau 2446019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr = 2456019feadSRadu Nicolau sa->src.ip.ip4; 2466019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr = 2476019feadSRadu Nicolau sa->dst.ip.ip4; 2486019feadSRadu Nicolau } else if (IS_IP6(sa->flags)) { 2496019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2506019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV6; 2516019feadSRadu Nicolau 2526019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr, 2536019feadSRadu Nicolau sa->src.ip.ip6.ip6_b, 16); 2546019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr, 2556019feadSRadu Nicolau sa->dst.ip.ip6.ip6_b, 16); 2566019feadSRadu Nicolau } 2576019feadSRadu Nicolau } else if (IS_TUNNEL(sa->flags)) { 2586019feadSRadu Nicolau sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL; 2596019feadSRadu Nicolau 2606019feadSRadu Nicolau if (IS_IP4(sa->flags)) { 2616019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2626019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV4; 2636019feadSRadu Nicolau 2646019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr = 2656019feadSRadu Nicolau sa->src.ip.ip4; 2666019feadSRadu Nicolau sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr = 2676019feadSRadu Nicolau sa->dst.ip.ip4; 2686019feadSRadu Nicolau } else if (IS_IP6(sa->flags)) { 2696019feadSRadu Nicolau sess_conf.ipsec.tunnel.type = 2706019feadSRadu Nicolau RTE_SECURITY_IPSEC_TUNNEL_IPV6; 2716019feadSRadu Nicolau 2726019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr, 2736019feadSRadu Nicolau sa->src.ip.ip6.ip6_b, 16); 2746019feadSRadu Nicolau memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr, 2756019feadSRadu Nicolau sa->dst.ip.ip6.ip6_b, 16); 2766019feadSRadu Nicolau } else { 2776019feadSRadu Nicolau RTE_LOG(ERR, IPSEC, "invalid tunnel type\n"); 2786019feadSRadu Nicolau return -1; 2796019feadSRadu Nicolau } 2806019feadSRadu Nicolau } 2816019feadSRadu Nicolau 2829ae86b4cSRadu Nicolau if (sa->udp_encap) { 2839ae86b4cSRadu Nicolau sess_conf.ipsec.options.udp_encap = 1; 2849ae86b4cSRadu Nicolau sess_conf.ipsec.udp.sport = htons(sa->udp.sport); 2859ae86b4cSRadu Nicolau sess_conf.ipsec.udp.dport = htons(sa->udp.dport); 2869ae86b4cSRadu Nicolau } 2879ae86b4cSRadu Nicolau 288560029d5SRadu Nicolau if (sa->esn > 0) { 289560029d5SRadu Nicolau sess_conf.ipsec.options.esn = 1; 290560029d5SRadu Nicolau sess_conf.ipsec.esn.value = sa->esn; 291560029d5SRadu Nicolau } 292560029d5SRadu Nicolau 293560029d5SRadu Nicolau 2943a690d5aSBernard Iremonger RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n", 2953a690d5aSBernard Iremonger sa->spi, sa->portid); 2963a690d5aSBernard Iremonger 2974a67af84SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { 298ec17993aSAkhil Goyal struct rte_flow_error err; 299ec17993aSAkhil Goyal const struct rte_security_capability *sec_cap; 300a4677f78SNélio Laranjeiro int ret = 0; 301ec17993aSAkhil Goyal 3023a690d5aSBernard Iremonger sec_ctx = (struct rte_security_ctx *) 3033a690d5aSBernard Iremonger rte_eth_dev_get_sec_ctx( 3043a690d5aSBernard Iremonger sa->portid); 3053a690d5aSBernard Iremonger if (sec_ctx == NULL) { 3063a690d5aSBernard Iremonger RTE_LOG(ERR, IPSEC, 3073a690d5aSBernard Iremonger " rte_eth_dev_get_sec_ctx failed\n"); 3083a690d5aSBernard Iremonger return -1; 3093a690d5aSBernard Iremonger } 3103a690d5aSBernard Iremonger 3114a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(sec_ctx, 3123f3fc330SAkhil Goyal &sess_conf, skt_ctx->session_pool); 3134a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 314ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 315ec17993aSAkhil Goyal "SEC Session init failed: err: %d\n", ret); 316ec17993aSAkhil Goyal return -1; 317ec17993aSAkhil Goyal } 318ec17993aSAkhil Goyal 3193a690d5aSBernard Iremonger sec_cap = rte_security_capabilities_get(sec_ctx); 320ec17993aSAkhil Goyal 321ec17993aSAkhil Goyal /* iterate until ESP tunnel*/ 3223a690d5aSBernard Iremonger while (sec_cap->action != RTE_SECURITY_ACTION_TYPE_NONE) { 3234a67af84SMarcin Smoczynski if (sec_cap->action == ips->type && 324ec17993aSAkhil Goyal sec_cap->protocol == 325ec17993aSAkhil Goyal RTE_SECURITY_PROTOCOL_IPSEC && 326ec17993aSAkhil Goyal sec_cap->ipsec.mode == 3273a690d5aSBernard Iremonger RTE_SECURITY_IPSEC_SA_MODE_TUNNEL && 328ec17993aSAkhil Goyal sec_cap->ipsec.direction == sa->direction) 329ec17993aSAkhil Goyal break; 330ec17993aSAkhil Goyal sec_cap++; 331ec17993aSAkhil Goyal } 332ec17993aSAkhil Goyal 333ec17993aSAkhil Goyal if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) { 334ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 335ec17993aSAkhil Goyal "No suitable security capability found\n"); 336ec17993aSAkhil Goyal return -1; 337ec17993aSAkhil Goyal } 338ec17993aSAkhil Goyal 3394a67af84SMarcin Smoczynski ips->security.ol_flags = sec_cap->ol_flags; 3404a67af84SMarcin Smoczynski ips->security.ctx = sec_ctx; 341ec17993aSAkhil Goyal sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 342ec17993aSAkhil Goyal 343b1a3ac78SMariusz Drost if (IS_IP6(sa->flags)) { 344b1a3ac78SMariusz Drost sa->pattern[1].mask = &rte_flow_item_ipv6_mask; 345b1a3ac78SMariusz Drost sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 346ec17993aSAkhil Goyal sa->pattern[1].spec = &sa->ipv6_spec; 347b1a3ac78SMariusz Drost 348ec17993aSAkhil Goyal memcpy(sa->ipv6_spec.hdr.dst_addr, 349ec17993aSAkhil Goyal sa->dst.ip.ip6.ip6_b, 16); 350ec17993aSAkhil Goyal memcpy(sa->ipv6_spec.hdr.src_addr, 351ec17993aSAkhil Goyal sa->src.ip.ip6.ip6_b, 16); 352b1a3ac78SMariusz Drost } else if (IS_IP4(sa->flags)) { 353b1a3ac78SMariusz Drost sa->pattern[1].mask = &rte_flow_item_ipv4_mask; 354b1a3ac78SMariusz Drost sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 355ec17993aSAkhil Goyal sa->pattern[1].spec = &sa->ipv4_spec; 356b1a3ac78SMariusz Drost 357ec17993aSAkhil Goyal sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4; 358ec17993aSAkhil Goyal sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4; 359ec17993aSAkhil Goyal } 360ec17993aSAkhil Goyal 3619ae86b4cSRadu Nicolau sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 3629ae86b4cSRadu Nicolau 3639ae86b4cSRadu Nicolau if (sa->udp_encap) { 3649ae86b4cSRadu Nicolau 3659ae86b4cSRadu Nicolau sa->udp_spec.hdr.dst_port = 3669ae86b4cSRadu Nicolau rte_cpu_to_be_16(sa->udp.dport); 3679ae86b4cSRadu Nicolau sa->udp_spec.hdr.src_port = 3689ae86b4cSRadu Nicolau rte_cpu_to_be_16(sa->udp.sport); 3699ae86b4cSRadu Nicolau 3709ae86b4cSRadu Nicolau sa->pattern[2].mask = &rte_flow_item_udp_mask; 3719ae86b4cSRadu Nicolau sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP; 3729ae86b4cSRadu Nicolau sa->pattern[2].spec = &sa->udp_spec; 3739ae86b4cSRadu Nicolau 3749ae86b4cSRadu Nicolau sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP; 3759ae86b4cSRadu Nicolau sa->pattern[3].spec = &sa->esp_spec; 3769ae86b4cSRadu Nicolau sa->pattern[3].mask = &rte_flow_item_esp_mask; 3779ae86b4cSRadu Nicolau 3789ae86b4cSRadu Nicolau sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END; 3799ae86b4cSRadu Nicolau } else { 380ec17993aSAkhil Goyal sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 381ec17993aSAkhil Goyal sa->pattern[2].spec = &sa->esp_spec; 382ec17993aSAkhil Goyal sa->pattern[2].mask = &rte_flow_item_esp_mask; 383ec17993aSAkhil Goyal 384ec17993aSAkhil Goyal sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 3859ae86b4cSRadu Nicolau } 386ec17993aSAkhil Goyal 387ec17993aSAkhil Goyal sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY; 3884a67af84SMarcin Smoczynski sa->action[0].conf = ips->security.ses; 389ec17993aSAkhil Goyal 390ec17993aSAkhil Goyal sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 391ec17993aSAkhil Goyal 392ec17993aSAkhil Goyal sa->attr.egress = (sa->direction == 393ec17993aSAkhil Goyal RTE_SECURITY_IPSEC_SA_DIR_EGRESS); 394a4cde424SNélio Laranjeiro sa->attr.ingress = (sa->direction == 395a4cde424SNélio Laranjeiro RTE_SECURITY_IPSEC_SA_DIR_INGRESS); 396a4677f78SNélio Laranjeiro if (sa->attr.ingress) { 3976019feadSRadu Nicolau uint8_t rss_key[64]; 398a4677f78SNélio Laranjeiro struct rte_eth_rss_conf rss_conf = { 399a4677f78SNélio Laranjeiro .rss_key = rss_key, 4006019feadSRadu Nicolau .rss_key_len = sizeof(rss_key), 401a4677f78SNélio Laranjeiro }; 4020109baf1SMarcin Zapolski struct rte_eth_dev_info dev_info; 403a4677f78SNélio Laranjeiro uint16_t queue[RTE_MAX_QUEUES_PER_PORT]; 40419b3bc47SAdrien Mazarguil struct rte_flow_action_rss action_rss; 405a4677f78SNélio Laranjeiro unsigned int i; 406a4677f78SNélio Laranjeiro unsigned int j; 407a4677f78SNélio Laranjeiro 408513f192bSAnkur Dwivedi /* Don't create flow if default flow is created */ 409513f192bSAnkur Dwivedi if (flow_info_tbl[sa->portid].rx_def_flow) 410513f192bSAnkur Dwivedi return 0; 411513f192bSAnkur Dwivedi 41203ad0e5cSIvan Ilchenko ret = rte_eth_dev_info_get(sa->portid, &dev_info); 41303ad0e5cSIvan Ilchenko if (ret != 0) { 41403ad0e5cSIvan Ilchenko RTE_LOG(ERR, IPSEC, 41503ad0e5cSIvan Ilchenko "Error during getting device (port %u) info: %s\n", 41603ad0e5cSIvan Ilchenko sa->portid, strerror(-ret)); 41703ad0e5cSIvan Ilchenko return ret; 41803ad0e5cSIvan Ilchenko } 41903ad0e5cSIvan Ilchenko 420a4677f78SNélio Laranjeiro sa->action[2].type = RTE_FLOW_ACTION_TYPE_END; 421a4677f78SNélio Laranjeiro /* Try RSS. */ 422a4677f78SNélio Laranjeiro sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS; 423a4677f78SNélio Laranjeiro sa->action[1].conf = &action_rss; 42423742f21SBernard Iremonger ret = rte_eth_dev_rss_hash_conf_get(sa->portid, 42523742f21SBernard Iremonger &rss_conf); 42623742f21SBernard Iremonger if (ret != 0) { 42723742f21SBernard Iremonger RTE_LOG(ERR, IPSEC, 42823742f21SBernard Iremonger "rte_eth_dev_rss_hash_conf_get:ret=%d\n", 42923742f21SBernard Iremonger ret); 43023742f21SBernard Iremonger return -1; 43123742f21SBernard Iremonger } 4323a690d5aSBernard Iremonger for (i = 0, j = 0; i < dev_info.nb_rx_queues; ++i) 43319b3bc47SAdrien Mazarguil queue[j++] = i; 4343a690d5aSBernard Iremonger 435ac8d22deSAdrien Mazarguil action_rss = (struct rte_flow_action_rss){ 436ac8d22deSAdrien Mazarguil .types = rss_conf.rss_hf, 437ac8d22deSAdrien Mazarguil .key_len = rss_conf.rss_key_len, 438ac8d22deSAdrien Mazarguil .queue_num = j, 439ac8d22deSAdrien Mazarguil .key = rss_key, 440ac8d22deSAdrien Mazarguil .queue = queue, 441ac8d22deSAdrien Mazarguil }; 442a4677f78SNélio Laranjeiro ret = rte_flow_validate(sa->portid, &sa->attr, 443a4677f78SNélio Laranjeiro sa->pattern, sa->action, 444a4677f78SNélio Laranjeiro &err); 445a4677f78SNélio Laranjeiro if (!ret) 446a4677f78SNélio Laranjeiro goto flow_create; 447a4677f78SNélio Laranjeiro /* Try Queue. */ 448a4677f78SNélio Laranjeiro sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE; 449a4677f78SNélio Laranjeiro sa->action[1].conf = 450a4677f78SNélio Laranjeiro &(struct rte_flow_action_queue){ 451a4677f78SNélio Laranjeiro .index = 0, 452a4677f78SNélio Laranjeiro }; 453a4677f78SNélio Laranjeiro ret = rte_flow_validate(sa->portid, &sa->attr, 454a4677f78SNélio Laranjeiro sa->pattern, sa->action, 455a4677f78SNélio Laranjeiro &err); 4566138c2daSRadu Nicolau /* Try End. */ 4576138c2daSRadu Nicolau sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 4586138c2daSRadu Nicolau sa->action[1].conf = NULL; 4596138c2daSRadu Nicolau ret = rte_flow_validate(sa->portid, &sa->attr, 4606138c2daSRadu Nicolau sa->pattern, sa->action, 4616138c2daSRadu Nicolau &err); 462a4677f78SNélio Laranjeiro if (ret) 463a4677f78SNélio Laranjeiro goto flow_create_failure; 464a90e6ce6SNélio Laranjeiro } else if (sa->attr.egress && 4654a67af84SMarcin Smoczynski (ips->security.ol_flags & 466a90e6ce6SNélio Laranjeiro RTE_SECURITY_TX_HW_TRAILER_OFFLOAD)) { 467a90e6ce6SNélio Laranjeiro sa->action[1].type = 468a90e6ce6SNélio Laranjeiro RTE_FLOW_ACTION_TYPE_PASSTHRU; 469a90e6ce6SNélio Laranjeiro sa->action[2].type = 470a90e6ce6SNélio Laranjeiro RTE_FLOW_ACTION_TYPE_END; 471a4677f78SNélio Laranjeiro } 472a4677f78SNélio Laranjeiro flow_create: 473ec17993aSAkhil Goyal sa->flow = rte_flow_create(sa->portid, 474ec17993aSAkhil Goyal &sa->attr, sa->pattern, sa->action, &err); 475ec17993aSAkhil Goyal if (sa->flow == NULL) { 476a4677f78SNélio Laranjeiro flow_create_failure: 477ec17993aSAkhil Goyal RTE_LOG(ERR, IPSEC, 478ec17993aSAkhil Goyal "Failed to create ipsec flow msg: %s\n", 479ec17993aSAkhil Goyal err.message); 480ec17993aSAkhil Goyal return -1; 481ec17993aSAkhil Goyal } 4824a67af84SMarcin Smoczynski } else if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) { 4830ccfd14bSAnoob Joseph const struct rte_security_capability *sec_cap; 4840ccfd14bSAnoob Joseph 4853a690d5aSBernard Iremonger sec_ctx = (struct rte_security_ctx *) 4863a690d5aSBernard Iremonger rte_eth_dev_get_sec_ctx(sa->portid); 4873a690d5aSBernard Iremonger 4883a690d5aSBernard Iremonger if (sec_ctx == NULL) { 4890ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 4900ccfd14bSAnoob Joseph "Ethernet device doesn't have security features registered\n"); 4910ccfd14bSAnoob Joseph return -1; 4920ccfd14bSAnoob Joseph } 4930ccfd14bSAnoob Joseph 4940ccfd14bSAnoob Joseph /* Set IPsec parameters in conf */ 4950ccfd14bSAnoob Joseph set_ipsec_conf(sa, &(sess_conf.ipsec)); 4960ccfd14bSAnoob Joseph 4970ccfd14bSAnoob Joseph /* Save SA as userdata for the security session. When 4980ccfd14bSAnoob Joseph * the packet is received, this userdata will be 4990ccfd14bSAnoob Joseph * retrieved using the metadata from the packet. 5000ccfd14bSAnoob Joseph * 501fa4de2ccSAnoob Joseph * The PMD is expected to set similar metadata for other 502fa4de2ccSAnoob Joseph * operations, like rte_eth_event, which are tied to 503fa4de2ccSAnoob Joseph * security session. In such cases, the userdata could 504fa4de2ccSAnoob Joseph * be obtained to uniquely identify the security 505fa4de2ccSAnoob Joseph * parameters denoted. 5060ccfd14bSAnoob Joseph */ 5070ccfd14bSAnoob Joseph 5080ccfd14bSAnoob Joseph sess_conf.userdata = (void *) sa; 5090ccfd14bSAnoob Joseph 5104a67af84SMarcin Smoczynski ips->security.ses = rte_security_session_create(sec_ctx, 5113f3fc330SAkhil Goyal &sess_conf, skt_ctx->session_pool); 5124a67af84SMarcin Smoczynski if (ips->security.ses == NULL) { 5130ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 5140ccfd14bSAnoob Joseph "SEC Session init failed: err: %d\n", ret); 5150ccfd14bSAnoob Joseph return -1; 5160ccfd14bSAnoob Joseph } 5170ccfd14bSAnoob Joseph 5183a690d5aSBernard Iremonger sec_cap = rte_security_capabilities_get(sec_ctx); 5190ccfd14bSAnoob Joseph if (sec_cap == NULL) { 5200ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 5210ccfd14bSAnoob Joseph "No capabilities registered\n"); 5220ccfd14bSAnoob Joseph return -1; 5230ccfd14bSAnoob Joseph } 5240ccfd14bSAnoob Joseph 5250ccfd14bSAnoob Joseph /* iterate until ESP tunnel*/ 5260ccfd14bSAnoob Joseph while (sec_cap->action != 5270ccfd14bSAnoob Joseph RTE_SECURITY_ACTION_TYPE_NONE) { 5284a67af84SMarcin Smoczynski if (sec_cap->action == ips->type && 5290ccfd14bSAnoob Joseph sec_cap->protocol == 5300ccfd14bSAnoob Joseph RTE_SECURITY_PROTOCOL_IPSEC && 5310ccfd14bSAnoob Joseph sec_cap->ipsec.mode == 532b1a3ac78SMariusz Drost sess_conf.ipsec.mode && 5330ccfd14bSAnoob Joseph sec_cap->ipsec.direction == sa->direction) 5340ccfd14bSAnoob Joseph break; 5350ccfd14bSAnoob Joseph sec_cap++; 5360ccfd14bSAnoob Joseph } 5370ccfd14bSAnoob Joseph 5380ccfd14bSAnoob Joseph if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) { 5390ccfd14bSAnoob Joseph RTE_LOG(ERR, IPSEC, 5400ccfd14bSAnoob Joseph "No suitable security capability found\n"); 5410ccfd14bSAnoob Joseph return -1; 5420ccfd14bSAnoob Joseph } 5430ccfd14bSAnoob Joseph 5444a67af84SMarcin Smoczynski ips->security.ol_flags = sec_cap->ol_flags; 5454a67af84SMarcin Smoczynski ips->security.ctx = sec_ctx; 546ec17993aSAkhil Goyal } 547d299106eSSergio Gonzalez Monroy 548d299106eSSergio Gonzalez Monroy return 0; 549d299106eSSergio Gonzalez Monroy } 550d299106eSSergio Gonzalez Monroy 5516738c0a9SPraveen Shetty int 5526738c0a9SPraveen Shetty create_ipsec_esp_flow(struct ipsec_sa *sa) 5536738c0a9SPraveen Shetty { 5546738c0a9SPraveen Shetty int ret = 0; 5550b512a92SVolodymyr Fialko struct rte_flow_error err = {}; 5566738c0a9SPraveen Shetty if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 5576738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, 5586738c0a9SPraveen Shetty "No Flow director rule for Egress traffic\n"); 5596738c0a9SPraveen Shetty return -1; 5606738c0a9SPraveen Shetty } 5616738c0a9SPraveen Shetty if (sa->flags == TRANSPORT) { 5626738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, 5636738c0a9SPraveen Shetty "No Flow director rule for transport mode\n"); 5646738c0a9SPraveen Shetty return -1; 5656738c0a9SPraveen Shetty } 5666738c0a9SPraveen Shetty sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; 5676738c0a9SPraveen Shetty sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; 5686738c0a9SPraveen Shetty sa->action[0].conf = &(struct rte_flow_action_queue) { 5696738c0a9SPraveen Shetty .index = sa->fdir_qid, 5706738c0a9SPraveen Shetty }; 5716738c0a9SPraveen Shetty sa->attr.egress = 0; 5726738c0a9SPraveen Shetty sa->attr.ingress = 1; 5736738c0a9SPraveen Shetty if (IS_IP6(sa->flags)) { 5746738c0a9SPraveen Shetty sa->pattern[1].mask = &rte_flow_item_ipv6_mask; 5756738c0a9SPraveen Shetty sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; 5766738c0a9SPraveen Shetty sa->pattern[1].spec = &sa->ipv6_spec; 5776738c0a9SPraveen Shetty memcpy(sa->ipv6_spec.hdr.dst_addr, 5786738c0a9SPraveen Shetty sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b)); 5796738c0a9SPraveen Shetty memcpy(sa->ipv6_spec.hdr.src_addr, 5806738c0a9SPraveen Shetty sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b)); 5816738c0a9SPraveen Shetty sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 5826738c0a9SPraveen Shetty sa->pattern[2].spec = &sa->esp_spec; 5836738c0a9SPraveen Shetty sa->pattern[2].mask = &rte_flow_item_esp_mask; 5846738c0a9SPraveen Shetty sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 5856738c0a9SPraveen Shetty sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 5866738c0a9SPraveen Shetty } else if (IS_IP4(sa->flags)) { 5876738c0a9SPraveen Shetty sa->pattern[1].mask = &rte_flow_item_ipv4_mask; 5886738c0a9SPraveen Shetty sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; 5896738c0a9SPraveen Shetty sa->pattern[1].spec = &sa->ipv4_spec; 5906738c0a9SPraveen Shetty sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4; 5916738c0a9SPraveen Shetty sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4; 5926738c0a9SPraveen Shetty sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP; 5936738c0a9SPraveen Shetty sa->pattern[2].spec = &sa->esp_spec; 5946738c0a9SPraveen Shetty sa->pattern[2].mask = &rte_flow_item_esp_mask; 5956738c0a9SPraveen Shetty sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi); 5966738c0a9SPraveen Shetty sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END; 5976738c0a9SPraveen Shetty } 5986738c0a9SPraveen Shetty sa->action[1].type = RTE_FLOW_ACTION_TYPE_END; 5996738c0a9SPraveen Shetty 6006738c0a9SPraveen Shetty ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action, 6016738c0a9SPraveen Shetty &err); 6026738c0a9SPraveen Shetty if (ret < 0) { 6036738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message); 6046738c0a9SPraveen Shetty return ret; 6056738c0a9SPraveen Shetty } 6066738c0a9SPraveen Shetty 6076738c0a9SPraveen Shetty sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern, 6086738c0a9SPraveen Shetty sa->action, &err); 6096738c0a9SPraveen Shetty if (!sa->flow) { 6106738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message); 6116738c0a9SPraveen Shetty return -1; 6126738c0a9SPraveen Shetty } 6136738c0a9SPraveen Shetty 6146738c0a9SPraveen Shetty return 0; 6156738c0a9SPraveen Shetty } 6166738c0a9SPraveen Shetty 617d87152e7SKonstantin Ananyev /* 618d87152e7SKonstantin Ananyev * queue crypto-ops into PMD queue. 619d87152e7SKonstantin Ananyev */ 620d87152e7SKonstantin Ananyev void 621d87152e7SKonstantin Ananyev enqueue_cop_burst(struct cdev_qp *cqp) 622d299106eSSergio Gonzalez Monroy { 623d87152e7SKonstantin Ananyev uint32_t i, len, ret; 624d299106eSSergio Gonzalez Monroy 625d87152e7SKonstantin Ananyev len = cqp->len; 626d87152e7SKonstantin Ananyev ret = rte_cryptodev_enqueue_burst(cqp->id, cqp->qp, cqp->buf, len); 627d87152e7SKonstantin Ananyev if (ret < len) { 6285d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, IPSEC, "Cryptodev %u queue %u:" 629d299106eSSergio Gonzalez Monroy " enqueued %u crypto ops out of %u\n", 630d87152e7SKonstantin Ananyev cqp->id, cqp->qp, ret, len); 631d87152e7SKonstantin Ananyev /* drop packets that we fail to enqueue */ 632d87152e7SKonstantin Ananyev for (i = ret; i < len; i++) 6331329602bSAnoob Joseph free_pkts(&cqp->buf[i]->sym->m_src, 1); 634d299106eSSergio Gonzalez Monroy } 635d299106eSSergio Gonzalez Monroy cqp->in_flight += ret; 636d299106eSSergio Gonzalez Monroy cqp->len = 0; 637d299106eSSergio Gonzalez Monroy } 638d87152e7SKonstantin Ananyev 639d87152e7SKonstantin Ananyev static inline void 640d87152e7SKonstantin Ananyev enqueue_cop(struct cdev_qp *cqp, struct rte_crypto_op *cop) 641d87152e7SKonstantin Ananyev { 642d87152e7SKonstantin Ananyev cqp->buf[cqp->len++] = cop; 643d87152e7SKonstantin Ananyev 644d87152e7SKonstantin Ananyev if (cqp->len == MAX_PKT_BURST) 645d87152e7SKonstantin Ananyev enqueue_cop_burst(cqp); 646d299106eSSergio Gonzalez Monroy } 647d299106eSSergio Gonzalez Monroy 648c64278c0SSergio Gonzalez Monroy static inline void 649c64278c0SSergio Gonzalez Monroy ipsec_enqueue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 650ba66534fSMarcin Smoczynski struct rte_mbuf *pkts[], void *sas[], 651c64278c0SSergio Gonzalez Monroy uint16_t nb_pkts) 652d299106eSSergio Gonzalez Monroy { 653906257e9SSergio Gonzalez Monroy int32_t ret = 0, i; 654d299106eSSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 655ec17993aSAkhil Goyal struct rte_crypto_sym_op *sym_cop; 656d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa; 6574a67af84SMarcin Smoczynski struct rte_ipsec_session *ips; 658d299106eSSergio Gonzalez Monroy 659d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_pkts; i++) { 66085f84767SSergio Gonzalez Monroy if (unlikely(sas[i] == NULL)) { 6611329602bSAnoob Joseph free_pkts(&pkts[i], 1); 66285f84767SSergio Gonzalez Monroy continue; 66385f84767SSergio Gonzalez Monroy } 66485f84767SSergio Gonzalez Monroy 665d299106eSSergio Gonzalez Monroy rte_prefetch0(sas[i]); 666d299106eSSergio Gonzalez Monroy rte_prefetch0(pkts[i]); 667d299106eSSergio Gonzalez Monroy 668d299106eSSergio Gonzalez Monroy priv = get_priv(pkts[i]); 669ba66534fSMarcin Smoczynski sa = ipsec_mask_saptr(sas[i]); 670d299106eSSergio Gonzalez Monroy priv->sa = sa; 671ba66534fSMarcin Smoczynski ips = ipsec_get_primary_session(sa); 672d299106eSSergio Gonzalez Monroy 6734a67af84SMarcin Smoczynski switch (ips->type) { 674ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 675ec17993aSAkhil Goyal priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 676ec17993aSAkhil Goyal priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 677ec17993aSAkhil Goyal 678ec17993aSAkhil Goyal rte_prefetch0(&priv->sym_cop); 679ec17993aSAkhil Goyal 680a8ade121SVolodymyr Fialko if (unlikely(ips->security.ses == NULL)) { 6811329602bSAnoob Joseph free_pkts(&pkts[i], 1); 682ec17993aSAkhil Goyal continue; 683ec17993aSAkhil Goyal } 684ec17993aSAkhil Goyal 6859a1cc8f1STejasree Kondoj if (unlikely((pkts[i]->packet_type & 6869a1cc8f1STejasree Kondoj (RTE_PTYPE_TUNNEL_MASK | 6879a1cc8f1STejasree Kondoj RTE_PTYPE_L4_MASK)) == 6889a1cc8f1STejasree Kondoj MBUF_PTYPE_TUNNEL_ESP_IN_UDP && 6899a1cc8f1STejasree Kondoj sa->udp_encap != 1)) { 6909a1cc8f1STejasree Kondoj free_pkts(&pkts[i], 1); 6919a1cc8f1STejasree Kondoj continue; 6929a1cc8f1STejasree Kondoj } 6939a1cc8f1STejasree Kondoj 694ec17993aSAkhil Goyal sym_cop = get_sym_cop(&priv->cop); 695ec17993aSAkhil Goyal sym_cop->m_src = pkts[i]; 696ec17993aSAkhil Goyal 697ec17993aSAkhil Goyal rte_security_attach_session(&priv->cop, 6984a67af84SMarcin Smoczynski ips->security.ses); 699ec17993aSAkhil Goyal break; 7005139d5d9SMarcin Smoczynski 7015139d5d9SMarcin Smoczynski case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 7025139d5d9SMarcin Smoczynski RTE_LOG(ERR, IPSEC, "CPU crypto is not supported by the" 7035139d5d9SMarcin Smoczynski " legacy mode."); 7041329602bSAnoob Joseph free_pkts(&pkts[i], 1); 7055139d5d9SMarcin Smoczynski continue; 7065139d5d9SMarcin Smoczynski 707ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_NONE: 708ec17993aSAkhil Goyal 709d299106eSSergio Gonzalez Monroy priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 710a60c05b5SSergio Gonzalez Monroy priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 711d299106eSSergio Gonzalez Monroy 712d299106eSSergio Gonzalez Monroy rte_prefetch0(&priv->sym_cop); 713d299106eSSergio Gonzalez Monroy 714a8ade121SVolodymyr Fialko if (unlikely(ips->crypto.ses == NULL)) { 7151329602bSAnoob Joseph free_pkts(&pkts[i], 1); 716d299106eSSergio Gonzalez Monroy continue; 717d299106eSSergio Gonzalez Monroy } 718d299106eSSergio Gonzalez Monroy 719d299106eSSergio Gonzalez Monroy rte_crypto_op_attach_sym_session(&priv->cop, 7204a67af84SMarcin Smoczynski ips->crypto.ses); 721d299106eSSergio Gonzalez Monroy 722c64278c0SSergio Gonzalez Monroy ret = xform_func(pkts[i], sa, &priv->cop); 723d299106eSSergio Gonzalez Monroy if (unlikely(ret)) { 7241329602bSAnoob Joseph free_pkts(&pkts[i], 1); 725d299106eSSergio Gonzalez Monroy continue; 726d299106eSSergio Gonzalez Monroy } 727ec17993aSAkhil Goyal break; 728ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 7294a67af84SMarcin Smoczynski RTE_ASSERT(ips->security.ses != NULL); 7303da37f68SRadu Nicolau ipsec_ctx->ol_pkts[ipsec_ctx->ol_pkts_cnt++] = pkts[i]; 7314a67af84SMarcin Smoczynski if (ips->security.ol_flags & 7324a67af84SMarcin Smoczynski RTE_SECURITY_TX_OLOAD_NEED_MDATA) 7330ccfd14bSAnoob Joseph rte_security_set_pkt_metadata( 7344a67af84SMarcin Smoczynski ips->security.ctx, ips->security.ses, 7354a67af84SMarcin Smoczynski pkts[i], NULL); 7360ccfd14bSAnoob Joseph continue; 737ec17993aSAkhil Goyal case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 7384a67af84SMarcin Smoczynski RTE_ASSERT(ips->security.ses != NULL); 739ec17993aSAkhil Goyal priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; 740ec17993aSAkhil Goyal priv->cop.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; 741ec17993aSAkhil Goyal 742ec17993aSAkhil Goyal rte_prefetch0(&priv->sym_cop); 743ec17993aSAkhil Goyal rte_security_attach_session(&priv->cop, 7444a67af84SMarcin Smoczynski ips->security.ses); 745ec17993aSAkhil Goyal 746ec17993aSAkhil Goyal ret = xform_func(pkts[i], sa, &priv->cop); 747ec17993aSAkhil Goyal if (unlikely(ret)) { 7481329602bSAnoob Joseph free_pkts(&pkts[i], 1); 749ec17993aSAkhil Goyal continue; 750ec17993aSAkhil Goyal } 751ec17993aSAkhil Goyal 7523da37f68SRadu Nicolau ipsec_ctx->ol_pkts[ipsec_ctx->ol_pkts_cnt++] = pkts[i]; 7534a67af84SMarcin Smoczynski if (ips->security.ol_flags & 7544a67af84SMarcin Smoczynski RTE_SECURITY_TX_OLOAD_NEED_MDATA) 755ec17993aSAkhil Goyal rte_security_set_pkt_metadata( 7564a67af84SMarcin Smoczynski ips->security.ctx, ips->security.ses, 7574a67af84SMarcin Smoczynski pkts[i], NULL); 758ec17993aSAkhil Goyal continue; 759ec17993aSAkhil Goyal } 760d299106eSSergio Gonzalez Monroy 761a8ade121SVolodymyr Fialko enqueue_cop(sa->cqp[ipsec_ctx->lcore_id], &priv->cop); 762d299106eSSergio Gonzalez Monroy } 763c64278c0SSergio Gonzalez Monroy } 764d299106eSSergio Gonzalez Monroy 765d87152e7SKonstantin Ananyev static inline int32_t 766d87152e7SKonstantin Ananyev ipsec_inline_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 767d87152e7SKonstantin Ananyev struct rte_mbuf *pkts[], uint16_t max_pkts) 768d87152e7SKonstantin Ananyev { 769d87152e7SKonstantin Ananyev int32_t nb_pkts, ret; 770d87152e7SKonstantin Ananyev struct ipsec_mbuf_metadata *priv; 771d87152e7SKonstantin Ananyev struct ipsec_sa *sa; 772d87152e7SKonstantin Ananyev struct rte_mbuf *pkt; 773d87152e7SKonstantin Ananyev 774d87152e7SKonstantin Ananyev nb_pkts = 0; 775d87152e7SKonstantin Ananyev while (ipsec_ctx->ol_pkts_cnt > 0 && nb_pkts < max_pkts) { 776d87152e7SKonstantin Ananyev pkt = ipsec_ctx->ol_pkts[--ipsec_ctx->ol_pkts_cnt]; 777d87152e7SKonstantin Ananyev rte_prefetch0(pkt); 778d87152e7SKonstantin Ananyev priv = get_priv(pkt); 779d87152e7SKonstantin Ananyev sa = priv->sa; 780d87152e7SKonstantin Ananyev ret = xform_func(pkt, sa, &priv->cop); 781d87152e7SKonstantin Ananyev if (unlikely(ret)) { 7821329602bSAnoob Joseph free_pkts(&pkt, 1); 783d87152e7SKonstantin Ananyev continue; 784d87152e7SKonstantin Ananyev } 785d87152e7SKonstantin Ananyev pkts[nb_pkts++] = pkt; 786d87152e7SKonstantin Ananyev } 787d87152e7SKonstantin Ananyev 788d87152e7SKonstantin Ananyev return nb_pkts; 789d87152e7SKonstantin Ananyev } 790d87152e7SKonstantin Ananyev 791c64278c0SSergio Gonzalez Monroy static inline int 792c64278c0SSergio Gonzalez Monroy ipsec_dequeue(ipsec_xform_fn xform_func, struct ipsec_ctx *ipsec_ctx, 793c64278c0SSergio Gonzalez Monroy struct rte_mbuf *pkts[], uint16_t max_pkts) 794c64278c0SSergio Gonzalez Monroy { 795906257e9SSergio Gonzalez Monroy int32_t nb_pkts = 0, ret = 0, i, j, nb_cops; 796c64278c0SSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 797c64278c0SSergio Gonzalez Monroy struct rte_crypto_op *cops[max_pkts]; 798c64278c0SSergio Gonzalez Monroy struct ipsec_sa *sa; 799c64278c0SSergio Gonzalez Monroy struct rte_mbuf *pkt; 800c64278c0SSergio Gonzalez Monroy 801833e36b8SRadu Nicolau for (i = 0; i < ipsec_ctx->nb_qps && nb_pkts < max_pkts; i++) { 802d299106eSSergio Gonzalez Monroy struct cdev_qp *cqp; 803833e36b8SRadu Nicolau 804833e36b8SRadu Nicolau cqp = &ipsec_ctx->tbl[ipsec_ctx->last_qp++]; 805833e36b8SRadu Nicolau if (ipsec_ctx->last_qp == ipsec_ctx->nb_qps) 806833e36b8SRadu Nicolau ipsec_ctx->last_qp %= ipsec_ctx->nb_qps; 807d299106eSSergio Gonzalez Monroy 808833e36b8SRadu Nicolau if (cqp->in_flight == 0) 809d299106eSSergio Gonzalez Monroy continue; 810d299106eSSergio Gonzalez Monroy 811d299106eSSergio Gonzalez Monroy nb_cops = rte_cryptodev_dequeue_burst(cqp->id, cqp->qp, 812d299106eSSergio Gonzalez Monroy cops, max_pkts - nb_pkts); 813d299106eSSergio Gonzalez Monroy 814d299106eSSergio Gonzalez Monroy cqp->in_flight -= nb_cops; 815d299106eSSergio Gonzalez Monroy 816d299106eSSergio Gonzalez Monroy for (j = 0; j < nb_cops; j++) { 817d299106eSSergio Gonzalez Monroy pkt = cops[j]->sym->m_src; 818d299106eSSergio Gonzalez Monroy rte_prefetch0(pkt); 819d299106eSSergio Gonzalez Monroy 820d299106eSSergio Gonzalez Monroy priv = get_priv(pkt); 821d299106eSSergio Gonzalez Monroy sa = priv->sa; 822d299106eSSergio Gonzalez Monroy 82350705e8eSThomas Monjalon RTE_ASSERT(sa != NULL); 824d299106eSSergio Gonzalez Monroy 8254a67af84SMarcin Smoczynski if (ipsec_get_action_type(sa) == 8264a67af84SMarcin Smoczynski RTE_SECURITY_ACTION_TYPE_NONE) { 827c64278c0SSergio Gonzalez Monroy ret = xform_func(pkt, sa, cops[j]); 828ec17993aSAkhil Goyal if (unlikely(ret)) { 8291329602bSAnoob Joseph free_pkts(&pkt, 1); 830ec17993aSAkhil Goyal continue; 831ec17993aSAkhil Goyal } 8324a67af84SMarcin Smoczynski } else if (ipsec_get_action_type(sa) == 83374ac7558SMichael Shamis RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) { 83474ac7558SMichael Shamis if (cops[j]->status) { 8351329602bSAnoob Joseph free_pkts(&pkt, 1); 83674ac7558SMichael Shamis continue; 83774ac7558SMichael Shamis } 838ec17993aSAkhil Goyal } 839d299106eSSergio Gonzalez Monroy pkts[nb_pkts++] = pkt; 840d299106eSSergio Gonzalez Monroy } 841d299106eSSergio Gonzalez Monroy } 842d299106eSSergio Gonzalez Monroy 843d299106eSSergio Gonzalez Monroy /* return packets */ 844d299106eSSergio Gonzalez Monroy return nb_pkts; 845d299106eSSergio Gonzalez Monroy } 846d299106eSSergio Gonzalez Monroy 847d299106eSSergio Gonzalez Monroy uint16_t 848d299106eSSergio Gonzalez Monroy ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 849d299106eSSergio Gonzalez Monroy uint16_t nb_pkts, uint16_t len) 850d299106eSSergio Gonzalez Monroy { 851ba66534fSMarcin Smoczynski void *sas[nb_pkts]; 852d299106eSSergio Gonzalez Monroy 853d299106eSSergio Gonzalez Monroy inbound_sa_lookup(ctx->sa_ctx, pkts, sas, nb_pkts); 854d299106eSSergio Gonzalez Monroy 855c64278c0SSergio Gonzalez Monroy ipsec_enqueue(esp_inbound, ctx, pkts, sas, nb_pkts); 856c64278c0SSergio Gonzalez Monroy 857d87152e7SKonstantin Ananyev return ipsec_inline_dequeue(esp_inbound_post, ctx, pkts, len); 858d87152e7SKonstantin Ananyev } 859d87152e7SKonstantin Ananyev 860d87152e7SKonstantin Ananyev uint16_t 861d87152e7SKonstantin Ananyev ipsec_inbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 862d87152e7SKonstantin Ananyev uint16_t len) 863d87152e7SKonstantin Ananyev { 864c64278c0SSergio Gonzalez Monroy return ipsec_dequeue(esp_inbound_post, ctx, pkts, len); 865d299106eSSergio Gonzalez Monroy } 866d299106eSSergio Gonzalez Monroy 867d299106eSSergio Gonzalez Monroy uint16_t 868d299106eSSergio Gonzalez Monroy ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 869d299106eSSergio Gonzalez Monroy uint32_t sa_idx[], uint16_t nb_pkts, uint16_t len) 870d299106eSSergio Gonzalez Monroy { 871ba66534fSMarcin Smoczynski void *sas[nb_pkts]; 872d299106eSSergio Gonzalez Monroy 873d299106eSSergio Gonzalez Monroy outbound_sa_lookup(ctx->sa_ctx, sa_idx, sas, nb_pkts); 874d299106eSSergio Gonzalez Monroy 875c64278c0SSergio Gonzalez Monroy ipsec_enqueue(esp_outbound, ctx, pkts, sas, nb_pkts); 876c64278c0SSergio Gonzalez Monroy 877d87152e7SKonstantin Ananyev return ipsec_inline_dequeue(esp_outbound_post, ctx, pkts, len); 878d87152e7SKonstantin Ananyev } 879d87152e7SKonstantin Ananyev 880d87152e7SKonstantin Ananyev uint16_t 881d87152e7SKonstantin Ananyev ipsec_outbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], 882d87152e7SKonstantin Ananyev uint16_t len) 883d87152e7SKonstantin Ananyev { 884c64278c0SSergio Gonzalez Monroy return ipsec_dequeue(esp_outbound_post, ctx, pkts, len); 885d299106eSSergio Gonzalez Monroy } 886