13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 23998e2a0SBruce Richardson * Copyright(c) 2010-2016 Intel Corporation 3268888b5SRavi Kerur */ 4268888b5SRavi Kerur 5268888b5SRavi Kerur #ifndef __L3FWD_LPM_SSE_H__ 6268888b5SRavi Kerur #define __L3FWD_LPM_SSE_H__ 7268888b5SRavi Kerur 894c54b41STomasz Kulasek #include "l3fwd_sse.h" 9268888b5SRavi Kerur 10268888b5SRavi Kerur /* 11268888b5SRavi Kerur * Read packet_type and destination IPV4 addresses from 4 mbufs. 12268888b5SRavi Kerur */ 13268888b5SRavi Kerur static inline void 14268888b5SRavi Kerur processx4_step1(struct rte_mbuf *pkt[FWDSTEP], 15268888b5SRavi Kerur __m128i *dip, 16268888b5SRavi Kerur uint32_t *ipv4_flag) 17268888b5SRavi Kerur { 18a7c528e5SOlivier Matz struct rte_ipv4_hdr *ipv4_hdr; 196d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 20268888b5SRavi Kerur uint32_t x0, x1, x2, x3; 21268888b5SRavi Kerur 226d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(pkt[0], struct rte_ether_hdr *); 23a7c528e5SOlivier Matz ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); 24268888b5SRavi Kerur x0 = ipv4_hdr->dst_addr; 25268888b5SRavi Kerur ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4; 26268888b5SRavi Kerur 276d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(pkt[1], struct rte_ether_hdr *); 28a7c528e5SOlivier Matz ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); 29268888b5SRavi Kerur x1 = ipv4_hdr->dst_addr; 30268888b5SRavi Kerur ipv4_flag[0] &= pkt[1]->packet_type; 31268888b5SRavi Kerur 326d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(pkt[2], struct rte_ether_hdr *); 33a7c528e5SOlivier Matz ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); 34268888b5SRavi Kerur x2 = ipv4_hdr->dst_addr; 35268888b5SRavi Kerur ipv4_flag[0] &= pkt[2]->packet_type; 36268888b5SRavi Kerur 376d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(pkt[3], struct rte_ether_hdr *); 38a7c528e5SOlivier Matz ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); 39268888b5SRavi Kerur x3 = ipv4_hdr->dst_addr; 40268888b5SRavi Kerur ipv4_flag[0] &= pkt[3]->packet_type; 41268888b5SRavi Kerur 42268888b5SRavi Kerur dip[0] = _mm_set_epi32(x3, x2, x1, x0); 43268888b5SRavi Kerur } 44268888b5SRavi Kerur 45268888b5SRavi Kerur /* 46268888b5SRavi Kerur * Lookup into LPM for destination port. 47268888b5SRavi Kerur * If lookup fails, use incoming port (portid) as destination port. 48268888b5SRavi Kerur */ 49268888b5SRavi Kerur static inline void 50268888b5SRavi Kerur processx4_step2(const struct lcore_conf *qconf, 51268888b5SRavi Kerur __m128i dip, 52268888b5SRavi Kerur uint32_t ipv4_flag, 53f8244c63SZhiyong Yang uint16_t portid, 54268888b5SRavi Kerur struct rte_mbuf *pkt[FWDSTEP], 558353a36aSKonstantin Ananyev uint16_t dprt[FWDSTEP]) 56268888b5SRavi Kerur { 57268888b5SRavi Kerur rte_xmm_t dst; 58268888b5SRavi Kerur const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 59268888b5SRavi Kerur 4, 5, 6, 7, 0, 1, 2, 3); 60268888b5SRavi Kerur 61268888b5SRavi Kerur /* Byte swap 4 IPV4 addresses. */ 62268888b5SRavi Kerur dip = _mm_shuffle_epi8(dip, bswap_mask); 63268888b5SRavi Kerur 64268888b5SRavi Kerur /* if all 4 packets are IPV4. */ 65268888b5SRavi Kerur if (likely(ipv4_flag)) { 668353a36aSKonstantin Ananyev rte_lpm_lookupx4(qconf->ipv4_lookup_struct, dip, dst.u32, 678353a36aSKonstantin Ananyev portid); 688353a36aSKonstantin Ananyev /* get rid of unused upper 16 bit for each dport. */ 698353a36aSKonstantin Ananyev dst.x = _mm_packs_epi32(dst.x, dst.x); 708353a36aSKonstantin Ananyev *(uint64_t *)dprt = dst.u64[0]; 71268888b5SRavi Kerur } else { 72268888b5SRavi Kerur dst.x = dip; 7394c54b41STomasz Kulasek dprt[0] = lpm_get_dst_port_with_ipv4(qconf, pkt[0], dst.u32[0], portid); 7494c54b41STomasz Kulasek dprt[1] = lpm_get_dst_port_with_ipv4(qconf, pkt[1], dst.u32[1], portid); 7594c54b41STomasz Kulasek dprt[2] = lpm_get_dst_port_with_ipv4(qconf, pkt[2], dst.u32[2], portid); 7694c54b41STomasz Kulasek dprt[3] = lpm_get_dst_port_with_ipv4(qconf, pkt[3], dst.u32[3], portid); 77268888b5SRavi Kerur } 78268888b5SRavi Kerur } 79268888b5SRavi Kerur 80268888b5SRavi Kerur /* 81268888b5SRavi Kerur * Buffer optimized handling of packets, invoked 82268888b5SRavi Kerur * from main_loop. 83268888b5SRavi Kerur */ 84268888b5SRavi Kerur static inline void 85cb0ddabfSPavan Nikhilesh l3fwd_lpm_process_packets(int nb_rx, struct rte_mbuf **pkts_burst, 86cb0ddabfSPavan Nikhilesh uint16_t portid, uint16_t *dst_port, 87cb0ddabfSPavan Nikhilesh struct lcore_conf *qconf, const uint8_t do_step3) 88268888b5SRavi Kerur { 8994c54b41STomasz Kulasek int32_t j; 90268888b5SRavi Kerur __m128i dip[MAX_PKT_BURST / FWDSTEP]; 91268888b5SRavi Kerur uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP]; 9294c54b41STomasz Kulasek const int32_t k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); 93268888b5SRavi Kerur 9494c54b41STomasz Kulasek for (j = 0; j != k; j += FWDSTEP) 9594c54b41STomasz Kulasek processx4_step1(&pkts_burst[j], &dip[j / FWDSTEP], 96268888b5SRavi Kerur &ipv4_flag[j / FWDSTEP]); 97268888b5SRavi Kerur 9894c54b41STomasz Kulasek for (j = 0; j != k; j += FWDSTEP) 99268888b5SRavi Kerur processx4_step2(qconf, dip[j / FWDSTEP], 10094c54b41STomasz Kulasek ipv4_flag[j / FWDSTEP], portid, &pkts_burst[j], &dst_port[j]); 101268888b5SRavi Kerur 102cb0ddabfSPavan Nikhilesh if (do_step3) 103cb0ddabfSPavan Nikhilesh for (j = 0; j != k; j += FWDSTEP) 104cb0ddabfSPavan Nikhilesh processx4_step3(&pkts_burst[j], &dst_port[j]); 105cb0ddabfSPavan Nikhilesh 10694c54b41STomasz Kulasek /* Classify last up to 3 packets one by one */ 107268888b5SRavi Kerur switch (nb_rx % FWDSTEP) { 108268888b5SRavi Kerur case 3: 10994c54b41STomasz Kulasek dst_port[j] = lpm_get_dst_port(qconf, pkts_burst[j], portid); 110cb0ddabfSPavan Nikhilesh if (do_step3) 111cb0ddabfSPavan Nikhilesh process_packet(pkts_burst[j], &dst_port[j]); 112268888b5SRavi Kerur j++; 113663d3bc6SJerin Jacob /* fall-through */ 114268888b5SRavi Kerur case 2: 11594c54b41STomasz Kulasek dst_port[j] = lpm_get_dst_port(qconf, pkts_burst[j], portid); 116cb0ddabfSPavan Nikhilesh if (do_step3) 117cb0ddabfSPavan Nikhilesh process_packet(pkts_burst[j], &dst_port[j]); 118268888b5SRavi Kerur j++; 119663d3bc6SJerin Jacob /* fall-through */ 120268888b5SRavi Kerur case 1: 12194c54b41STomasz Kulasek dst_port[j] = lpm_get_dst_port(qconf, pkts_burst[j], portid); 122cb0ddabfSPavan Nikhilesh if (do_step3) 123cb0ddabfSPavan Nikhilesh process_packet(pkts_burst[j], &dst_port[j]); 124268888b5SRavi Kerur j++; 125268888b5SRavi Kerur } 126cb0ddabfSPavan Nikhilesh } 127268888b5SRavi Kerur 128cb0ddabfSPavan Nikhilesh static inline void 129cb0ddabfSPavan Nikhilesh l3fwd_lpm_send_packets(int nb_rx, struct rte_mbuf **pkts_burst, uint16_t portid, 130cb0ddabfSPavan Nikhilesh struct lcore_conf *qconf) 131cb0ddabfSPavan Nikhilesh { 132*ebab0e8bSKonstantin Ananyev uint16_t dst_port[SENDM_PORT_OVERHEAD(MAX_PKT_BURST)]; 133cb0ddabfSPavan Nikhilesh 134cb0ddabfSPavan Nikhilesh l3fwd_lpm_process_packets(nb_rx, pkts_burst, portid, dst_port, qconf, 135cb0ddabfSPavan Nikhilesh 0); 13694c54b41STomasz Kulasek send_packets_multi(qconf, pkts_burst, dst_port, nb_rx); 137268888b5SRavi Kerur } 138268888b5SRavi Kerur 139268888b5SRavi Kerur #endif /* __L3FWD_LPM_SSE_H__ */ 140