14965dda0SLukasz Bartosik /* SPDX-License-Identifier: BSD-3-Clause 24965dda0SLukasz Bartosik * Copyright(c) 2010-2016 Intel Corporation 34965dda0SLukasz Bartosik * Copyright (C) 2020 Marvell International Ltd. 44965dda0SLukasz Bartosik */ 59ad50c29SLukasz Bartosik #include <rte_acl.h> 66938fc92SVolodymyr Fialko #include <rte_event_crypto_adapter.h> 74965dda0SLukasz Bartosik #include <rte_event_eth_tx_adapter.h> 89ad50c29SLukasz Bartosik #include <rte_lpm.h> 99ad50c29SLukasz Bartosik #include <rte_lpm6.h> 104965dda0SLukasz Bartosik 114965dda0SLukasz Bartosik #include "event_helper.h" 124965dda0SLukasz Bartosik #include "ipsec.h" 134965dda0SLukasz Bartosik #include "ipsec-secgw.h" 149ad50c29SLukasz Bartosik #include "ipsec_worker.h" 156938fc92SVolodymyr Fialko #include "sad.h" 169ad50c29SLukasz Bartosik 176eb3ba03SRahul Bhansali #if defined(__ARM_NEON) 186eb3ba03SRahul Bhansali #include "ipsec_lpm_neon.h" 196eb3ba03SRahul Bhansali #endif 206eb3ba03SRahul Bhansali 21ea28ab88SNithin Dabilpuram struct port_drv_mode_data { 222973dbf9SAkhil Goyal void *sess; 2379bdb787SAkhil Goyal void *ctx; 24ea28ab88SNithin Dabilpuram }; 25ea28ab88SNithin Dabilpuram 260d76e22dSNithin Dabilpuram typedef void (*ipsec_worker_fn_t)(void); 270d76e22dSNithin Dabilpuram 28d8d51d4fSRahul Bhansali int ip_reassembly_dynfield_offset = -1; 29d8d51d4fSRahul Bhansali uint64_t ip_reassembly_dynflag; 30d8d51d4fSRahul Bhansali 319ad50c29SLukasz Bartosik static inline enum pkt_type 329ad50c29SLukasz Bartosik process_ipsec_get_pkt_type(struct rte_mbuf *pkt, uint8_t **nlp) 339ad50c29SLukasz Bartosik { 349ad50c29SLukasz Bartosik struct rte_ether_hdr *eth; 352e7abb8bSNithin Dabilpuram uint32_t ptype = pkt->packet_type; 369ad50c29SLukasz Bartosik 379ad50c29SLukasz Bartosik eth = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 382e7abb8bSNithin Dabilpuram rte_prefetch0(eth); 392e7abb8bSNithin Dabilpuram 402e7abb8bSNithin Dabilpuram if (RTE_ETH_IS_IPV4_HDR(ptype)) { 419ad50c29SLukasz Bartosik *nlp = RTE_PTR_ADD(eth, RTE_ETHER_HDR_LEN + 429ad50c29SLukasz Bartosik offsetof(struct ip, ip_p)); 432e7abb8bSNithin Dabilpuram if ((ptype & RTE_PTYPE_TUNNEL_MASK) == RTE_PTYPE_TUNNEL_ESP) 449ad50c29SLukasz Bartosik return PKT_TYPE_IPSEC_IPV4; 459ad50c29SLukasz Bartosik else 469ad50c29SLukasz Bartosik return PKT_TYPE_PLAIN_IPV4; 472e7abb8bSNithin Dabilpuram } else if (RTE_ETH_IS_IPV6_HDR(ptype)) { 489ad50c29SLukasz Bartosik *nlp = RTE_PTR_ADD(eth, RTE_ETHER_HDR_LEN + 499ad50c29SLukasz Bartosik offsetof(struct ip6_hdr, ip6_nxt)); 502e7abb8bSNithin Dabilpuram if ((ptype & RTE_PTYPE_TUNNEL_MASK) == RTE_PTYPE_TUNNEL_ESP) 519ad50c29SLukasz Bartosik return PKT_TYPE_IPSEC_IPV6; 529ad50c29SLukasz Bartosik else 539ad50c29SLukasz Bartosik return PKT_TYPE_PLAIN_IPV6; 549ad50c29SLukasz Bartosik } 559ad50c29SLukasz Bartosik 569ad50c29SLukasz Bartosik /* Unknown/Unsupported type */ 579ad50c29SLukasz Bartosik return PKT_TYPE_INVALID; 589ad50c29SLukasz Bartosik } 599ad50c29SLukasz Bartosik 609ad50c29SLukasz Bartosik static inline void 6158e2cf4cSNithin Dabilpuram update_mac_addrs(struct rte_ether_hdr *ethhdr, uint16_t portid) 629ad50c29SLukasz Bartosik { 6304d43857SDmitry Kozlyuk memcpy(ðhdr->src_addr, ðaddr_tbl[portid].src, RTE_ETHER_ADDR_LEN); 6404d43857SDmitry Kozlyuk memcpy(ðhdr->dst_addr, ðaddr_tbl[portid].dst, RTE_ETHER_ADDR_LEN); 659ad50c29SLukasz Bartosik } 664965dda0SLukasz Bartosik 674965dda0SLukasz Bartosik static inline void 684965dda0SLukasz Bartosik ipsec_event_pre_forward(struct rte_mbuf *m, unsigned int port_id) 694965dda0SLukasz Bartosik { 704965dda0SLukasz Bartosik /* Save the destination port in the mbuf */ 714965dda0SLukasz Bartosik m->port = port_id; 724965dda0SLukasz Bartosik 734965dda0SLukasz Bartosik /* Save eth queue for Tx */ 744965dda0SLukasz Bartosik rte_event_eth_tx_adapter_txq_set(m, 0); 754965dda0SLukasz Bartosik } 764965dda0SLukasz Bartosik 774965dda0SLukasz Bartosik static inline void 7886738ebeSSrujana Challa ev_vector_attr_init(struct rte_event_vector *vec) 7986738ebeSSrujana Challa { 8086738ebeSSrujana Challa vec->attr_valid = 1; 8186738ebeSSrujana Challa vec->port = 0xFFFF; 8286738ebeSSrujana Challa vec->queue = 0; 8386738ebeSSrujana Challa } 8486738ebeSSrujana Challa 8586738ebeSSrujana Challa static inline void 8686738ebeSSrujana Challa ev_vector_attr_update(struct rte_event_vector *vec, struct rte_mbuf *pkt) 8786738ebeSSrujana Challa { 8886738ebeSSrujana Challa if (vec->port == 0xFFFF) { 8986738ebeSSrujana Challa vec->port = pkt->port; 9086738ebeSSrujana Challa return; 9186738ebeSSrujana Challa } 9286738ebeSSrujana Challa if (vec->attr_valid && (vec->port != pkt->port)) 9386738ebeSSrujana Challa vec->attr_valid = 0; 9486738ebeSSrujana Challa } 9586738ebeSSrujana Challa 9686738ebeSSrujana Challa static inline void 974965dda0SLukasz Bartosik prepare_out_sessions_tbl(struct sa_ctx *sa_out, 98ea28ab88SNithin Dabilpuram struct port_drv_mode_data *data, 99ea28ab88SNithin Dabilpuram uint16_t size) 1004965dda0SLukasz Bartosik { 1014965dda0SLukasz Bartosik struct rte_ipsec_session *pri_sess; 1024965dda0SLukasz Bartosik struct ipsec_sa *sa; 1034965dda0SLukasz Bartosik uint32_t i; 1044965dda0SLukasz Bartosik 1054965dda0SLukasz Bartosik if (!sa_out) 1064965dda0SLukasz Bartosik return; 1074965dda0SLukasz Bartosik 1084965dda0SLukasz Bartosik for (i = 0; i < sa_out->nb_sa; i++) { 1094965dda0SLukasz Bartosik 1104965dda0SLukasz Bartosik sa = &sa_out->sa[i]; 1114965dda0SLukasz Bartosik if (!sa) 1124965dda0SLukasz Bartosik continue; 1134965dda0SLukasz Bartosik 1144965dda0SLukasz Bartosik pri_sess = ipsec_get_primary_session(sa); 1154965dda0SLukasz Bartosik if (!pri_sess) 1164965dda0SLukasz Bartosik continue; 1174965dda0SLukasz Bartosik 1184965dda0SLukasz Bartosik if (pri_sess->type != 1194965dda0SLukasz Bartosik RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) { 1204965dda0SLukasz Bartosik 1214965dda0SLukasz Bartosik RTE_LOG(ERR, IPSEC, "Invalid session type %d\n", 1224965dda0SLukasz Bartosik pri_sess->type); 1234965dda0SLukasz Bartosik continue; 1244965dda0SLukasz Bartosik } 1254965dda0SLukasz Bartosik 1264965dda0SLukasz Bartosik if (sa->portid >= size) { 1274965dda0SLukasz Bartosik RTE_LOG(ERR, IPSEC, 1284965dda0SLukasz Bartosik "Port id >= than table size %d, %d\n", 1294965dda0SLukasz Bartosik sa->portid, size); 1304965dda0SLukasz Bartosik continue; 1314965dda0SLukasz Bartosik } 1324965dda0SLukasz Bartosik 1334965dda0SLukasz Bartosik /* Use only first inline session found for a given port */ 134ea28ab88SNithin Dabilpuram if (data[sa->portid].sess) 1354965dda0SLukasz Bartosik continue; 136ea28ab88SNithin Dabilpuram data[sa->portid].sess = pri_sess->security.ses; 137ea28ab88SNithin Dabilpuram data[sa->portid].ctx = pri_sess->security.ctx; 1384965dda0SLukasz Bartosik } 1394965dda0SLukasz Bartosik } 1404965dda0SLukasz Bartosik 1419ad50c29SLukasz Bartosik static inline int 1429ad50c29SLukasz Bartosik check_sp(struct sp_ctx *sp, const uint8_t *nlp, uint32_t *sa_idx) 1439ad50c29SLukasz Bartosik { 1449ad50c29SLukasz Bartosik uint32_t res; 1459ad50c29SLukasz Bartosik 1469ad50c29SLukasz Bartosik if (unlikely(sp == NULL)) 1479ad50c29SLukasz Bartosik return 0; 1489ad50c29SLukasz Bartosik 1499ad50c29SLukasz Bartosik rte_acl_classify((struct rte_acl_ctx *)sp, &nlp, &res, 1, 1509ad50c29SLukasz Bartosik DEFAULT_MAX_CATEGORIES); 1519ad50c29SLukasz Bartosik 152ab722af6SAnkur Dwivedi if (unlikely(res == DISCARD)) 1539ad50c29SLukasz Bartosik return 0; 1549ad50c29SLukasz Bartosik else if (res == BYPASS) { 1559ad50c29SLukasz Bartosik *sa_idx = -1; 1569ad50c29SLukasz Bartosik return 1; 1579ad50c29SLukasz Bartosik } 1589ad50c29SLukasz Bartosik 1599ad50c29SLukasz Bartosik *sa_idx = res - 1; 1609ad50c29SLukasz Bartosik return 1; 1619ad50c29SLukasz Bartosik } 1629ad50c29SLukasz Bartosik 16386738ebeSSrujana Challa static inline void 16486738ebeSSrujana Challa check_sp_bulk(struct sp_ctx *sp, struct traffic_type *ip, 16586738ebeSSrujana Challa struct traffic_type *ipsec) 16686738ebeSSrujana Challa { 16786738ebeSSrujana Challa uint32_t i, j, res; 16886738ebeSSrujana Challa struct rte_mbuf *m; 16986738ebeSSrujana Challa 17086738ebeSSrujana Challa if (unlikely(sp == NULL || ip->num == 0)) 17186738ebeSSrujana Challa return; 17286738ebeSSrujana Challa 17386738ebeSSrujana Challa rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, ip->num, 17486738ebeSSrujana Challa DEFAULT_MAX_CATEGORIES); 17586738ebeSSrujana Challa 17686738ebeSSrujana Challa j = 0; 17786738ebeSSrujana Challa for (i = 0; i < ip->num; i++) { 17886738ebeSSrujana Challa m = ip->pkts[i]; 17986738ebeSSrujana Challa res = ip->res[i]; 18086738ebeSSrujana Challa if (unlikely(res == DISCARD)) 18186738ebeSSrujana Challa free_pkts(&m, 1); 18286738ebeSSrujana Challa else if (res == BYPASS) 18386738ebeSSrujana Challa ip->pkts[j++] = m; 18486738ebeSSrujana Challa else { 18586738ebeSSrujana Challa ipsec->res[ipsec->num] = res - 1; 18686738ebeSSrujana Challa ipsec->pkts[ipsec->num++] = m; 18786738ebeSSrujana Challa } 18886738ebeSSrujana Challa } 18986738ebeSSrujana Challa ip->num = j; 19086738ebeSSrujana Challa } 19186738ebeSSrujana Challa 19286738ebeSSrujana Challa static inline void 19386738ebeSSrujana Challa check_sp_sa_bulk(struct sp_ctx *sp, struct sa_ctx *sa_ctx, 19486738ebeSSrujana Challa struct traffic_type *ip) 19586738ebeSSrujana Challa { 19686738ebeSSrujana Challa struct ipsec_sa *sa; 19786738ebeSSrujana Challa uint32_t i, j, res; 19886738ebeSSrujana Challa struct rte_mbuf *m; 19986738ebeSSrujana Challa 20086738ebeSSrujana Challa if (unlikely(sp == NULL || ip->num == 0)) 20186738ebeSSrujana Challa return; 20286738ebeSSrujana Challa 20386738ebeSSrujana Challa rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, ip->num, 20486738ebeSSrujana Challa DEFAULT_MAX_CATEGORIES); 20586738ebeSSrujana Challa 20686738ebeSSrujana Challa j = 0; 20786738ebeSSrujana Challa for (i = 0; i < ip->num; i++) { 20886738ebeSSrujana Challa m = ip->pkts[i]; 20986738ebeSSrujana Challa res = ip->res[i]; 21086738ebeSSrujana Challa if (unlikely(res == DISCARD)) 21186738ebeSSrujana Challa free_pkts(&m, 1); 21286738ebeSSrujana Challa else if (res == BYPASS) 21386738ebeSSrujana Challa ip->pkts[j++] = m; 21486738ebeSSrujana Challa else { 21586738ebeSSrujana Challa sa = *(struct ipsec_sa **)rte_security_dynfield(m); 2165fb245baSNithin Dabilpuram if (sa == NULL) { 21786738ebeSSrujana Challa free_pkts(&m, 1); 2185fb245baSNithin Dabilpuram continue; 2195fb245baSNithin Dabilpuram } 22086738ebeSSrujana Challa 22186738ebeSSrujana Challa /* SPI on the packet should match with the one in SA */ 2225fb245baSNithin Dabilpuram if (unlikely(sa->spi != sa_ctx->sa[res - 1].spi)) { 22386738ebeSSrujana Challa free_pkts(&m, 1); 2245fb245baSNithin Dabilpuram continue; 2255fb245baSNithin Dabilpuram } 22686738ebeSSrujana Challa 22786738ebeSSrujana Challa ip->pkts[j++] = m; 22886738ebeSSrujana Challa } 22986738ebeSSrujana Challa } 23086738ebeSSrujana Challa ip->num = j; 23186738ebeSSrujana Challa } 23286738ebeSSrujana Challa 2336938fc92SVolodymyr Fialko static inline void 2346938fc92SVolodymyr Fialko ipv4_pkt_l3_len_set(struct rte_mbuf *pkt) 2356938fc92SVolodymyr Fialko { 2366938fc92SVolodymyr Fialko struct rte_ipv4_hdr *ipv4; 2376938fc92SVolodymyr Fialko 2386938fc92SVolodymyr Fialko ipv4 = rte_pktmbuf_mtod(pkt, struct rte_ipv4_hdr *); 2396938fc92SVolodymyr Fialko pkt->l3_len = ipv4->ihl * 4; 2406938fc92SVolodymyr Fialko } 2416938fc92SVolodymyr Fialko 2426938fc92SVolodymyr Fialko static inline int 2436938fc92SVolodymyr Fialko ipv6_pkt_l3_len_set(struct rte_mbuf *pkt) 2446938fc92SVolodymyr Fialko { 2456938fc92SVolodymyr Fialko struct rte_ipv6_hdr *ipv6; 2466938fc92SVolodymyr Fialko size_t l3_len, ext_len; 2476938fc92SVolodymyr Fialko uint32_t l3_type; 2486938fc92SVolodymyr Fialko int next_proto; 2496938fc92SVolodymyr Fialko uint8_t *p; 2506938fc92SVolodymyr Fialko 2516938fc92SVolodymyr Fialko ipv6 = rte_pktmbuf_mtod(pkt, struct rte_ipv6_hdr *); 2526938fc92SVolodymyr Fialko l3_len = sizeof(struct rte_ipv6_hdr); 2536938fc92SVolodymyr Fialko l3_type = pkt->packet_type & RTE_PTYPE_L3_MASK; 2546938fc92SVolodymyr Fialko 2556938fc92SVolodymyr Fialko if (l3_type == RTE_PTYPE_L3_IPV6_EXT || 2566938fc92SVolodymyr Fialko l3_type == RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) { 2576938fc92SVolodymyr Fialko p = rte_pktmbuf_mtod(pkt, uint8_t *); 2586938fc92SVolodymyr Fialko next_proto = ipv6->proto; 2596938fc92SVolodymyr Fialko while (next_proto != IPPROTO_ESP && 2606938fc92SVolodymyr Fialko l3_len < pkt->data_len && 2616938fc92SVolodymyr Fialko (next_proto = rte_ipv6_get_next_ext(p + l3_len, 2626938fc92SVolodymyr Fialko next_proto, &ext_len)) >= 0) 2636938fc92SVolodymyr Fialko l3_len += ext_len; 2646938fc92SVolodymyr Fialko 2656938fc92SVolodymyr Fialko /* Drop pkt when IPv6 header exceeds first seg size */ 2666938fc92SVolodymyr Fialko if (unlikely(l3_len > pkt->data_len)) 2676938fc92SVolodymyr Fialko return -EINVAL; 2686938fc92SVolodymyr Fialko } 2696938fc92SVolodymyr Fialko pkt->l3_len = l3_len; 2706938fc92SVolodymyr Fialko 2716938fc92SVolodymyr Fialko return 0; 2726938fc92SVolodymyr Fialko } 2736938fc92SVolodymyr Fialko 2749ad50c29SLukasz Bartosik static inline uint16_t 2759ad50c29SLukasz Bartosik route4_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx) 2769ad50c29SLukasz Bartosik { 2779ad50c29SLukasz Bartosik uint32_t dst_ip; 2789ad50c29SLukasz Bartosik uint16_t offset; 2799ad50c29SLukasz Bartosik uint32_t hop; 2809ad50c29SLukasz Bartosik int ret; 2819ad50c29SLukasz Bartosik 2829ad50c29SLukasz Bartosik offset = RTE_ETHER_HDR_LEN + offsetof(struct ip, ip_dst); 2839ad50c29SLukasz Bartosik dst_ip = *rte_pktmbuf_mtod_offset(pkt, uint32_t *, offset); 2849ad50c29SLukasz Bartosik dst_ip = rte_be_to_cpu_32(dst_ip); 2859ad50c29SLukasz Bartosik 2869ad50c29SLukasz Bartosik ret = rte_lpm_lookup((struct rte_lpm *)rt_ctx, dst_ip, &hop); 2879ad50c29SLukasz Bartosik 2889ad50c29SLukasz Bartosik if (ret == 0) { 2899ad50c29SLukasz Bartosik /* We have a hit */ 2909ad50c29SLukasz Bartosik return hop; 2919ad50c29SLukasz Bartosik } 2929ad50c29SLukasz Bartosik 2939ad50c29SLukasz Bartosik /* else */ 2949ad50c29SLukasz Bartosik return RTE_MAX_ETHPORTS; 2959ad50c29SLukasz Bartosik } 2969ad50c29SLukasz Bartosik 2979ad50c29SLukasz Bartosik /* TODO: To be tested */ 2989ad50c29SLukasz Bartosik static inline uint16_t 2999ad50c29SLukasz Bartosik route6_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx) 3009ad50c29SLukasz Bartosik { 301*e1a06e39SRobin Jarry struct rte_ipv6_hdr *ip; 3029ad50c29SLukasz Bartosik uint32_t hop; 3039ad50c29SLukasz Bartosik int ret; 3049ad50c29SLukasz Bartosik 305*e1a06e39SRobin Jarry ip = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *, RTE_ETHER_HDR_LEN); 306*e1a06e39SRobin Jarry ret = rte_lpm6_lookup((struct rte_lpm6 *)rt_ctx, &ip->dst_addr, &hop); 3079ad50c29SLukasz Bartosik 3089ad50c29SLukasz Bartosik if (ret == 0) { 3099ad50c29SLukasz Bartosik /* We have a hit */ 3109ad50c29SLukasz Bartosik return hop; 3119ad50c29SLukasz Bartosik } 3129ad50c29SLukasz Bartosik 3139ad50c29SLukasz Bartosik /* else */ 3149ad50c29SLukasz Bartosik return RTE_MAX_ETHPORTS; 3159ad50c29SLukasz Bartosik } 3169ad50c29SLukasz Bartosik 3179ad50c29SLukasz Bartosik static inline uint16_t 3189ad50c29SLukasz Bartosik get_route(struct rte_mbuf *pkt, struct route_table *rt, enum pkt_type type) 3199ad50c29SLukasz Bartosik { 3209ad50c29SLukasz Bartosik if (type == PKT_TYPE_PLAIN_IPV4 || type == PKT_TYPE_IPSEC_IPV4) 3219ad50c29SLukasz Bartosik return route4_pkt(pkt, rt->rt4_ctx); 3229ad50c29SLukasz Bartosik else if (type == PKT_TYPE_PLAIN_IPV6 || type == PKT_TYPE_IPSEC_IPV6) 3239ad50c29SLukasz Bartosik return route6_pkt(pkt, rt->rt6_ctx); 3249ad50c29SLukasz Bartosik 3259ad50c29SLukasz Bartosik return RTE_MAX_ETHPORTS; 3269ad50c29SLukasz Bartosik } 3279ad50c29SLukasz Bartosik 3286938fc92SVolodymyr Fialko static inline void 3296938fc92SVolodymyr Fialko crypto_op_reset(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], 3306938fc92SVolodymyr Fialko struct rte_crypto_op *cop[], uint16_t num) 3316938fc92SVolodymyr Fialko { 3326938fc92SVolodymyr Fialko struct rte_crypto_sym_op *sop; 3336938fc92SVolodymyr Fialko uint32_t i; 3346938fc92SVolodymyr Fialko 3356938fc92SVolodymyr Fialko const struct rte_crypto_op unproc_cop = { 3366938fc92SVolodymyr Fialko .type = RTE_CRYPTO_OP_TYPE_SYMMETRIC, 3376938fc92SVolodymyr Fialko .status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED, 3386938fc92SVolodymyr Fialko .sess_type = RTE_CRYPTO_OP_SECURITY_SESSION, 3396938fc92SVolodymyr Fialko }; 3406938fc92SVolodymyr Fialko 3416938fc92SVolodymyr Fialko for (i = 0; i != num; i++) { 3426938fc92SVolodymyr Fialko cop[i]->raw = unproc_cop.raw; 3436938fc92SVolodymyr Fialko sop = cop[i]->sym; 3446938fc92SVolodymyr Fialko sop->m_src = mb[i]; 3456938fc92SVolodymyr Fialko sop->m_dst = NULL; 3466938fc92SVolodymyr Fialko __rte_security_attach_session(sop, ss->security.ses); 3476938fc92SVolodymyr Fialko } 3486938fc92SVolodymyr Fialko } 3496938fc92SVolodymyr Fialko 3501d5078c6SVolodymyr Fialko static inline void 3511d5078c6SVolodymyr Fialko crypto_prepare_event(struct rte_mbuf *pkt, struct rte_ipsec_session *sess, struct rte_event *ev) 3526938fc92SVolodymyr Fialko { 3536938fc92SVolodymyr Fialko struct ipsec_mbuf_metadata *priv; 3546938fc92SVolodymyr Fialko struct rte_crypto_op *cop; 3556938fc92SVolodymyr Fialko 3566938fc92SVolodymyr Fialko /* Get pkt private data */ 3576938fc92SVolodymyr Fialko priv = get_priv(pkt); 3586938fc92SVolodymyr Fialko cop = &priv->cop; 3596938fc92SVolodymyr Fialko 3606938fc92SVolodymyr Fialko /* Reset crypto operation data */ 3616938fc92SVolodymyr Fialko crypto_op_reset(sess, &pkt, &cop, 1); 3626938fc92SVolodymyr Fialko 3636938fc92SVolodymyr Fialko /* Update event_ptr with rte_crypto_op */ 3641d5078c6SVolodymyr Fialko ev->event = 0; 3651d5078c6SVolodymyr Fialko ev->event_ptr = cop; 3661d5078c6SVolodymyr Fialko } 3671d5078c6SVolodymyr Fialko 3681d5078c6SVolodymyr Fialko static inline void 3691d5078c6SVolodymyr Fialko free_pkts_from_events(struct rte_event events[], uint16_t count) 3701d5078c6SVolodymyr Fialko { 3711d5078c6SVolodymyr Fialko struct rte_crypto_op *cop; 3721d5078c6SVolodymyr Fialko int i; 3731d5078c6SVolodymyr Fialko 3741d5078c6SVolodymyr Fialko for (i = 0; i < count; i++) { 3751d5078c6SVolodymyr Fialko cop = events[i].event_ptr; 3761d5078c6SVolodymyr Fialko free_pkts(&cop->sym->m_src, 1); 3771d5078c6SVolodymyr Fialko } 3781d5078c6SVolodymyr Fialko } 3791d5078c6SVolodymyr Fialko 3801d5078c6SVolodymyr Fialko static inline int 3811d5078c6SVolodymyr Fialko event_crypto_enqueue(struct rte_mbuf *pkt, 3821d5078c6SVolodymyr Fialko struct ipsec_sa *sa, const struct eh_event_link_info *ev_link) 3831d5078c6SVolodymyr Fialko { 3841d5078c6SVolodymyr Fialko struct rte_ipsec_session *sess; 3851d5078c6SVolodymyr Fialko struct rte_event ev; 3861d5078c6SVolodymyr Fialko int ret; 3871d5078c6SVolodymyr Fialko 3881d5078c6SVolodymyr Fialko /* Get IPsec session */ 3891d5078c6SVolodymyr Fialko sess = ipsec_get_primary_session(sa); 3901d5078c6SVolodymyr Fialko 3911d5078c6SVolodymyr Fialko crypto_prepare_event(pkt, sess, &ev); 3926938fc92SVolodymyr Fialko 3936938fc92SVolodymyr Fialko /* Enqueue event to crypto adapter */ 3946938fc92SVolodymyr Fialko ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id, 3951d5078c6SVolodymyr Fialko ev_link->event_port_id, &ev, 1); 3961d5078c6SVolodymyr Fialko if (unlikely(ret != 1)) { 3976938fc92SVolodymyr Fialko /* pkt will be freed by the caller */ 3986938fc92SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue event: %i (errno: %i)\n", ret, rte_errno); 3996938fc92SVolodymyr Fialko return rte_errno; 4006938fc92SVolodymyr Fialko } 4016938fc92SVolodymyr Fialko 4026938fc92SVolodymyr Fialko return 0; 4036938fc92SVolodymyr Fialko } 4046938fc92SVolodymyr Fialko 4059ad50c29SLukasz Bartosik static inline int 4069ad50c29SLukasz Bartosik process_ipsec_ev_inbound(struct ipsec_ctx *ctx, struct route_table *rt, 4076938fc92SVolodymyr Fialko const struct eh_event_link_info *ev_link, struct rte_event *ev) 4089ad50c29SLukasz Bartosik { 4099ad50c29SLukasz Bartosik struct ipsec_sa *sa = NULL; 4109ad50c29SLukasz Bartosik struct rte_mbuf *pkt; 4119ad50c29SLukasz Bartosik uint16_t port_id = 0; 4129ad50c29SLukasz Bartosik enum pkt_type type; 4139ad50c29SLukasz Bartosik uint32_t sa_idx; 4149ad50c29SLukasz Bartosik uint8_t *nlp; 4159ad50c29SLukasz Bartosik 4169ad50c29SLukasz Bartosik /* Get pkt from event */ 4179ad50c29SLukasz Bartosik pkt = ev->mbuf; 418d8d51d4fSRahul Bhansali if (is_ip_reassembly_incomplete(pkt) > 0) { 419d8d51d4fSRahul Bhansali free_reassembly_fail_pkt(pkt); 420d8d51d4fSRahul Bhansali return PKT_DROPPED; 421d8d51d4fSRahul Bhansali } 4229ad50c29SLukasz Bartosik 4239ad50c29SLukasz Bartosik /* Check the packet type */ 4249ad50c29SLukasz Bartosik type = process_ipsec_get_pkt_type(pkt, &nlp); 4259ad50c29SLukasz Bartosik 4269ad50c29SLukasz Bartosik switch (type) { 4279ad50c29SLukasz Bartosik case PKT_TYPE_PLAIN_IPV4: 428daa02b5cSOlivier Matz if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) { 4299ad50c29SLukasz Bartosik if (unlikely(pkt->ol_flags & 430daa02b5cSOlivier Matz RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) { 4319ad50c29SLukasz Bartosik RTE_LOG(ERR, IPSEC, 4329ad50c29SLukasz Bartosik "Inbound security offload failed\n"); 4339ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 4349ad50c29SLukasz Bartosik } 435614af754SThomas Monjalon sa = *(struct ipsec_sa **)rte_security_dynfield(pkt); 4369ad50c29SLukasz Bartosik } 4379ad50c29SLukasz Bartosik 4389ad50c29SLukasz Bartosik /* Check if we have a match */ 4399ad50c29SLukasz Bartosik if (check_sp(ctx->sp4_ctx, nlp, &sa_idx) == 0) { 4409ad50c29SLukasz Bartosik /* No valid match */ 4419ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 4429ad50c29SLukasz Bartosik } 4439ad50c29SLukasz Bartosik break; 4449ad50c29SLukasz Bartosik 4459ad50c29SLukasz Bartosik case PKT_TYPE_PLAIN_IPV6: 446daa02b5cSOlivier Matz if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) { 4479ad50c29SLukasz Bartosik if (unlikely(pkt->ol_flags & 448daa02b5cSOlivier Matz RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) { 4499ad50c29SLukasz Bartosik RTE_LOG(ERR, IPSEC, 4509ad50c29SLukasz Bartosik "Inbound security offload failed\n"); 4519ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 4529ad50c29SLukasz Bartosik } 453614af754SThomas Monjalon sa = *(struct ipsec_sa **)rte_security_dynfield(pkt); 4549ad50c29SLukasz Bartosik } 4559ad50c29SLukasz Bartosik 4569ad50c29SLukasz Bartosik /* Check if we have a match */ 4579ad50c29SLukasz Bartosik if (check_sp(ctx->sp6_ctx, nlp, &sa_idx) == 0) { 4589ad50c29SLukasz Bartosik /* No valid match */ 4599ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 4609ad50c29SLukasz Bartosik } 4619ad50c29SLukasz Bartosik break; 4626938fc92SVolodymyr Fialko case PKT_TYPE_IPSEC_IPV4: 4636938fc92SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 4646938fc92SVolodymyr Fialko ipv4_pkt_l3_len_set(pkt); 4656938fc92SVolodymyr Fialko sad_lookup(&ctx->sa_ctx->sad, &pkt, (void **)&sa, 1); 4666938fc92SVolodymyr Fialko sa = ipsec_mask_saptr(sa); 4676938fc92SVolodymyr Fialko if (unlikely(sa == NULL)) { 4686938fc92SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot find sa\n"); 4696938fc92SVolodymyr Fialko goto drop_pkt_and_exit; 4706938fc92SVolodymyr Fialko } 4719ad50c29SLukasz Bartosik 4721d5078c6SVolodymyr Fialko if (unlikely(event_crypto_enqueue(pkt, sa, ev_link))) 4736938fc92SVolodymyr Fialko goto drop_pkt_and_exit; 4746938fc92SVolodymyr Fialko 4756938fc92SVolodymyr Fialko return PKT_POSTED; 4766938fc92SVolodymyr Fialko case PKT_TYPE_IPSEC_IPV6: 4776938fc92SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 4786938fc92SVolodymyr Fialko if (unlikely(ipv6_pkt_l3_len_set(pkt) != 0)) 4796938fc92SVolodymyr Fialko goto drop_pkt_and_exit; 4806938fc92SVolodymyr Fialko sad_lookup(&ctx->sa_ctx->sad, &pkt, (void **)&sa, 1); 4816938fc92SVolodymyr Fialko sa = ipsec_mask_saptr(sa); 4826938fc92SVolodymyr Fialko if (unlikely(sa == NULL)) { 4836938fc92SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot find sa\n"); 4846938fc92SVolodymyr Fialko goto drop_pkt_and_exit; 4856938fc92SVolodymyr Fialko } 4866938fc92SVolodymyr Fialko 4871d5078c6SVolodymyr Fialko if (unlikely(event_crypto_enqueue(pkt, sa, ev_link))) 4886938fc92SVolodymyr Fialko goto drop_pkt_and_exit; 4896938fc92SVolodymyr Fialko 4906938fc92SVolodymyr Fialko return PKT_POSTED; 4919ad50c29SLukasz Bartosik default: 4925315b774SNithin Dabilpuram RTE_LOG_DP(DEBUG, IPSEC_ESP, "Unsupported packet type = %d\n", 4935315b774SNithin Dabilpuram type); 4949ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 4959ad50c29SLukasz Bartosik } 4969ad50c29SLukasz Bartosik 4979ad50c29SLukasz Bartosik /* Check if the packet has to be bypassed */ 4989ad50c29SLukasz Bartosik if (sa_idx == BYPASS) 4999ad50c29SLukasz Bartosik goto route_and_send_pkt; 5009ad50c29SLukasz Bartosik 5019ad50c29SLukasz Bartosik /* Validate sa_idx */ 5029ad50c29SLukasz Bartosik if (sa_idx >= ctx->sa_ctx->nb_sa) 5039ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5049ad50c29SLukasz Bartosik 5059ad50c29SLukasz Bartosik /* Else the packet has to be protected with SA */ 5069ad50c29SLukasz Bartosik 5079ad50c29SLukasz Bartosik /* If the packet was IPsec processed, then SA pointer should be set */ 5089ad50c29SLukasz Bartosik if (sa == NULL) 5099ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5109ad50c29SLukasz Bartosik 5119ad50c29SLukasz Bartosik /* SPI on the packet should match with the one in SA */ 5129ad50c29SLukasz Bartosik if (unlikely(sa->spi != ctx->sa_ctx->sa[sa_idx].spi)) 5139ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5149ad50c29SLukasz Bartosik 5159ad50c29SLukasz Bartosik route_and_send_pkt: 5169ad50c29SLukasz Bartosik port_id = get_route(pkt, rt, type); 5179ad50c29SLukasz Bartosik if (unlikely(port_id == RTE_MAX_ETHPORTS)) { 5189ad50c29SLukasz Bartosik /* no match */ 5199ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5209ad50c29SLukasz Bartosik } 5219ad50c29SLukasz Bartosik /* else, we have a matching route */ 5229ad50c29SLukasz Bartosik 5239ad50c29SLukasz Bartosik /* Update mac addresses */ 52458e2cf4cSNithin Dabilpuram update_mac_addrs(rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *), port_id); 5259ad50c29SLukasz Bartosik 5269ad50c29SLukasz Bartosik /* Update the event with the dest port */ 5279ad50c29SLukasz Bartosik ipsec_event_pre_forward(pkt, port_id); 5289ad50c29SLukasz Bartosik return PKT_FORWARDED; 5299ad50c29SLukasz Bartosik 5309ad50c29SLukasz Bartosik drop_pkt_and_exit: 531f44481efSVolodymyr Fialko free_pkts(&pkt, 1); 5329ad50c29SLukasz Bartosik ev->mbuf = NULL; 5339ad50c29SLukasz Bartosik return PKT_DROPPED; 5349ad50c29SLukasz Bartosik } 5359ad50c29SLukasz Bartosik 5369ad50c29SLukasz Bartosik static inline int 5379ad50c29SLukasz Bartosik process_ipsec_ev_outbound(struct ipsec_ctx *ctx, struct route_table *rt, 5386938fc92SVolodymyr Fialko const struct eh_event_link_info *ev_link, struct rte_event *ev) 5399ad50c29SLukasz Bartosik { 5409ad50c29SLukasz Bartosik struct rte_ipsec_session *sess; 54158e2cf4cSNithin Dabilpuram struct rte_ether_hdr *ethhdr; 5429ad50c29SLukasz Bartosik struct sa_ctx *sa_ctx; 5439ad50c29SLukasz Bartosik struct rte_mbuf *pkt; 5449ad50c29SLukasz Bartosik uint16_t port_id = 0; 5459ad50c29SLukasz Bartosik struct ipsec_sa *sa; 5469ad50c29SLukasz Bartosik enum pkt_type type; 5479ad50c29SLukasz Bartosik uint32_t sa_idx; 5489ad50c29SLukasz Bartosik uint8_t *nlp; 5499ad50c29SLukasz Bartosik 5509ad50c29SLukasz Bartosik /* Get pkt from event */ 5519ad50c29SLukasz Bartosik pkt = ev->mbuf; 5529ad50c29SLukasz Bartosik 5539ad50c29SLukasz Bartosik /* Check the packet type */ 5549ad50c29SLukasz Bartosik type = process_ipsec_get_pkt_type(pkt, &nlp); 5559ad50c29SLukasz Bartosik 5569ad50c29SLukasz Bartosik switch (type) { 5579ad50c29SLukasz Bartosik case PKT_TYPE_PLAIN_IPV4: 5589ad50c29SLukasz Bartosik /* Check if we have a match */ 5599ad50c29SLukasz Bartosik if (check_sp(ctx->sp4_ctx, nlp, &sa_idx) == 0) { 5609ad50c29SLukasz Bartosik /* No valid match */ 5619ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5629ad50c29SLukasz Bartosik } 5639ad50c29SLukasz Bartosik break; 5649ad50c29SLukasz Bartosik case PKT_TYPE_PLAIN_IPV6: 5659ad50c29SLukasz Bartosik /* Check if we have a match */ 5669ad50c29SLukasz Bartosik if (check_sp(ctx->sp6_ctx, nlp, &sa_idx) == 0) { 5679ad50c29SLukasz Bartosik /* No valid match */ 5689ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5699ad50c29SLukasz Bartosik } 5709ad50c29SLukasz Bartosik break; 5719ad50c29SLukasz Bartosik default: 5729ad50c29SLukasz Bartosik /* 5739ad50c29SLukasz Bartosik * Only plain IPv4 & IPv6 packets are allowed 5749ad50c29SLukasz Bartosik * on protected port. Drop the rest. 5759ad50c29SLukasz Bartosik */ 576aabf7ec4SNithin Dabilpuram RTE_LOG_DP(DEBUG, IPSEC, "Unsupported packet type = %d\n", type); 5779ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5789ad50c29SLukasz Bartosik } 5799ad50c29SLukasz Bartosik 58058e2cf4cSNithin Dabilpuram ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 5819ad50c29SLukasz Bartosik /* Check if the packet has to be bypassed */ 5829ad50c29SLukasz Bartosik if (sa_idx == BYPASS) { 5839ad50c29SLukasz Bartosik port_id = get_route(pkt, rt, type); 5849ad50c29SLukasz Bartosik if (unlikely(port_id == RTE_MAX_ETHPORTS)) { 5859ad50c29SLukasz Bartosik /* no match */ 5869ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5879ad50c29SLukasz Bartosik } 5889ad50c29SLukasz Bartosik /* else, we have a matching route */ 5899ad50c29SLukasz Bartosik goto send_pkt; 5909ad50c29SLukasz Bartosik } 5919ad50c29SLukasz Bartosik 5929ad50c29SLukasz Bartosik /* Validate sa_idx */ 5932e7abb8bSNithin Dabilpuram if (unlikely(sa_idx >= ctx->sa_ctx->nb_sa)) 5949ad50c29SLukasz Bartosik goto drop_pkt_and_exit; 5959ad50c29SLukasz Bartosik 5969ad50c29SLukasz Bartosik /* Else the packet has to be protected */ 5979ad50c29SLukasz Bartosik 5989ad50c29SLukasz Bartosik /* Get SA ctx*/ 5999ad50c29SLukasz Bartosik sa_ctx = ctx->sa_ctx; 6009ad50c29SLukasz Bartosik 6019ad50c29SLukasz Bartosik /* Get SA */ 6029ad50c29SLukasz Bartosik sa = &(sa_ctx->sa[sa_idx]); 6039ad50c29SLukasz Bartosik 6049ad50c29SLukasz Bartosik /* Get IPsec session */ 6059ad50c29SLukasz Bartosik sess = ipsec_get_primary_session(sa); 6069ad50c29SLukasz Bartosik 6076938fc92SVolodymyr Fialko /* Determine protocol type */ 6086938fc92SVolodymyr Fialko if (sess->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) 6096938fc92SVolodymyr Fialko goto lookaside; 6109ad50c29SLukasz Bartosik 611ea28ab88SNithin Dabilpuram rte_security_set_pkt_metadata(sess->security.ctx, 612ea28ab88SNithin Dabilpuram sess->security.ses, pkt, NULL); 6139ad50c29SLukasz Bartosik 6149ad50c29SLukasz Bartosik /* Mark the packet for Tx security offload */ 615daa02b5cSOlivier Matz pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD; 61658e2cf4cSNithin Dabilpuram /* Update ether type */ 61758e2cf4cSNithin Dabilpuram ethhdr->ether_type = (IS_IP4(sa->flags) ? rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) : 61858e2cf4cSNithin Dabilpuram rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)); 6199ad50c29SLukasz Bartosik 6209ad50c29SLukasz Bartosik /* Get the port to which this pkt need to be submitted */ 6219ad50c29SLukasz Bartosik port_id = sa->portid; 6229ad50c29SLukasz Bartosik 6239ad50c29SLukasz Bartosik send_pkt: 624ea28ab88SNithin Dabilpuram /* Provide L2 len for Outbound processing */ 625ea28ab88SNithin Dabilpuram pkt->l2_len = RTE_ETHER_HDR_LEN; 626ea28ab88SNithin Dabilpuram 6279ad50c29SLukasz Bartosik /* Update mac addresses */ 62858e2cf4cSNithin Dabilpuram update_mac_addrs(ethhdr, port_id); 6299ad50c29SLukasz Bartosik 6309ad50c29SLukasz Bartosik /* Update the event with the dest port */ 6319ad50c29SLukasz Bartosik ipsec_event_pre_forward(pkt, port_id); 6329ad50c29SLukasz Bartosik return PKT_FORWARDED; 6339ad50c29SLukasz Bartosik 6346938fc92SVolodymyr Fialko lookaside: 6356938fc92SVolodymyr Fialko /* prepare pkt - advance start to L3 */ 6366938fc92SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 6376938fc92SVolodymyr Fialko 6381d5078c6SVolodymyr Fialko if (likely(event_crypto_enqueue(pkt, sa, ev_link) == 0)) 6396938fc92SVolodymyr Fialko return PKT_POSTED; 6406938fc92SVolodymyr Fialko 6419ad50c29SLukasz Bartosik drop_pkt_and_exit: 6429ad50c29SLukasz Bartosik RTE_LOG(ERR, IPSEC, "Outbound packet dropped\n"); 643f44481efSVolodymyr Fialko free_pkts(&pkt, 1); 6449ad50c29SLukasz Bartosik ev->mbuf = NULL; 6459ad50c29SLukasz Bartosik return PKT_DROPPED; 6469ad50c29SLukasz Bartosik } 6479ad50c29SLukasz Bartosik 64886738ebeSSrujana Challa static inline int 6491d5078c6SVolodymyr Fialko ipsec_ev_route_ip_pkts(struct rte_event_vector *vec, struct route_table *rt, 6501d5078c6SVolodymyr Fialko struct ipsec_traffic *t) 65186738ebeSSrujana Challa { 65258e2cf4cSNithin Dabilpuram struct rte_ether_hdr *ethhdr; 65386738ebeSSrujana Challa struct rte_mbuf *pkt; 6541d5078c6SVolodymyr Fialko uint16_t port_id = 0; 6551d5078c6SVolodymyr Fialko uint32_t i, j = 0; 65686738ebeSSrujana Challa 65786738ebeSSrujana Challa /* Route IPv4 packets */ 65886738ebeSSrujana Challa for (i = 0; i < t->ip4.num; i++) { 65986738ebeSSrujana Challa pkt = t->ip4.pkts[i]; 66086738ebeSSrujana Challa port_id = route4_pkt(pkt, rt->rt4_ctx); 66186738ebeSSrujana Challa if (port_id != RTE_MAX_ETHPORTS) { 66286738ebeSSrujana Challa /* Update mac addresses */ 66358e2cf4cSNithin Dabilpuram ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 66458e2cf4cSNithin Dabilpuram update_mac_addrs(ethhdr, port_id); 66586738ebeSSrujana Challa /* Update the event with the dest port */ 66686738ebeSSrujana Challa ipsec_event_pre_forward(pkt, port_id); 66786738ebeSSrujana Challa ev_vector_attr_update(vec, pkt); 66886738ebeSSrujana Challa vec->mbufs[j++] = pkt; 66986738ebeSSrujana Challa } else 67086738ebeSSrujana Challa free_pkts(&pkt, 1); 67186738ebeSSrujana Challa } 67286738ebeSSrujana Challa 67386738ebeSSrujana Challa /* Route IPv6 packets */ 67486738ebeSSrujana Challa for (i = 0; i < t->ip6.num; i++) { 67586738ebeSSrujana Challa pkt = t->ip6.pkts[i]; 67686738ebeSSrujana Challa port_id = route6_pkt(pkt, rt->rt6_ctx); 67786738ebeSSrujana Challa if (port_id != RTE_MAX_ETHPORTS) { 67886738ebeSSrujana Challa /* Update mac addresses */ 67958e2cf4cSNithin Dabilpuram ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 68058e2cf4cSNithin Dabilpuram update_mac_addrs(ethhdr, port_id); 68186738ebeSSrujana Challa /* Update the event with the dest port */ 68286738ebeSSrujana Challa ipsec_event_pre_forward(pkt, port_id); 68386738ebeSSrujana Challa ev_vector_attr_update(vec, pkt); 68486738ebeSSrujana Challa vec->mbufs[j++] = pkt; 68586738ebeSSrujana Challa } else 68686738ebeSSrujana Challa free_pkts(&pkt, 1); 68786738ebeSSrujana Challa } 68886738ebeSSrujana Challa 6891d5078c6SVolodymyr Fialko return j; 6901d5078c6SVolodymyr Fialko } 6911d5078c6SVolodymyr Fialko 6921d5078c6SVolodymyr Fialko static inline int 6931d5078c6SVolodymyr Fialko ipsec_ev_inbound_route_pkts(struct rte_event_vector *vec, 6941d5078c6SVolodymyr Fialko struct route_table *rt, 6951d5078c6SVolodymyr Fialko struct ipsec_traffic *t, 6961d5078c6SVolodymyr Fialko const struct eh_event_link_info *ev_link) 6971d5078c6SVolodymyr Fialko { 6981d5078c6SVolodymyr Fialko uint32_t ret, i, j, ev_len = 0; 6991d5078c6SVolodymyr Fialko struct rte_event events[MAX_PKTS]; 7001d5078c6SVolodymyr Fialko struct rte_ipsec_session *sess; 7011d5078c6SVolodymyr Fialko struct rte_mbuf *pkt; 7021d5078c6SVolodymyr Fialko struct ipsec_sa *sa; 7031d5078c6SVolodymyr Fialko 7041d5078c6SVolodymyr Fialko j = ipsec_ev_route_ip_pkts(vec, rt, t); 7051d5078c6SVolodymyr Fialko 70686738ebeSSrujana Challa /* Route ESP packets */ 70786738ebeSSrujana Challa for (i = 0; i < t->ipsec.num; i++) { 7081d5078c6SVolodymyr Fialko pkt = t->ipsec.pkts[i]; 7091d5078c6SVolodymyr Fialko sa = ipsec_mask_saptr(t->ipsec.saptr[i]); 7101d5078c6SVolodymyr Fialko if (unlikely(sa == NULL)) { 7111d5078c6SVolodymyr Fialko free_pkts(&pkt, 1); 7121d5078c6SVolodymyr Fialko continue; 7131d5078c6SVolodymyr Fialko } 7141d5078c6SVolodymyr Fialko sess = ipsec_get_primary_session(sa); 7151d5078c6SVolodymyr Fialko crypto_prepare_event(pkt, sess, &events[ev_len]); 7161d5078c6SVolodymyr Fialko ev_len++; 7171d5078c6SVolodymyr Fialko } 7181d5078c6SVolodymyr Fialko 7191d5078c6SVolodymyr Fialko if (ev_len) { 7201d5078c6SVolodymyr Fialko ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id, 7211d5078c6SVolodymyr Fialko ev_link->event_port_id, events, ev_len); 7221d5078c6SVolodymyr Fialko if (ret < ev_len) { 7231d5078c6SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue events: %i (errno: %i)\n", 7241d5078c6SVolodymyr Fialko ev_len, rte_errno); 7251d5078c6SVolodymyr Fialko free_pkts_from_events(&events[ret], ev_len - ret); 7261d5078c6SVolodymyr Fialko return -rte_errno; 7271d5078c6SVolodymyr Fialko } 7281d5078c6SVolodymyr Fialko } 7291d5078c6SVolodymyr Fialko 7301d5078c6SVolodymyr Fialko return j; 7311d5078c6SVolodymyr Fialko } 7321d5078c6SVolodymyr Fialko 7331d5078c6SVolodymyr Fialko static inline int 7341d5078c6SVolodymyr Fialko ipsec_ev_outbound_route_pkts(struct rte_event_vector *vec, struct route_table *rt, 7351d5078c6SVolodymyr Fialko struct ipsec_traffic *t, struct sa_ctx *sa_ctx, 7361d5078c6SVolodymyr Fialko const struct eh_event_link_info *ev_link) 7371d5078c6SVolodymyr Fialko { 7381d5078c6SVolodymyr Fialko uint32_t sa_idx, ret, i, j, ev_len = 0; 7391d5078c6SVolodymyr Fialko struct rte_event events[MAX_PKTS]; 7401d5078c6SVolodymyr Fialko struct rte_ipsec_session *sess; 7411d5078c6SVolodymyr Fialko struct rte_ether_hdr *ethhdr; 7421d5078c6SVolodymyr Fialko uint16_t port_id = 0; 7431d5078c6SVolodymyr Fialko struct rte_mbuf *pkt; 7441d5078c6SVolodymyr Fialko struct ipsec_sa *sa; 7451d5078c6SVolodymyr Fialko 7461d5078c6SVolodymyr Fialko j = ipsec_ev_route_ip_pkts(vec, rt, t); 7471d5078c6SVolodymyr Fialko 7481d5078c6SVolodymyr Fialko /* Handle IPsec packets. 7491d5078c6SVolodymyr Fialko * For lookaside IPsec packets, submit to cryptodev queue. 7501d5078c6SVolodymyr Fialko * For inline IPsec packets, route the packet. 7511d5078c6SVolodymyr Fialko */ 7521d5078c6SVolodymyr Fialko for (i = 0; i < t->ipsec.num; i++) { 75386738ebeSSrujana Challa /* Validate sa_idx */ 75486738ebeSSrujana Challa sa_idx = t->ipsec.res[i]; 75586738ebeSSrujana Challa pkt = t->ipsec.pkts[i]; 7561d5078c6SVolodymyr Fialko if (unlikely(sa_idx >= sa_ctx->nb_sa)) { 75786738ebeSSrujana Challa free_pkts(&pkt, 1); 7581d5078c6SVolodymyr Fialko continue; 7591d5078c6SVolodymyr Fialko } 76086738ebeSSrujana Challa /* Else the packet has to be protected */ 76186738ebeSSrujana Challa sa = &(sa_ctx->sa[sa_idx]); 76286738ebeSSrujana Challa /* Get IPsec session */ 76386738ebeSSrujana Challa sess = ipsec_get_primary_session(sa); 7641d5078c6SVolodymyr Fialko switch (sess->type) { 7651d5078c6SVolodymyr Fialko case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 7661d5078c6SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 7671d5078c6SVolodymyr Fialko crypto_prepare_event(pkt, sess, &events[ev_len]); 7681d5078c6SVolodymyr Fialko ev_len++; 7691d5078c6SVolodymyr Fialko break; 7701d5078c6SVolodymyr Fialko case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 77186738ebeSSrujana Challa rte_security_set_pkt_metadata(sess->security.ctx, 77286738ebeSSrujana Challa sess->security.ses, pkt, NULL); 77386738ebeSSrujana Challa pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD; 77486738ebeSSrujana Challa port_id = sa->portid; 77558e2cf4cSNithin Dabilpuram 77658e2cf4cSNithin Dabilpuram /* Fetch outer ip type and update */ 77758e2cf4cSNithin Dabilpuram ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 77858e2cf4cSNithin Dabilpuram ethhdr->ether_type = (IS_IP4(sa->flags) ? 77958e2cf4cSNithin Dabilpuram rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) : 78058e2cf4cSNithin Dabilpuram rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)); 78158e2cf4cSNithin Dabilpuram update_mac_addrs(ethhdr, port_id); 78258e2cf4cSNithin Dabilpuram 78386738ebeSSrujana Challa ipsec_event_pre_forward(pkt, port_id); 78486738ebeSSrujana Challa ev_vector_attr_update(vec, pkt); 78586738ebeSSrujana Challa vec->mbufs[j++] = pkt; 7861d5078c6SVolodymyr Fialko break; 7871d5078c6SVolodymyr Fialko default: 7881d5078c6SVolodymyr Fialko RTE_LOG(ERR, IPSEC, "SA type not supported\n"); 7891d5078c6SVolodymyr Fialko free_pkts(&pkt, 1); 7901d5078c6SVolodymyr Fialko break; 7911d5078c6SVolodymyr Fialko } 7921d5078c6SVolodymyr Fialko } 7931d5078c6SVolodymyr Fialko 7941d5078c6SVolodymyr Fialko if (ev_len) { 7951d5078c6SVolodymyr Fialko ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id, 7961d5078c6SVolodymyr Fialko ev_link->event_port_id, events, ev_len); 7971d5078c6SVolodymyr Fialko if (ret < ev_len) { 7981d5078c6SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue events: %i (errno: %i)\n", 7991d5078c6SVolodymyr Fialko ev_len, rte_errno); 8001d5078c6SVolodymyr Fialko free_pkts_from_events(&events[ret], ev_len - ret); 8011d5078c6SVolodymyr Fialko return -rte_errno; 80286738ebeSSrujana Challa } 80386738ebeSSrujana Challa } 80486738ebeSSrujana Challa 80586738ebeSSrujana Challa return j; 80686738ebeSSrujana Challa } 80786738ebeSSrujana Challa 80886738ebeSSrujana Challa static inline void 80986738ebeSSrujana Challa classify_pkt(struct rte_mbuf *pkt, struct ipsec_traffic *t) 81086738ebeSSrujana Challa { 81186738ebeSSrujana Challa enum pkt_type type; 81286738ebeSSrujana Challa uint8_t *nlp; 81386738ebeSSrujana Challa 81486738ebeSSrujana Challa /* Check the packet type */ 81586738ebeSSrujana Challa type = process_ipsec_get_pkt_type(pkt, &nlp); 81686738ebeSSrujana Challa 81786738ebeSSrujana Challa switch (type) { 81886738ebeSSrujana Challa case PKT_TYPE_PLAIN_IPV4: 81986738ebeSSrujana Challa t->ip4.data[t->ip4.num] = nlp; 82086738ebeSSrujana Challa t->ip4.pkts[(t->ip4.num)++] = pkt; 82186738ebeSSrujana Challa break; 82286738ebeSSrujana Challa case PKT_TYPE_PLAIN_IPV6: 82386738ebeSSrujana Challa t->ip6.data[t->ip6.num] = nlp; 82486738ebeSSrujana Challa t->ip6.pkts[(t->ip6.num)++] = pkt; 82586738ebeSSrujana Challa break; 8261d5078c6SVolodymyr Fialko case PKT_TYPE_IPSEC_IPV4: 8271d5078c6SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 8281d5078c6SVolodymyr Fialko ipv4_pkt_l3_len_set(pkt); 8291d5078c6SVolodymyr Fialko t->ipsec.pkts[(t->ipsec.num)++] = pkt; 8301d5078c6SVolodymyr Fialko break; 8311d5078c6SVolodymyr Fialko case PKT_TYPE_IPSEC_IPV6: 8321d5078c6SVolodymyr Fialko rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN); 8331d5078c6SVolodymyr Fialko if (ipv6_pkt_l3_len_set(pkt) != 0) { 8341d5078c6SVolodymyr Fialko free_pkts(&pkt, 1); 8351d5078c6SVolodymyr Fialko return; 8361d5078c6SVolodymyr Fialko } 8371d5078c6SVolodymyr Fialko t->ipsec.pkts[(t->ipsec.num)++] = pkt; 8381d5078c6SVolodymyr Fialko break; 83986738ebeSSrujana Challa default: 8405315b774SNithin Dabilpuram RTE_LOG_DP(DEBUG, IPSEC_ESP, "Unsupported packet type = %d\n", 8415315b774SNithin Dabilpuram type); 84286738ebeSSrujana Challa free_pkts(&pkt, 1); 84386738ebeSSrujana Challa break; 84486738ebeSSrujana Challa } 84586738ebeSSrujana Challa } 84686738ebeSSrujana Challa 84786738ebeSSrujana Challa static inline int 84886738ebeSSrujana Challa process_ipsec_ev_inbound_vector(struct ipsec_ctx *ctx, struct route_table *rt, 8491d5078c6SVolodymyr Fialko struct rte_event_vector *vec, 8501d5078c6SVolodymyr Fialko const struct eh_event_link_info *ev_link) 85186738ebeSSrujana Challa { 85286738ebeSSrujana Challa struct ipsec_traffic t; 85386738ebeSSrujana Challa struct rte_mbuf *pkt; 85486738ebeSSrujana Challa int i; 85586738ebeSSrujana Challa 85686738ebeSSrujana Challa t.ip4.num = 0; 85786738ebeSSrujana Challa t.ip6.num = 0; 85886738ebeSSrujana Challa t.ipsec.num = 0; 85986738ebeSSrujana Challa 86086738ebeSSrujana Challa for (i = 0; i < vec->nb_elem; i++) { 86186738ebeSSrujana Challa /* Get pkt from event */ 86286738ebeSSrujana Challa pkt = vec->mbufs[i]; 863d8d51d4fSRahul Bhansali if (is_ip_reassembly_incomplete(pkt) > 0) { 864d8d51d4fSRahul Bhansali free_reassembly_fail_pkt(pkt); 865d8d51d4fSRahul Bhansali continue; 866d8d51d4fSRahul Bhansali } 86786738ebeSSrujana Challa 86886738ebeSSrujana Challa if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) { 86986738ebeSSrujana Challa if (unlikely(pkt->ol_flags & 87086738ebeSSrujana Challa RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) { 87186738ebeSSrujana Challa RTE_LOG(ERR, IPSEC, 87286738ebeSSrujana Challa "Inbound security offload failed\n"); 87386738ebeSSrujana Challa free_pkts(&pkt, 1); 87486738ebeSSrujana Challa continue; 87586738ebeSSrujana Challa } 87686738ebeSSrujana Challa } 87786738ebeSSrujana Challa 87886738ebeSSrujana Challa classify_pkt(pkt, &t); 87986738ebeSSrujana Challa } 88086738ebeSSrujana Challa 88186738ebeSSrujana Challa check_sp_sa_bulk(ctx->sp4_ctx, ctx->sa_ctx, &t.ip4); 88286738ebeSSrujana Challa check_sp_sa_bulk(ctx->sp6_ctx, ctx->sa_ctx, &t.ip6); 88386738ebeSSrujana Challa 8841d5078c6SVolodymyr Fialko if (t.ipsec.num != 0) 8851d5078c6SVolodymyr Fialko sad_lookup(&ctx->sa_ctx->sad, t.ipsec.pkts, t.ipsec.saptr, t.ipsec.num); 8861d5078c6SVolodymyr Fialko 8871d5078c6SVolodymyr Fialko return ipsec_ev_inbound_route_pkts(vec, rt, &t, ev_link); 88886738ebeSSrujana Challa } 88986738ebeSSrujana Challa 89086738ebeSSrujana Challa static inline int 89186738ebeSSrujana Challa process_ipsec_ev_outbound_vector(struct ipsec_ctx *ctx, struct route_table *rt, 8921d5078c6SVolodymyr Fialko struct rte_event_vector *vec, 8931d5078c6SVolodymyr Fialko const struct eh_event_link_info *ev_link) 89486738ebeSSrujana Challa { 89586738ebeSSrujana Challa struct ipsec_traffic t; 89686738ebeSSrujana Challa struct rte_mbuf *pkt; 89786738ebeSSrujana Challa uint32_t i; 89886738ebeSSrujana Challa 89986738ebeSSrujana Challa t.ip4.num = 0; 90086738ebeSSrujana Challa t.ip6.num = 0; 90186738ebeSSrujana Challa t.ipsec.num = 0; 90286738ebeSSrujana Challa 90386738ebeSSrujana Challa for (i = 0; i < vec->nb_elem; i++) { 90486738ebeSSrujana Challa /* Get pkt from event */ 90586738ebeSSrujana Challa pkt = vec->mbufs[i]; 90686738ebeSSrujana Challa 90786738ebeSSrujana Challa classify_pkt(pkt, &t); 90886738ebeSSrujana Challa 90986738ebeSSrujana Challa /* Provide L2 len for Outbound processing */ 91086738ebeSSrujana Challa pkt->l2_len = RTE_ETHER_HDR_LEN; 91186738ebeSSrujana Challa } 91286738ebeSSrujana Challa 91386738ebeSSrujana Challa check_sp_bulk(ctx->sp4_ctx, &t.ip4, &t.ipsec); 91486738ebeSSrujana Challa check_sp_bulk(ctx->sp6_ctx, &t.ip6, &t.ipsec); 91586738ebeSSrujana Challa 9161d5078c6SVolodymyr Fialko return ipsec_ev_outbound_route_pkts(vec, rt, &t, ctx->sa_ctx, ev_link); 91786738ebeSSrujana Challa } 91886738ebeSSrujana Challa 91986738ebeSSrujana Challa static inline int 92086738ebeSSrujana Challa process_ipsec_ev_drv_mode_outbound_vector(struct rte_event_vector *vec, 92186738ebeSSrujana Challa struct port_drv_mode_data *data) 92286738ebeSSrujana Challa { 92386738ebeSSrujana Challa struct rte_mbuf *pkt; 92486738ebeSSrujana Challa int16_t port_id; 92586738ebeSSrujana Challa uint32_t i; 92686738ebeSSrujana Challa int j = 0; 92786738ebeSSrujana Challa 92886738ebeSSrujana Challa for (i = 0; i < vec->nb_elem; i++) { 92986738ebeSSrujana Challa pkt = vec->mbufs[i]; 93086738ebeSSrujana Challa port_id = pkt->port; 93186738ebeSSrujana Challa 93286738ebeSSrujana Challa if (unlikely(!data[port_id].sess)) { 93386738ebeSSrujana Challa free_pkts(&pkt, 1); 93486738ebeSSrujana Challa continue; 93586738ebeSSrujana Challa } 93686738ebeSSrujana Challa ipsec_event_pre_forward(pkt, port_id); 93786738ebeSSrujana Challa /* Save security session */ 93886738ebeSSrujana Challa rte_security_set_pkt_metadata(data[port_id].ctx, 93986738ebeSSrujana Challa data[port_id].sess, pkt, 94086738ebeSSrujana Challa NULL); 94186738ebeSSrujana Challa 94286738ebeSSrujana Challa /* Mark the packet for Tx security offload */ 94386738ebeSSrujana Challa pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD; 94486738ebeSSrujana Challa 94586738ebeSSrujana Challa /* Provide L2 len for Outbound processing */ 94686738ebeSSrujana Challa pkt->l2_len = RTE_ETHER_HDR_LEN; 94786738ebeSSrujana Challa 94886738ebeSSrujana Challa vec->mbufs[j++] = pkt; 94986738ebeSSrujana Challa } 95086738ebeSSrujana Challa 95186738ebeSSrujana Challa return j; 95286738ebeSSrujana Challa } 95386738ebeSSrujana Challa 954ae279ac9SRahul Bhansali static void 955ae279ac9SRahul Bhansali ipsec_event_vector_free(struct rte_event *ev) 956ae279ac9SRahul Bhansali { 957ae279ac9SRahul Bhansali struct rte_event_vector *vec = ev->vec; 958991b0859SVidya Sagar Velumuri 959991b0859SVidya Sagar Velumuri if (ev->event_type == RTE_EVENT_TYPE_CRYPTODEV_VECTOR) { 960991b0859SVidya Sagar Velumuri struct rte_crypto_op *cop; 961991b0859SVidya Sagar Velumuri int i; 962991b0859SVidya Sagar Velumuri 963991b0859SVidya Sagar Velumuri for (i = 0; i < vec->nb_elem; i++) { 964991b0859SVidya Sagar Velumuri cop = vec->ptrs[i]; 965991b0859SVidya Sagar Velumuri rte_pktmbuf_free(cop->sym->m_src); 966991b0859SVidya Sagar Velumuri } 967991b0859SVidya Sagar Velumuri } else { 968ae279ac9SRahul Bhansali rte_pktmbuf_free_bulk(vec->mbufs + vec->elem_offset, vec->nb_elem); 969991b0859SVidya Sagar Velumuri } 970ae279ac9SRahul Bhansali rte_mempool_put(rte_mempool_from_obj(vec), vec); 971ae279ac9SRahul Bhansali } 972ae279ac9SRahul Bhansali 97386738ebeSSrujana Challa static inline void 97486738ebeSSrujana Challa ipsec_ev_vector_process(struct lcore_conf_ev_tx_int_port_wrkr *lconf, 97586738ebeSSrujana Challa struct eh_event_link_info *links, 97686738ebeSSrujana Challa struct rte_event *ev) 97786738ebeSSrujana Challa { 97886738ebeSSrujana Challa struct rte_event_vector *vec = ev->vec; 97986738ebeSSrujana Challa struct rte_mbuf *pkt; 98086738ebeSSrujana Challa int ret; 98186738ebeSSrujana Challa 98286738ebeSSrujana Challa pkt = vec->mbufs[0]; 98386738ebeSSrujana Challa 98486738ebeSSrujana Challa ev_vector_attr_init(vec); 985f44481efSVolodymyr Fialko core_stats_update_rx(vec->nb_elem); 9861d5078c6SVolodymyr Fialko 98786738ebeSSrujana Challa if (is_unprotected_port(pkt->port)) 98886738ebeSSrujana Challa ret = process_ipsec_ev_inbound_vector(&lconf->inbound, 9891d5078c6SVolodymyr Fialko &lconf->rt, vec, links); 99086738ebeSSrujana Challa else 99186738ebeSSrujana Challa ret = process_ipsec_ev_outbound_vector(&lconf->outbound, 9921d5078c6SVolodymyr Fialko &lconf->rt, vec, links); 99386738ebeSSrujana Challa 9945fb245baSNithin Dabilpuram if (likely(ret > 0)) { 995f44481efSVolodymyr Fialko core_stats_update_tx(vec->nb_elem); 99686738ebeSSrujana Challa vec->nb_elem = ret; 997ae279ac9SRahul Bhansali ret = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id, 998ae279ac9SRahul Bhansali links[0].event_port_id, ev, 1, 0); 999ae279ac9SRahul Bhansali if (unlikely(ret == 0)) 1000ae279ac9SRahul Bhansali ipsec_event_vector_free(ev); 10015fb245baSNithin Dabilpuram } else { 10025fb245baSNithin Dabilpuram rte_mempool_put(rte_mempool_from_obj(vec), vec); 100386738ebeSSrujana Challa } 100486738ebeSSrujana Challa } 100586738ebeSSrujana Challa 100686738ebeSSrujana Challa static inline void 100786738ebeSSrujana Challa ipsec_ev_vector_drv_mode_process(struct eh_event_link_info *links, 100886738ebeSSrujana Challa struct rte_event *ev, 100986738ebeSSrujana Challa struct port_drv_mode_data *data) 101086738ebeSSrujana Challa { 101186738ebeSSrujana Challa struct rte_event_vector *vec = ev->vec; 101286738ebeSSrujana Challa struct rte_mbuf *pkt; 1013ae279ac9SRahul Bhansali uint16_t ret; 101486738ebeSSrujana Challa 101586738ebeSSrujana Challa pkt = vec->mbufs[0]; 1016ae279ac9SRahul Bhansali vec->attr_valid = 1; 1017ae279ac9SRahul Bhansali vec->port = pkt->port; 101886738ebeSSrujana Challa 101986738ebeSSrujana Challa if (!is_unprotected_port(pkt->port)) 102086738ebeSSrujana Challa vec->nb_elem = process_ipsec_ev_drv_mode_outbound_vector(vec, 102186738ebeSSrujana Challa data); 1022ae279ac9SRahul Bhansali if (likely(vec->nb_elem > 0)) { 1023ae279ac9SRahul Bhansali ret = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id, 1024ae279ac9SRahul Bhansali links[0].event_port_id, ev, 1, 0); 1025ae279ac9SRahul Bhansali if (unlikely(ret == 0)) 1026ae279ac9SRahul Bhansali ipsec_event_vector_free(ev); 1027ae279ac9SRahul Bhansali } else 10285fb245baSNithin Dabilpuram rte_mempool_put(rte_mempool_from_obj(vec), vec); 102986738ebeSSrujana Challa } 103086738ebeSSrujana Challa 10316938fc92SVolodymyr Fialko static inline int 10321d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_process_one_pkt( 10331d5078c6SVolodymyr Fialko const struct lcore_conf_ev_tx_int_port_wrkr *lconf, 10341d5078c6SVolodymyr Fialko const struct rte_crypto_op *cop, struct rte_mbuf *pkt) 10356938fc92SVolodymyr Fialko { 10366938fc92SVolodymyr Fialko struct rte_ether_hdr *ethhdr; 10376938fc92SVolodymyr Fialko uint16_t port_id; 10386938fc92SVolodymyr Fialko struct ip *ip; 10396938fc92SVolodymyr Fialko 10401d5078c6SVolodymyr Fialko /* If operation was not successful, free the packet */ 10416938fc92SVolodymyr Fialko if (unlikely(cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) { 10426938fc92SVolodymyr Fialko RTE_LOG_DP(INFO, IPSEC, "Crypto operation failed\n"); 10436938fc92SVolodymyr Fialko free_pkts(&pkt, 1); 10441d5078c6SVolodymyr Fialko return -1; 10456938fc92SVolodymyr Fialko } 10466938fc92SVolodymyr Fialko 10476938fc92SVolodymyr Fialko ip = rte_pktmbuf_mtod(pkt, struct ip *); 10486938fc92SVolodymyr Fialko 10496938fc92SVolodymyr Fialko /* Prepend Ether layer */ 10506938fc92SVolodymyr Fialko ethhdr = (struct rte_ether_hdr *)rte_pktmbuf_prepend(pkt, RTE_ETHER_HDR_LEN); 10516938fc92SVolodymyr Fialko 10526938fc92SVolodymyr Fialko /* Route pkt and update required fields */ 10536938fc92SVolodymyr Fialko if (ip->ip_v == IPVERSION) { 10546938fc92SVolodymyr Fialko pkt->ol_flags |= lconf->outbound.ipv4_offloads; 10556938fc92SVolodymyr Fialko pkt->l3_len = sizeof(struct ip); 10566938fc92SVolodymyr Fialko pkt->l2_len = RTE_ETHER_HDR_LEN; 10576938fc92SVolodymyr Fialko 10586938fc92SVolodymyr Fialko ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 10596938fc92SVolodymyr Fialko 10606938fc92SVolodymyr Fialko port_id = route4_pkt(pkt, lconf->rt.rt4_ctx); 10616938fc92SVolodymyr Fialko } else { 10626938fc92SVolodymyr Fialko pkt->ol_flags |= lconf->outbound.ipv6_offloads; 10636938fc92SVolodymyr Fialko pkt->l3_len = sizeof(struct ip6_hdr); 10646938fc92SVolodymyr Fialko pkt->l2_len = RTE_ETHER_HDR_LEN; 10656938fc92SVolodymyr Fialko 10666938fc92SVolodymyr Fialko ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 10676938fc92SVolodymyr Fialko 10686938fc92SVolodymyr Fialko port_id = route6_pkt(pkt, lconf->rt.rt6_ctx); 10696938fc92SVolodymyr Fialko } 10706938fc92SVolodymyr Fialko 10716938fc92SVolodymyr Fialko if (unlikely(port_id == RTE_MAX_ETHPORTS)) { 10726938fc92SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Cannot route processed packet\n"); 10736938fc92SVolodymyr Fialko free_pkts(&pkt, 1); 10741d5078c6SVolodymyr Fialko return -1; 10756938fc92SVolodymyr Fialko } 10766938fc92SVolodymyr Fialko 10776938fc92SVolodymyr Fialko /* Update Ether with port's MAC addresses */ 10786938fc92SVolodymyr Fialko memcpy(ðhdr->src_addr, ðaddr_tbl[port_id].src, sizeof(struct rte_ether_addr)); 10796938fc92SVolodymyr Fialko memcpy(ðhdr->dst_addr, ðaddr_tbl[port_id].dst, sizeof(struct rte_ether_addr)); 10806938fc92SVolodymyr Fialko 10811d5078c6SVolodymyr Fialko ipsec_event_pre_forward(pkt, port_id); 10821d5078c6SVolodymyr Fialko 10831d5078c6SVolodymyr Fialko return 0; 10841d5078c6SVolodymyr Fialko } 10851d5078c6SVolodymyr Fialko 10861d5078c6SVolodymyr Fialko static inline void 10871d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_vector_process( 10881d5078c6SVolodymyr Fialko const struct lcore_conf_ev_tx_int_port_wrkr *lconf, 10891d5078c6SVolodymyr Fialko const struct eh_event_link_info *links, 10901d5078c6SVolodymyr Fialko struct rte_event *ev) 10911d5078c6SVolodymyr Fialko { 10921d5078c6SVolodymyr Fialko struct rte_event_vector *vec = ev->vec; 10931d5078c6SVolodymyr Fialko const uint16_t nb_events = 1; 10941d5078c6SVolodymyr Fialko struct rte_crypto_op *cop; 10951d5078c6SVolodymyr Fialko struct rte_mbuf *pkt; 10961d5078c6SVolodymyr Fialko uint16_t enqueued; 10971d5078c6SVolodymyr Fialko int i, n = 0; 10981d5078c6SVolodymyr Fialko 10991d5078c6SVolodymyr Fialko ev_vector_attr_init(vec); 11001d5078c6SVolodymyr Fialko /* Transform cop vec into pkt vec */ 11011d5078c6SVolodymyr Fialko for (i = 0; i < vec->nb_elem; i++) { 11021d5078c6SVolodymyr Fialko /* Get pkt data */ 11031d5078c6SVolodymyr Fialko cop = vec->ptrs[i]; 11041d5078c6SVolodymyr Fialko pkt = cop->sym->m_src; 11051d5078c6SVolodymyr Fialko if (ipsec_ev_cryptodev_process_one_pkt(lconf, cop, pkt)) 11061d5078c6SVolodymyr Fialko continue; 11071d5078c6SVolodymyr Fialko 11081d5078c6SVolodymyr Fialko vec->mbufs[n++] = pkt; 11091d5078c6SVolodymyr Fialko ev_vector_attr_update(vec, pkt); 11101d5078c6SVolodymyr Fialko } 11111d5078c6SVolodymyr Fialko 11121d5078c6SVolodymyr Fialko if (n == 0) { 11131d5078c6SVolodymyr Fialko rte_mempool_put(rte_mempool_from_obj(vec), vec); 11141d5078c6SVolodymyr Fialko return; 11151d5078c6SVolodymyr Fialko } 11161d5078c6SVolodymyr Fialko 11171d5078c6SVolodymyr Fialko vec->nb_elem = n; 11181d5078c6SVolodymyr Fialko enqueued = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id, 11191d5078c6SVolodymyr Fialko links[0].event_port_id, ev, nb_events, 0); 11201d5078c6SVolodymyr Fialko if (enqueued != nb_events) { 11211d5078c6SVolodymyr Fialko RTE_LOG_DP(DEBUG, IPSEC, "Failed to enqueue to tx, ret = %u," 11221d5078c6SVolodymyr Fialko " errno = %i\n", enqueued, rte_errno); 11231d5078c6SVolodymyr Fialko free_pkts(vec->mbufs, vec->nb_elem); 11241d5078c6SVolodymyr Fialko rte_mempool_put(rte_mempool_from_obj(vec), vec); 11251d5078c6SVolodymyr Fialko } else { 11261d5078c6SVolodymyr Fialko core_stats_update_tx(n); 11271d5078c6SVolodymyr Fialko } 11281d5078c6SVolodymyr Fialko } 11291d5078c6SVolodymyr Fialko 11301d5078c6SVolodymyr Fialko static inline int 11311d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_process(const struct lcore_conf_ev_tx_int_port_wrkr *lconf, 11321d5078c6SVolodymyr Fialko struct rte_event *ev) 11331d5078c6SVolodymyr Fialko { 11341d5078c6SVolodymyr Fialko struct rte_crypto_op *cop; 11351d5078c6SVolodymyr Fialko struct rte_mbuf *pkt; 11361d5078c6SVolodymyr Fialko 11371d5078c6SVolodymyr Fialko /* Get pkt data */ 11381d5078c6SVolodymyr Fialko cop = ev->event_ptr; 11391d5078c6SVolodymyr Fialko pkt = cop->sym->m_src; 11401d5078c6SVolodymyr Fialko 11411d5078c6SVolodymyr Fialko if (ipsec_ev_cryptodev_process_one_pkt(lconf, cop, pkt)) 11421d5078c6SVolodymyr Fialko return PKT_DROPPED; 11431d5078c6SVolodymyr Fialko 11446938fc92SVolodymyr Fialko /* Update event */ 11456938fc92SVolodymyr Fialko ev->mbuf = pkt; 11466938fc92SVolodymyr Fialko 11476938fc92SVolodymyr Fialko return PKT_FORWARDED; 11486938fc92SVolodymyr Fialko } 11496938fc92SVolodymyr Fialko 11504965dda0SLukasz Bartosik /* 11514965dda0SLukasz Bartosik * Event mode exposes various operating modes depending on the 11524965dda0SLukasz Bartosik * capabilities of the event device and the operating mode 11534965dda0SLukasz Bartosik * selected. 11544965dda0SLukasz Bartosik */ 11554965dda0SLukasz Bartosik 1156aae4f5e0SPavan Nikhilesh static void 1157aae4f5e0SPavan Nikhilesh ipsec_event_port_flush(uint8_t eventdev_id __rte_unused, struct rte_event ev, 1158aae4f5e0SPavan Nikhilesh void *args __rte_unused) 1159aae4f5e0SPavan Nikhilesh { 1160ae279ac9SRahul Bhansali if (ev.event_type & RTE_EVENT_TYPE_VECTOR) 1161ae279ac9SRahul Bhansali ipsec_event_vector_free(&ev); 1162ae279ac9SRahul Bhansali else 1163aae4f5e0SPavan Nikhilesh rte_pktmbuf_free(ev.mbuf); 1164aae4f5e0SPavan Nikhilesh } 1165aae4f5e0SPavan Nikhilesh 11664965dda0SLukasz Bartosik /* Workers registered */ 11679ad50c29SLukasz Bartosik #define IPSEC_EVENTMODE_WORKERS 2 11684965dda0SLukasz Bartosik 1169d8d51d4fSRahul Bhansali static void 1170d8d51d4fSRahul Bhansali ipsec_ip_reassembly_dyn_offset_get(void) 1171d8d51d4fSRahul Bhansali { 1172d8d51d4fSRahul Bhansali /* Retrieve reassembly dynfield offset if available */ 1173d8d51d4fSRahul Bhansali if (ip_reassembly_dynfield_offset < 0) 1174d8d51d4fSRahul Bhansali ip_reassembly_dynfield_offset = rte_mbuf_dynfield_lookup( 1175d8d51d4fSRahul Bhansali RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME, NULL); 1176d8d51d4fSRahul Bhansali 1177d8d51d4fSRahul Bhansali if (ip_reassembly_dynflag == 0) { 1178d8d51d4fSRahul Bhansali int ip_reassembly_dynflag_offset; 1179d8d51d4fSRahul Bhansali ip_reassembly_dynflag_offset = rte_mbuf_dynflag_lookup( 1180d8d51d4fSRahul Bhansali RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME, NULL); 1181d8d51d4fSRahul Bhansali if (ip_reassembly_dynflag_offset >= 0) 1182d8d51d4fSRahul Bhansali ip_reassembly_dynflag = RTE_BIT64(ip_reassembly_dynflag_offset); 1183d8d51d4fSRahul Bhansali } 1184d8d51d4fSRahul Bhansali } 1185d8d51d4fSRahul Bhansali 11864965dda0SLukasz Bartosik /* 11874965dda0SLukasz Bartosik * Event mode worker 11884965dda0SLukasz Bartosik * Operating parameters : non-burst - Tx internal port - driver mode 11894965dda0SLukasz Bartosik */ 11904965dda0SLukasz Bartosik static void 11914965dda0SLukasz Bartosik ipsec_wrkr_non_burst_int_port_drv_mode(struct eh_event_link_info *links, 11924965dda0SLukasz Bartosik uint8_t nb_links) 11934965dda0SLukasz Bartosik { 1194ea28ab88SNithin Dabilpuram struct port_drv_mode_data data[RTE_MAX_ETHPORTS]; 119522bfcba4SPavan Nikhilesh unsigned int nb_rx = 0, nb_tx; 11964965dda0SLukasz Bartosik struct rte_mbuf *pkt; 11974965dda0SLukasz Bartosik struct rte_event ev; 11984965dda0SLukasz Bartosik uint32_t lcore_id; 11994965dda0SLukasz Bartosik int32_t socket_id; 12004965dda0SLukasz Bartosik int16_t port_id; 12014965dda0SLukasz Bartosik 12024965dda0SLukasz Bartosik /* Check if we have links registered for this lcore */ 12034965dda0SLukasz Bartosik if (nb_links == 0) { 12044965dda0SLukasz Bartosik /* No links registered - exit */ 12054965dda0SLukasz Bartosik return; 12064965dda0SLukasz Bartosik } 12074965dda0SLukasz Bartosik 1208ea28ab88SNithin Dabilpuram memset(&data, 0, sizeof(struct port_drv_mode_data)); 1209ea28ab88SNithin Dabilpuram 12104965dda0SLukasz Bartosik /* Get core ID */ 12114965dda0SLukasz Bartosik lcore_id = rte_lcore_id(); 12124965dda0SLukasz Bartosik 12134965dda0SLukasz Bartosik /* Get socket ID */ 12144965dda0SLukasz Bartosik socket_id = rte_lcore_to_socket_id(lcore_id); 12154965dda0SLukasz Bartosik 12164965dda0SLukasz Bartosik /* 12174965dda0SLukasz Bartosik * Prepare security sessions table. In outbound driver mode 12184965dda0SLukasz Bartosik * we always use first session configured for a given port 12194965dda0SLukasz Bartosik */ 1220ea28ab88SNithin Dabilpuram prepare_out_sessions_tbl(socket_ctx[socket_id].sa_out, data, 12214965dda0SLukasz Bartosik RTE_MAX_ETHPORTS); 12224965dda0SLukasz Bartosik 12234965dda0SLukasz Bartosik RTE_LOG(INFO, IPSEC, 12244965dda0SLukasz Bartosik "Launching event mode worker (non-burst - Tx internal port - " 12254965dda0SLukasz Bartosik "driver mode) on lcore %d\n", lcore_id); 12264965dda0SLukasz Bartosik 12274965dda0SLukasz Bartosik /* We have valid links */ 12284965dda0SLukasz Bartosik 12294965dda0SLukasz Bartosik /* Check if it's single link */ 12304965dda0SLukasz Bartosik if (nb_links != 1) { 12314965dda0SLukasz Bartosik RTE_LOG(INFO, IPSEC, 12324965dda0SLukasz Bartosik "Multiple links not supported. Using first link\n"); 12334965dda0SLukasz Bartosik } 12344965dda0SLukasz Bartosik 12354965dda0SLukasz Bartosik RTE_LOG(INFO, IPSEC, " -- lcoreid=%u event_port_id=%u\n", lcore_id, 12364965dda0SLukasz Bartosik links[0].event_port_id); 12374965dda0SLukasz Bartosik while (!force_quit) { 12384965dda0SLukasz Bartosik /* Read packet from event queues */ 12394965dda0SLukasz Bartosik nb_rx = rte_event_dequeue_burst(links[0].eventdev_id, 12404965dda0SLukasz Bartosik links[0].event_port_id, 12414965dda0SLukasz Bartosik &ev, /* events */ 12424965dda0SLukasz Bartosik 1, /* nb_events */ 12434965dda0SLukasz Bartosik 0 /* timeout_ticks */); 12444965dda0SLukasz Bartosik 12454965dda0SLukasz Bartosik if (nb_rx == 0) 12464965dda0SLukasz Bartosik continue; 12474965dda0SLukasz Bartosik 124886738ebeSSrujana Challa switch (ev.event_type) { 124986738ebeSSrujana Challa case RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR: 125086738ebeSSrujana Challa case RTE_EVENT_TYPE_ETHDEV_VECTOR: 125186738ebeSSrujana Challa ipsec_ev_vector_drv_mode_process(links, &ev, data); 125286738ebeSSrujana Challa continue; 125386738ebeSSrujana Challa case RTE_EVENT_TYPE_ETHDEV: 125486738ebeSSrujana Challa break; 125586738ebeSSrujana Challa default: 125686738ebeSSrujana Challa RTE_LOG(ERR, IPSEC, "Invalid event type %u", 125786738ebeSSrujana Challa ev.event_type); 125886738ebeSSrujana Challa continue; 125986738ebeSSrujana Challa } 126086738ebeSSrujana Challa 12614965dda0SLukasz Bartosik pkt = ev.mbuf; 12624965dda0SLukasz Bartosik port_id = pkt->port; 12634965dda0SLukasz Bartosik 12644965dda0SLukasz Bartosik rte_prefetch0(rte_pktmbuf_mtod(pkt, void *)); 12654965dda0SLukasz Bartosik 12664965dda0SLukasz Bartosik /* Process packet */ 12674965dda0SLukasz Bartosik ipsec_event_pre_forward(pkt, port_id); 12684965dda0SLukasz Bartosik 12694965dda0SLukasz Bartosik if (!is_unprotected_port(port_id)) { 12704965dda0SLukasz Bartosik 1271ea28ab88SNithin Dabilpuram if (unlikely(!data[port_id].sess)) { 12724965dda0SLukasz Bartosik rte_pktmbuf_free(pkt); 12734965dda0SLukasz Bartosik continue; 12744965dda0SLukasz Bartosik } 12754965dda0SLukasz Bartosik 12764965dda0SLukasz Bartosik /* Save security session */ 1277ea28ab88SNithin Dabilpuram rte_security_set_pkt_metadata(data[port_id].ctx, 1278ea28ab88SNithin Dabilpuram data[port_id].sess, pkt, 1279ea28ab88SNithin Dabilpuram NULL); 12804965dda0SLukasz Bartosik 12814965dda0SLukasz Bartosik /* Mark the packet for Tx security offload */ 1282daa02b5cSOlivier Matz pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD; 1283ea28ab88SNithin Dabilpuram 1284ea28ab88SNithin Dabilpuram /* Provide L2 len for Outbound processing */ 1285ea28ab88SNithin Dabilpuram pkt->l2_len = RTE_ETHER_HDR_LEN; 12864965dda0SLukasz Bartosik } 12874965dda0SLukasz Bartosik 12884965dda0SLukasz Bartosik /* 12894965dda0SLukasz Bartosik * Since tx internal port is available, events can be 12904965dda0SLukasz Bartosik * directly enqueued to the adapter and it would be 12914965dda0SLukasz Bartosik * internally submitted to the eth device. 12924965dda0SLukasz Bartosik */ 129322bfcba4SPavan Nikhilesh nb_tx = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id, 12944965dda0SLukasz Bartosik links[0].event_port_id, 12954965dda0SLukasz Bartosik &ev, /* events */ 12964965dda0SLukasz Bartosik 1, /* nb_events */ 12974965dda0SLukasz Bartosik 0 /* flags */); 129822bfcba4SPavan Nikhilesh if (!nb_tx) 129922bfcba4SPavan Nikhilesh rte_pktmbuf_free(ev.mbuf); 130022bfcba4SPavan Nikhilesh } 130122bfcba4SPavan Nikhilesh 130222bfcba4SPavan Nikhilesh if (ev.u64) { 130322bfcba4SPavan Nikhilesh ev.op = RTE_EVENT_OP_RELEASE; 130422bfcba4SPavan Nikhilesh rte_event_enqueue_burst(links[0].eventdev_id, 130522bfcba4SPavan Nikhilesh links[0].event_port_id, &ev, 1); 13064965dda0SLukasz Bartosik } 1307aae4f5e0SPavan Nikhilesh 1308aae4f5e0SPavan Nikhilesh rte_event_port_quiesce(links[0].eventdev_id, links[0].event_port_id, 1309aae4f5e0SPavan Nikhilesh ipsec_event_port_flush, NULL); 13104965dda0SLukasz Bartosik } 13114965dda0SLukasz Bartosik 13129ad50c29SLukasz Bartosik /* 13139ad50c29SLukasz Bartosik * Event mode worker 13149ad50c29SLukasz Bartosik * Operating parameters : non-burst - Tx internal port - app mode 13159ad50c29SLukasz Bartosik */ 13169ad50c29SLukasz Bartosik static void 13179ad50c29SLukasz Bartosik ipsec_wrkr_non_burst_int_port_app_mode(struct eh_event_link_info *links, 13189ad50c29SLukasz Bartosik uint8_t nb_links) 13199ad50c29SLukasz Bartosik { 13209ad50c29SLukasz Bartosik struct lcore_conf_ev_tx_int_port_wrkr lconf; 132122bfcba4SPavan Nikhilesh unsigned int nb_rx = 0, nb_tx; 13229ad50c29SLukasz Bartosik struct rte_event ev; 13239ad50c29SLukasz Bartosik uint32_t lcore_id; 13249ad50c29SLukasz Bartosik int32_t socket_id; 13259ad50c29SLukasz Bartosik int ret; 13269ad50c29SLukasz Bartosik 13279ad50c29SLukasz Bartosik /* Check if we have links registered for this lcore */ 13289ad50c29SLukasz Bartosik if (nb_links == 0) { 13299ad50c29SLukasz Bartosik /* No links registered - exit */ 13309ad50c29SLukasz Bartosik return; 13319ad50c29SLukasz Bartosik } 13329ad50c29SLukasz Bartosik 13339ad50c29SLukasz Bartosik /* We have valid links */ 13349ad50c29SLukasz Bartosik 13359ad50c29SLukasz Bartosik /* Get core ID */ 13369ad50c29SLukasz Bartosik lcore_id = rte_lcore_id(); 13379ad50c29SLukasz Bartosik 13389ad50c29SLukasz Bartosik /* Get socket ID */ 13399ad50c29SLukasz Bartosik socket_id = rte_lcore_to_socket_id(lcore_id); 13409ad50c29SLukasz Bartosik 13419ad50c29SLukasz Bartosik /* Save routing table */ 13429ad50c29SLukasz Bartosik lconf.rt.rt4_ctx = socket_ctx[socket_id].rt_ip4; 13439ad50c29SLukasz Bartosik lconf.rt.rt6_ctx = socket_ctx[socket_id].rt_ip6; 13449ad50c29SLukasz Bartosik lconf.inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in; 13459ad50c29SLukasz Bartosik lconf.inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in; 13469ad50c29SLukasz Bartosik lconf.inbound.sa_ctx = socket_ctx[socket_id].sa_in; 1347a8ade121SVolodymyr Fialko lconf.inbound.lcore_id = lcore_id; 13489ad50c29SLukasz Bartosik lconf.outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out; 13499ad50c29SLukasz Bartosik lconf.outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out; 13509ad50c29SLukasz Bartosik lconf.outbound.sa_ctx = socket_ctx[socket_id].sa_out; 1351b1a6b1e9SVolodymyr Fialko lconf.outbound.ipv4_offloads = tx_offloads.ipv4_offloads; 1352b1a6b1e9SVolodymyr Fialko lconf.outbound.ipv6_offloads = tx_offloads.ipv6_offloads; 1353a8ade121SVolodymyr Fialko lconf.outbound.lcore_id = lcore_id; 13549ad50c29SLukasz Bartosik 13559ad50c29SLukasz Bartosik RTE_LOG(INFO, IPSEC, 13569ad50c29SLukasz Bartosik "Launching event mode worker (non-burst - Tx internal port - " 13579ad50c29SLukasz Bartosik "app mode) on lcore %d\n", lcore_id); 13589ad50c29SLukasz Bartosik 13596938fc92SVolodymyr Fialko ret = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz); 13606938fc92SVolodymyr Fialko if (ret != 0) { 13616938fc92SVolodymyr Fialko RTE_LOG(ERR, IPSEC, 13626938fc92SVolodymyr Fialko "SAD cache init on lcore %u, failed with code: %d\n", 13636938fc92SVolodymyr Fialko lcore_id, ret); 13646938fc92SVolodymyr Fialko return; 13656938fc92SVolodymyr Fialko } 13666938fc92SVolodymyr Fialko 13679ad50c29SLukasz Bartosik /* Check if it's single link */ 13689ad50c29SLukasz Bartosik if (nb_links != 1) { 13699ad50c29SLukasz Bartosik RTE_LOG(INFO, IPSEC, 13709ad50c29SLukasz Bartosik "Multiple links not supported. Using first link\n"); 13719ad50c29SLukasz Bartosik } 13729ad50c29SLukasz Bartosik 13739ad50c29SLukasz Bartosik RTE_LOG(INFO, IPSEC, " -- lcoreid=%u event_port_id=%u\n", lcore_id, 13749ad50c29SLukasz Bartosik links[0].event_port_id); 13759ad50c29SLukasz Bartosik 1376d8d51d4fSRahul Bhansali ipsec_ip_reassembly_dyn_offset_get(); 1377d8d51d4fSRahul Bhansali 13789ad50c29SLukasz Bartosik while (!force_quit) { 13799ad50c29SLukasz Bartosik /* Read packet from event queues */ 13809ad50c29SLukasz Bartosik nb_rx = rte_event_dequeue_burst(links[0].eventdev_id, 13819ad50c29SLukasz Bartosik links[0].event_port_id, 13829ad50c29SLukasz Bartosik &ev, /* events */ 13839ad50c29SLukasz Bartosik 1, /* nb_events */ 13849ad50c29SLukasz Bartosik 0 /* timeout_ticks */); 13859ad50c29SLukasz Bartosik 13869ad50c29SLukasz Bartosik if (nb_rx == 0) 13879ad50c29SLukasz Bartosik continue; 13889ad50c29SLukasz Bartosik 138986738ebeSSrujana Challa switch (ev.event_type) { 139086738ebeSSrujana Challa case RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR: 139186738ebeSSrujana Challa case RTE_EVENT_TYPE_ETHDEV_VECTOR: 139286738ebeSSrujana Challa ipsec_ev_vector_process(&lconf, links, &ev); 139386738ebeSSrujana Challa continue; 139486738ebeSSrujana Challa case RTE_EVENT_TYPE_ETHDEV: 1395f44481efSVolodymyr Fialko core_stats_update_rx(1); 13966938fc92SVolodymyr Fialko if (is_unprotected_port(ev.mbuf->port)) 13976938fc92SVolodymyr Fialko ret = process_ipsec_ev_inbound(&lconf.inbound, 13986938fc92SVolodymyr Fialko &lconf.rt, links, &ev); 13996938fc92SVolodymyr Fialko else 14006938fc92SVolodymyr Fialko ret = process_ipsec_ev_outbound(&lconf.outbound, 14016938fc92SVolodymyr Fialko &lconf.rt, links, &ev); 14026938fc92SVolodymyr Fialko if (ret != 1) 14036938fc92SVolodymyr Fialko /* The pkt has been dropped or posted */ 14046938fc92SVolodymyr Fialko continue; 14056938fc92SVolodymyr Fialko break; 14066938fc92SVolodymyr Fialko case RTE_EVENT_TYPE_CRYPTODEV: 14076938fc92SVolodymyr Fialko ret = ipsec_ev_cryptodev_process(&lconf, &ev); 14086938fc92SVolodymyr Fialko if (unlikely(ret != PKT_FORWARDED)) 14096938fc92SVolodymyr Fialko continue; 141086738ebeSSrujana Challa break; 14111d5078c6SVolodymyr Fialko case RTE_EVENT_TYPE_CRYPTODEV_VECTOR: 14121d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_vector_process(&lconf, links, &ev); 14131d5078c6SVolodymyr Fialko continue; 141486738ebeSSrujana Challa default: 14159ad50c29SLukasz Bartosik RTE_LOG(ERR, IPSEC, "Invalid event type %u", 14169ad50c29SLukasz Bartosik ev.event_type); 14179ad50c29SLukasz Bartosik continue; 14189ad50c29SLukasz Bartosik } 14199ad50c29SLukasz Bartosik 1420f44481efSVolodymyr Fialko core_stats_update_tx(1); 14219ad50c29SLukasz Bartosik /* 14229ad50c29SLukasz Bartosik * Since tx internal port is available, events can be 14239ad50c29SLukasz Bartosik * directly enqueued to the adapter and it would be 14249ad50c29SLukasz Bartosik * internally submitted to the eth device. 14259ad50c29SLukasz Bartosik */ 142622bfcba4SPavan Nikhilesh nb_tx = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id, 14279ad50c29SLukasz Bartosik links[0].event_port_id, 14289ad50c29SLukasz Bartosik &ev, /* events */ 14299ad50c29SLukasz Bartosik 1, /* nb_events */ 14309ad50c29SLukasz Bartosik 0 /* flags */); 143122bfcba4SPavan Nikhilesh if (!nb_tx) 143222bfcba4SPavan Nikhilesh rte_pktmbuf_free(ev.mbuf); 143322bfcba4SPavan Nikhilesh } 143422bfcba4SPavan Nikhilesh 143522bfcba4SPavan Nikhilesh if (ev.u64) { 143622bfcba4SPavan Nikhilesh ev.op = RTE_EVENT_OP_RELEASE; 143722bfcba4SPavan Nikhilesh rte_event_enqueue_burst(links[0].eventdev_id, 143822bfcba4SPavan Nikhilesh links[0].event_port_id, &ev, 1); 14399ad50c29SLukasz Bartosik } 1440aae4f5e0SPavan Nikhilesh 1441aae4f5e0SPavan Nikhilesh rte_event_port_quiesce(links[0].eventdev_id, links[0].event_port_id, 1442aae4f5e0SPavan Nikhilesh ipsec_event_port_flush, NULL); 14439ad50c29SLukasz Bartosik } 14449ad50c29SLukasz Bartosik 14454965dda0SLukasz Bartosik static uint8_t 14464965dda0SLukasz Bartosik ipsec_eventmode_populate_wrkr_params(struct eh_app_worker_params *wrkrs) 14474965dda0SLukasz Bartosik { 14484965dda0SLukasz Bartosik struct eh_app_worker_params *wrkr; 14494965dda0SLukasz Bartosik uint8_t nb_wrkr_param = 0; 14504965dda0SLukasz Bartosik 14514965dda0SLukasz Bartosik /* Save workers */ 14524965dda0SLukasz Bartosik wrkr = wrkrs; 14534965dda0SLukasz Bartosik 14544965dda0SLukasz Bartosik /* Non-burst - Tx internal port - driver mode */ 14554965dda0SLukasz Bartosik wrkr->cap.burst = EH_RX_TYPE_NON_BURST; 14564965dda0SLukasz Bartosik wrkr->cap.tx_internal_port = EH_TX_TYPE_INTERNAL_PORT; 14574965dda0SLukasz Bartosik wrkr->cap.ipsec_mode = EH_IPSEC_MODE_TYPE_DRIVER; 14584965dda0SLukasz Bartosik wrkr->worker_thread = ipsec_wrkr_non_burst_int_port_drv_mode; 14594965dda0SLukasz Bartosik wrkr++; 14609ad50c29SLukasz Bartosik nb_wrkr_param++; 14619ad50c29SLukasz Bartosik 14629ad50c29SLukasz Bartosik /* Non-burst - Tx internal port - app mode */ 14639ad50c29SLukasz Bartosik wrkr->cap.burst = EH_RX_TYPE_NON_BURST; 14649ad50c29SLukasz Bartosik wrkr->cap.tx_internal_port = EH_TX_TYPE_INTERNAL_PORT; 14659ad50c29SLukasz Bartosik wrkr->cap.ipsec_mode = EH_IPSEC_MODE_TYPE_APP; 14669ad50c29SLukasz Bartosik wrkr->worker_thread = ipsec_wrkr_non_burst_int_port_app_mode; 14679ad50c29SLukasz Bartosik nb_wrkr_param++; 14684965dda0SLukasz Bartosik 14694965dda0SLukasz Bartosik return nb_wrkr_param; 14704965dda0SLukasz Bartosik } 14714965dda0SLukasz Bartosik 14724965dda0SLukasz Bartosik static void 14734965dda0SLukasz Bartosik ipsec_eventmode_worker(struct eh_conf *conf) 14744965dda0SLukasz Bartosik { 14754965dda0SLukasz Bartosik struct eh_app_worker_params ipsec_wrkr[IPSEC_EVENTMODE_WORKERS] = { 14764965dda0SLukasz Bartosik {{{0} }, NULL } }; 14774965dda0SLukasz Bartosik uint8_t nb_wrkr_param; 14784965dda0SLukasz Bartosik 14794965dda0SLukasz Bartosik /* Populate l2fwd_wrkr params */ 14804965dda0SLukasz Bartosik nb_wrkr_param = ipsec_eventmode_populate_wrkr_params(ipsec_wrkr); 14814965dda0SLukasz Bartosik 14824965dda0SLukasz Bartosik /* 14834965dda0SLukasz Bartosik * Launch correct worker after checking 14844965dda0SLukasz Bartosik * the event device's capabilities. 14854965dda0SLukasz Bartosik */ 14864965dda0SLukasz Bartosik eh_launch_worker(conf, ipsec_wrkr, nb_wrkr_param); 14874965dda0SLukasz Bartosik } 14884965dda0SLukasz Bartosik 14890d76e22dSNithin Dabilpuram static __rte_always_inline void 14900d76e22dSNithin Dabilpuram outb_inl_pro_spd_process(struct sp_ctx *sp, 14910d76e22dSNithin Dabilpuram struct sa_ctx *sa_ctx, 14920d76e22dSNithin Dabilpuram struct traffic_type *ip, 14930d76e22dSNithin Dabilpuram struct traffic_type *match, 14940d76e22dSNithin Dabilpuram struct traffic_type *mismatch, 14950d76e22dSNithin Dabilpuram bool match_flag, 14960d76e22dSNithin Dabilpuram struct ipsec_spd_stats *stats) 14970d76e22dSNithin Dabilpuram { 14980d76e22dSNithin Dabilpuram uint32_t prev_sa_idx = UINT32_MAX; 14990d76e22dSNithin Dabilpuram struct rte_mbuf *ipsec[MAX_PKT_BURST]; 15000d76e22dSNithin Dabilpuram struct rte_ipsec_session *ips; 15010d76e22dSNithin Dabilpuram uint32_t i, j, j_mis, sa_idx; 15020d76e22dSNithin Dabilpuram struct ipsec_sa *sa = NULL; 15030d76e22dSNithin Dabilpuram uint32_t ipsec_num = 0; 15040d76e22dSNithin Dabilpuram struct rte_mbuf *m; 15050d76e22dSNithin Dabilpuram uint64_t satp; 15060d76e22dSNithin Dabilpuram 15070d76e22dSNithin Dabilpuram if (ip->num == 0 || sp == NULL) 15080d76e22dSNithin Dabilpuram return; 15090d76e22dSNithin Dabilpuram 15100d76e22dSNithin Dabilpuram rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, 15110d76e22dSNithin Dabilpuram ip->num, DEFAULT_MAX_CATEGORIES); 15120d76e22dSNithin Dabilpuram 15130d76e22dSNithin Dabilpuram j = match->num; 15140d76e22dSNithin Dabilpuram j_mis = mismatch->num; 15150d76e22dSNithin Dabilpuram 15160d76e22dSNithin Dabilpuram for (i = 0; i < ip->num; i++) { 15170d76e22dSNithin Dabilpuram m = ip->pkts[i]; 15180d76e22dSNithin Dabilpuram sa_idx = ip->res[i] - 1; 15190d76e22dSNithin Dabilpuram 15200d76e22dSNithin Dabilpuram if (unlikely(ip->res[i] == DISCARD)) { 15210d76e22dSNithin Dabilpuram free_pkts(&m, 1); 15220d76e22dSNithin Dabilpuram 15230d76e22dSNithin Dabilpuram stats->discard++; 15240d76e22dSNithin Dabilpuram } else if (unlikely(ip->res[i] == BYPASS)) { 15250d76e22dSNithin Dabilpuram match->pkts[j++] = m; 15260d76e22dSNithin Dabilpuram 15270d76e22dSNithin Dabilpuram stats->bypass++; 15280d76e22dSNithin Dabilpuram } else { 15290d76e22dSNithin Dabilpuram if (prev_sa_idx == UINT32_MAX) { 15300d76e22dSNithin Dabilpuram prev_sa_idx = sa_idx; 15310d76e22dSNithin Dabilpuram sa = &sa_ctx->sa[sa_idx]; 15320d76e22dSNithin Dabilpuram ips = ipsec_get_primary_session(sa); 15330d76e22dSNithin Dabilpuram satp = rte_ipsec_sa_type(ips->sa); 15340d76e22dSNithin Dabilpuram } 15350d76e22dSNithin Dabilpuram 15360d76e22dSNithin Dabilpuram if (sa_idx != prev_sa_idx) { 15370d76e22dSNithin Dabilpuram prep_process_group(sa, ipsec, ipsec_num); 15380d76e22dSNithin Dabilpuram 15390d76e22dSNithin Dabilpuram /* Prepare packets for outbound */ 15400d76e22dSNithin Dabilpuram rte_ipsec_pkt_process(ips, ipsec, ipsec_num); 15410d76e22dSNithin Dabilpuram 15420d76e22dSNithin Dabilpuram /* Copy to current tr or a different tr */ 15430d76e22dSNithin Dabilpuram if (SATP_OUT_IPV4(satp) == match_flag) { 15440d76e22dSNithin Dabilpuram memcpy(&match->pkts[j], ipsec, 15450d76e22dSNithin Dabilpuram ipsec_num * sizeof(void *)); 15460d76e22dSNithin Dabilpuram j += ipsec_num; 15470d76e22dSNithin Dabilpuram } else { 15480d76e22dSNithin Dabilpuram memcpy(&mismatch->pkts[j_mis], ipsec, 15490d76e22dSNithin Dabilpuram ipsec_num * sizeof(void *)); 15500d76e22dSNithin Dabilpuram j_mis += ipsec_num; 15510d76e22dSNithin Dabilpuram } 15520d76e22dSNithin Dabilpuram 15530d76e22dSNithin Dabilpuram /* Update to new SA */ 15540d76e22dSNithin Dabilpuram sa = &sa_ctx->sa[sa_idx]; 15550d76e22dSNithin Dabilpuram ips = ipsec_get_primary_session(sa); 15560d76e22dSNithin Dabilpuram satp = rte_ipsec_sa_type(ips->sa); 15570d76e22dSNithin Dabilpuram ipsec_num = 0; 15580d76e22dSNithin Dabilpuram } 15590d76e22dSNithin Dabilpuram 15600d76e22dSNithin Dabilpuram ipsec[ipsec_num++] = m; 15610d76e22dSNithin Dabilpuram stats->protect++; 15620d76e22dSNithin Dabilpuram } 15630d76e22dSNithin Dabilpuram } 15640d76e22dSNithin Dabilpuram 15650d76e22dSNithin Dabilpuram if (ipsec_num) { 15660d76e22dSNithin Dabilpuram prep_process_group(sa, ipsec, ipsec_num); 15670d76e22dSNithin Dabilpuram 15680d76e22dSNithin Dabilpuram /* Prepare pacekts for outbound */ 15690d76e22dSNithin Dabilpuram rte_ipsec_pkt_process(ips, ipsec, ipsec_num); 15700d76e22dSNithin Dabilpuram 15710d76e22dSNithin Dabilpuram /* Copy to current tr or a different tr */ 15720d76e22dSNithin Dabilpuram if (SATP_OUT_IPV4(satp) == match_flag) { 15730d76e22dSNithin Dabilpuram memcpy(&match->pkts[j], ipsec, 15740d76e22dSNithin Dabilpuram ipsec_num * sizeof(void *)); 15750d76e22dSNithin Dabilpuram j += ipsec_num; 15760d76e22dSNithin Dabilpuram } else { 15770d76e22dSNithin Dabilpuram memcpy(&mismatch->pkts[j_mis], ipsec, 15780d76e22dSNithin Dabilpuram ipsec_num * sizeof(void *)); 15790d76e22dSNithin Dabilpuram j_mis += ipsec_num; 15800d76e22dSNithin Dabilpuram } 15810d76e22dSNithin Dabilpuram } 15820d76e22dSNithin Dabilpuram match->num = j; 15830d76e22dSNithin Dabilpuram mismatch->num = j_mis; 15840d76e22dSNithin Dabilpuram } 15850d76e22dSNithin Dabilpuram 15860d76e22dSNithin Dabilpuram /* Poll mode worker when all SA's are of type inline protocol */ 15870d76e22dSNithin Dabilpuram void 15880d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_inl_pr(void) 15890d76e22dSNithin Dabilpuram { 15900d76e22dSNithin Dabilpuram const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) 15910d76e22dSNithin Dabilpuram / US_PER_S * BURST_TX_DRAIN_US; 15920d76e22dSNithin Dabilpuram struct sp_ctx *sp4_in, *sp6_in, *sp4_out, *sp6_out; 15930d76e22dSNithin Dabilpuram struct rte_mbuf *pkts[MAX_PKT_BURST]; 15940d76e22dSNithin Dabilpuram uint64_t prev_tsc, diff_tsc, cur_tsc; 15950d76e22dSNithin Dabilpuram struct ipsec_core_statistics *stats; 15960d76e22dSNithin Dabilpuram struct rt_ctx *rt4_ctx, *rt6_ctx; 15970d76e22dSNithin Dabilpuram struct sa_ctx *sa_in, *sa_out; 15980d76e22dSNithin Dabilpuram struct traffic_type ip4, ip6; 15990d76e22dSNithin Dabilpuram struct lcore_rx_queue *rxql; 16000d76e22dSNithin Dabilpuram struct rte_mbuf **v4, **v6; 16010d76e22dSNithin Dabilpuram struct ipsec_traffic trf; 16020d76e22dSNithin Dabilpuram struct lcore_conf *qconf; 16030d76e22dSNithin Dabilpuram uint16_t v4_num, v6_num; 16040d76e22dSNithin Dabilpuram int32_t socket_id; 16050d76e22dSNithin Dabilpuram uint32_t lcore_id; 16060d76e22dSNithin Dabilpuram int32_t i, nb_rx; 1607b23c5bd7SSivaprasad Tummala uint16_t portid, queueid; 16080d76e22dSNithin Dabilpuram 16090d76e22dSNithin Dabilpuram prev_tsc = 0; 16100d76e22dSNithin Dabilpuram lcore_id = rte_lcore_id(); 16110d76e22dSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 16120d76e22dSNithin Dabilpuram rxql = qconf->rx_queue_list; 16130d76e22dSNithin Dabilpuram socket_id = rte_lcore_to_socket_id(lcore_id); 16140d76e22dSNithin Dabilpuram stats = &core_statistics[lcore_id]; 16150d76e22dSNithin Dabilpuram 16160d76e22dSNithin Dabilpuram rt4_ctx = socket_ctx[socket_id].rt_ip4; 16170d76e22dSNithin Dabilpuram rt6_ctx = socket_ctx[socket_id].rt_ip6; 16180d76e22dSNithin Dabilpuram 16190d76e22dSNithin Dabilpuram sp4_in = socket_ctx[socket_id].sp_ip4_in; 16200d76e22dSNithin Dabilpuram sp6_in = socket_ctx[socket_id].sp_ip6_in; 16210d76e22dSNithin Dabilpuram sa_in = socket_ctx[socket_id].sa_in; 16220d76e22dSNithin Dabilpuram 16230d76e22dSNithin Dabilpuram sp4_out = socket_ctx[socket_id].sp_ip4_out; 16240d76e22dSNithin Dabilpuram sp6_out = socket_ctx[socket_id].sp_ip6_out; 16250d76e22dSNithin Dabilpuram sa_out = socket_ctx[socket_id].sa_out; 16260d76e22dSNithin Dabilpuram 16270d76e22dSNithin Dabilpuram qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir; 16280d76e22dSNithin Dabilpuram 16290d76e22dSNithin Dabilpuram if (qconf->nb_rx_queue == 0) { 16300d76e22dSNithin Dabilpuram RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n", 16310d76e22dSNithin Dabilpuram lcore_id); 16320d76e22dSNithin Dabilpuram return; 16330d76e22dSNithin Dabilpuram } 16340d76e22dSNithin Dabilpuram 16350d76e22dSNithin Dabilpuram RTE_LOG(INFO, IPSEC, "entering main loop on lcore %u\n", lcore_id); 16360d76e22dSNithin Dabilpuram 16370d76e22dSNithin Dabilpuram for (i = 0; i < qconf->nb_rx_queue; i++) { 16380d76e22dSNithin Dabilpuram portid = rxql[i].port_id; 16390d76e22dSNithin Dabilpuram queueid = rxql[i].queue_id; 16400d76e22dSNithin Dabilpuram RTE_LOG(INFO, IPSEC, 1641b23c5bd7SSivaprasad Tummala " -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n", 16420d76e22dSNithin Dabilpuram lcore_id, portid, queueid); 16430d76e22dSNithin Dabilpuram } 16440d76e22dSNithin Dabilpuram 1645d8d51d4fSRahul Bhansali ipsec_ip_reassembly_dyn_offset_get(); 1646d8d51d4fSRahul Bhansali 16470d76e22dSNithin Dabilpuram while (!force_quit) { 16480d76e22dSNithin Dabilpuram cur_tsc = rte_rdtsc(); 16490d76e22dSNithin Dabilpuram 16500d76e22dSNithin Dabilpuram /* TX queue buffer drain */ 16510d76e22dSNithin Dabilpuram diff_tsc = cur_tsc - prev_tsc; 16520d76e22dSNithin Dabilpuram 16530d76e22dSNithin Dabilpuram if (unlikely(diff_tsc > drain_tsc)) { 16540d76e22dSNithin Dabilpuram drain_tx_buffers(qconf); 16550d76e22dSNithin Dabilpuram prev_tsc = cur_tsc; 16560d76e22dSNithin Dabilpuram } 16570d76e22dSNithin Dabilpuram 16580d76e22dSNithin Dabilpuram for (i = 0; i < qconf->nb_rx_queue; ++i) { 16590d76e22dSNithin Dabilpuram /* Read packets from RX queues */ 16600d76e22dSNithin Dabilpuram portid = rxql[i].port_id; 16610d76e22dSNithin Dabilpuram queueid = rxql[i].queue_id; 16620d76e22dSNithin Dabilpuram nb_rx = rte_eth_rx_burst(portid, queueid, 16630d76e22dSNithin Dabilpuram pkts, MAX_PKT_BURST); 16640d76e22dSNithin Dabilpuram 16650d76e22dSNithin Dabilpuram if (nb_rx <= 0) 16660d76e22dSNithin Dabilpuram continue; 16670d76e22dSNithin Dabilpuram 16680d76e22dSNithin Dabilpuram core_stats_update_rx(nb_rx); 16690d76e22dSNithin Dabilpuram 16700d76e22dSNithin Dabilpuram prepare_traffic(rxql[i].sec_ctx, pkts, &trf, nb_rx); 16710d76e22dSNithin Dabilpuram 16720d76e22dSNithin Dabilpuram /* Drop any IPsec traffic */ 16730d76e22dSNithin Dabilpuram free_pkts(trf.ipsec.pkts, trf.ipsec.num); 16740d76e22dSNithin Dabilpuram 16750d76e22dSNithin Dabilpuram if (is_unprotected_port(portid)) { 16760d76e22dSNithin Dabilpuram inbound_sp_sa(sp4_in, sa_in, &trf.ip4, 16770d76e22dSNithin Dabilpuram trf.ip4.num, 16780d76e22dSNithin Dabilpuram &stats->inbound.spd4); 16790d76e22dSNithin Dabilpuram 16800d76e22dSNithin Dabilpuram inbound_sp_sa(sp6_in, sa_in, &trf.ip6, 16810d76e22dSNithin Dabilpuram trf.ip6.num, 16820d76e22dSNithin Dabilpuram &stats->inbound.spd6); 16830d76e22dSNithin Dabilpuram 16840d76e22dSNithin Dabilpuram v4 = trf.ip4.pkts; 16850d76e22dSNithin Dabilpuram v4_num = trf.ip4.num; 16860d76e22dSNithin Dabilpuram v6 = trf.ip6.pkts; 16870d76e22dSNithin Dabilpuram v6_num = trf.ip6.num; 16880d76e22dSNithin Dabilpuram } else { 16890d76e22dSNithin Dabilpuram ip4.num = 0; 16900d76e22dSNithin Dabilpuram ip6.num = 0; 16910d76e22dSNithin Dabilpuram 16920d76e22dSNithin Dabilpuram outb_inl_pro_spd_process(sp4_out, sa_out, 16930d76e22dSNithin Dabilpuram &trf.ip4, &ip4, &ip6, 16940d76e22dSNithin Dabilpuram true, 16950d76e22dSNithin Dabilpuram &stats->outbound.spd4); 16960d76e22dSNithin Dabilpuram 16970d76e22dSNithin Dabilpuram outb_inl_pro_spd_process(sp6_out, sa_out, 16980d76e22dSNithin Dabilpuram &trf.ip6, &ip6, &ip4, 16990d76e22dSNithin Dabilpuram false, 17000d76e22dSNithin Dabilpuram &stats->outbound.spd6); 17010d76e22dSNithin Dabilpuram v4 = ip4.pkts; 17020d76e22dSNithin Dabilpuram v4_num = ip4.num; 17030d76e22dSNithin Dabilpuram v6 = ip6.pkts; 17040d76e22dSNithin Dabilpuram v6_num = ip6.num; 17050d76e22dSNithin Dabilpuram } 17060d76e22dSNithin Dabilpuram 17076eb3ba03SRahul Bhansali #if defined __ARM_NEON 17086eb3ba03SRahul Bhansali route4_pkts_neon(rt4_ctx, v4, v4_num, 0, false); 17096eb3ba03SRahul Bhansali route6_pkts_neon(rt6_ctx, v6, v6_num); 17106eb3ba03SRahul Bhansali #else 17110d76e22dSNithin Dabilpuram route4_pkts(rt4_ctx, v4, v4_num, 0, false); 17120d76e22dSNithin Dabilpuram route6_pkts(rt6_ctx, v6, v6_num); 17136eb3ba03SRahul Bhansali #endif 17140d76e22dSNithin Dabilpuram } 17150d76e22dSNithin Dabilpuram } 17160d76e22dSNithin Dabilpuram } 17170d76e22dSNithin Dabilpuram 17180d76e22dSNithin Dabilpuram /* Poll mode worker when all SA's are of type inline protocol 17190d76e22dSNithin Dabilpuram * and single sa mode is enabled. 17200d76e22dSNithin Dabilpuram */ 17210d76e22dSNithin Dabilpuram void 17220d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_inl_pr_ss(void) 17230d76e22dSNithin Dabilpuram { 17240d76e22dSNithin Dabilpuram const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) 17250d76e22dSNithin Dabilpuram / US_PER_S * BURST_TX_DRAIN_US; 17260d76e22dSNithin Dabilpuram uint16_t sa_out_portid = 0, sa_out_proto = 0; 17270d76e22dSNithin Dabilpuram struct rte_mbuf *pkts[MAX_PKT_BURST], *pkt; 17280d76e22dSNithin Dabilpuram uint64_t prev_tsc, diff_tsc, cur_tsc; 17290d76e22dSNithin Dabilpuram struct rte_ipsec_session *ips = NULL; 17300d76e22dSNithin Dabilpuram struct lcore_rx_queue *rxql; 17310d76e22dSNithin Dabilpuram struct ipsec_sa *sa = NULL; 17320d76e22dSNithin Dabilpuram struct lcore_conf *qconf; 17330d76e22dSNithin Dabilpuram struct sa_ctx *sa_out; 17340d76e22dSNithin Dabilpuram uint32_t i, nb_rx, j; 17350d76e22dSNithin Dabilpuram int32_t socket_id; 17360d76e22dSNithin Dabilpuram uint32_t lcore_id; 1737b23c5bd7SSivaprasad Tummala uint16_t portid, queueid; 17380d76e22dSNithin Dabilpuram 17390d76e22dSNithin Dabilpuram prev_tsc = 0; 17400d76e22dSNithin Dabilpuram lcore_id = rte_lcore_id(); 17410d76e22dSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 17420d76e22dSNithin Dabilpuram rxql = qconf->rx_queue_list; 17430d76e22dSNithin Dabilpuram socket_id = rte_lcore_to_socket_id(lcore_id); 17440d76e22dSNithin Dabilpuram 17450d76e22dSNithin Dabilpuram /* Get SA info */ 17460d76e22dSNithin Dabilpuram sa_out = socket_ctx[socket_id].sa_out; 17470d76e22dSNithin Dabilpuram if (sa_out && single_sa_idx < sa_out->nb_sa) { 17480d76e22dSNithin Dabilpuram sa = &sa_out->sa[single_sa_idx]; 17490d76e22dSNithin Dabilpuram ips = ipsec_get_primary_session(sa); 17500d76e22dSNithin Dabilpuram sa_out_portid = sa->portid; 17510d76e22dSNithin Dabilpuram if (sa->flags & IP6_TUNNEL) 17520d76e22dSNithin Dabilpuram sa_out_proto = IPPROTO_IPV6; 17530d76e22dSNithin Dabilpuram else 17540d76e22dSNithin Dabilpuram sa_out_proto = IPPROTO_IP; 17550d76e22dSNithin Dabilpuram } 17560d76e22dSNithin Dabilpuram 17570d76e22dSNithin Dabilpuram qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir; 17580d76e22dSNithin Dabilpuram 17590d76e22dSNithin Dabilpuram if (qconf->nb_rx_queue == 0) { 17600d76e22dSNithin Dabilpuram RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n", 17610d76e22dSNithin Dabilpuram lcore_id); 17620d76e22dSNithin Dabilpuram return; 17630d76e22dSNithin Dabilpuram } 17640d76e22dSNithin Dabilpuram 17650d76e22dSNithin Dabilpuram RTE_LOG(INFO, IPSEC, "entering main loop on lcore %u\n", lcore_id); 17660d76e22dSNithin Dabilpuram 17670d76e22dSNithin Dabilpuram for (i = 0; i < qconf->nb_rx_queue; i++) { 17680d76e22dSNithin Dabilpuram portid = rxql[i].port_id; 17690d76e22dSNithin Dabilpuram queueid = rxql[i].queue_id; 17700d76e22dSNithin Dabilpuram RTE_LOG(INFO, IPSEC, 1771b23c5bd7SSivaprasad Tummala " -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n", 17720d76e22dSNithin Dabilpuram lcore_id, portid, queueid); 17730d76e22dSNithin Dabilpuram } 17740d76e22dSNithin Dabilpuram 17750d76e22dSNithin Dabilpuram while (!force_quit) { 17760d76e22dSNithin Dabilpuram cur_tsc = rte_rdtsc(); 17770d76e22dSNithin Dabilpuram 17780d76e22dSNithin Dabilpuram /* TX queue buffer drain */ 17790d76e22dSNithin Dabilpuram diff_tsc = cur_tsc - prev_tsc; 17800d76e22dSNithin Dabilpuram 17810d76e22dSNithin Dabilpuram if (unlikely(diff_tsc > drain_tsc)) { 17820d76e22dSNithin Dabilpuram drain_tx_buffers(qconf); 17830d76e22dSNithin Dabilpuram prev_tsc = cur_tsc; 17840d76e22dSNithin Dabilpuram } 17850d76e22dSNithin Dabilpuram 17860d76e22dSNithin Dabilpuram for (i = 0; i < qconf->nb_rx_queue; ++i) { 17870d76e22dSNithin Dabilpuram /* Read packets from RX queues */ 17880d76e22dSNithin Dabilpuram portid = rxql[i].port_id; 17890d76e22dSNithin Dabilpuram queueid = rxql[i].queue_id; 17900d76e22dSNithin Dabilpuram nb_rx = rte_eth_rx_burst(portid, queueid, 17910d76e22dSNithin Dabilpuram pkts, MAX_PKT_BURST); 17920d76e22dSNithin Dabilpuram 17930d76e22dSNithin Dabilpuram if (nb_rx <= 0) 17940d76e22dSNithin Dabilpuram continue; 17950d76e22dSNithin Dabilpuram 17960d76e22dSNithin Dabilpuram core_stats_update_rx(nb_rx); 17970d76e22dSNithin Dabilpuram 17980d76e22dSNithin Dabilpuram if (is_unprotected_port(portid)) { 17990d76e22dSNithin Dabilpuram /* Nothing much to do for inbound inline 18000d76e22dSNithin Dabilpuram * decrypted traffic. 18010d76e22dSNithin Dabilpuram */ 18020d76e22dSNithin Dabilpuram for (j = 0; j < nb_rx; j++) { 18030d76e22dSNithin Dabilpuram uint32_t ptype, proto; 18040d76e22dSNithin Dabilpuram 18050d76e22dSNithin Dabilpuram pkt = pkts[j]; 18060d76e22dSNithin Dabilpuram ptype = pkt->packet_type & 18070d76e22dSNithin Dabilpuram RTE_PTYPE_L3_MASK; 18080d76e22dSNithin Dabilpuram if (ptype == RTE_PTYPE_L3_IPV4) 18090d76e22dSNithin Dabilpuram proto = IPPROTO_IP; 18100d76e22dSNithin Dabilpuram else 18110d76e22dSNithin Dabilpuram proto = IPPROTO_IPV6; 18120d76e22dSNithin Dabilpuram 18130d76e22dSNithin Dabilpuram send_single_packet(pkt, portid, proto); 18140d76e22dSNithin Dabilpuram } 18150d76e22dSNithin Dabilpuram 18160d76e22dSNithin Dabilpuram continue; 18170d76e22dSNithin Dabilpuram } 18180d76e22dSNithin Dabilpuram 18190d76e22dSNithin Dabilpuram /* Free packets if there are no outbound sessions */ 18200d76e22dSNithin Dabilpuram if (unlikely(!ips)) { 18210d76e22dSNithin Dabilpuram rte_pktmbuf_free_bulk(pkts, nb_rx); 18220d76e22dSNithin Dabilpuram continue; 18230d76e22dSNithin Dabilpuram } 18240d76e22dSNithin Dabilpuram 18250d76e22dSNithin Dabilpuram rte_ipsec_pkt_process(ips, pkts, nb_rx); 18260d76e22dSNithin Dabilpuram 18270d76e22dSNithin Dabilpuram /* Send pkts out */ 18280d76e22dSNithin Dabilpuram for (j = 0; j < nb_rx; j++) { 18290d76e22dSNithin Dabilpuram pkt = pkts[j]; 18300d76e22dSNithin Dabilpuram 18310d76e22dSNithin Dabilpuram pkt->l2_len = RTE_ETHER_HDR_LEN; 18320d76e22dSNithin Dabilpuram send_single_packet(pkt, sa_out_portid, 18330d76e22dSNithin Dabilpuram sa_out_proto); 18340d76e22dSNithin Dabilpuram } 18350d76e22dSNithin Dabilpuram } 18360d76e22dSNithin Dabilpuram } 18370d76e22dSNithin Dabilpuram } 18380d76e22dSNithin Dabilpuram 18390d76e22dSNithin Dabilpuram static void 18400d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_launch(void) 18410d76e22dSNithin Dabilpuram { 18420d76e22dSNithin Dabilpuram static ipsec_worker_fn_t poll_mode_wrkrs[MAX_F] = { 18430d76e22dSNithin Dabilpuram [INL_PR_F] = ipsec_poll_mode_wrkr_inl_pr, 18440d76e22dSNithin Dabilpuram [INL_PR_F | SS_F] = ipsec_poll_mode_wrkr_inl_pr_ss, 18450d76e22dSNithin Dabilpuram }; 18460d76e22dSNithin Dabilpuram ipsec_worker_fn_t fn; 18470d76e22dSNithin Dabilpuram 18480d76e22dSNithin Dabilpuram if (!app_sa_prm.enable) { 18490d76e22dSNithin Dabilpuram fn = ipsec_poll_mode_worker; 18500d76e22dSNithin Dabilpuram } else { 18510d76e22dSNithin Dabilpuram fn = poll_mode_wrkrs[wrkr_flags]; 18520d76e22dSNithin Dabilpuram 18530d76e22dSNithin Dabilpuram /* Always default to all mode worker */ 18540d76e22dSNithin Dabilpuram if (!fn) 18550d76e22dSNithin Dabilpuram fn = ipsec_poll_mode_worker; 18560d76e22dSNithin Dabilpuram } 18570d76e22dSNithin Dabilpuram 18580d76e22dSNithin Dabilpuram /* Launch worker */ 18590d76e22dSNithin Dabilpuram (*fn)(); 18600d76e22dSNithin Dabilpuram } 18610d76e22dSNithin Dabilpuram 18624965dda0SLukasz Bartosik int ipsec_launch_one_lcore(void *args) 18634965dda0SLukasz Bartosik { 18644965dda0SLukasz Bartosik struct eh_conf *conf; 18654965dda0SLukasz Bartosik 18664965dda0SLukasz Bartosik conf = (struct eh_conf *)args; 18674965dda0SLukasz Bartosik 18684965dda0SLukasz Bartosik if (conf->mode == EH_PKT_TRANSFER_MODE_POLL) { 18694965dda0SLukasz Bartosik /* Run in poll mode */ 18700d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_launch(); 18714965dda0SLukasz Bartosik } else if (conf->mode == EH_PKT_TRANSFER_MODE_EVENT) { 18724965dda0SLukasz Bartosik /* Run in event mode */ 18734965dda0SLukasz Bartosik ipsec_eventmode_worker(conf); 18744965dda0SLukasz Bartosik } 18754965dda0SLukasz Bartosik return 0; 18764965dda0SLukasz Bartosik } 1877