1f0e7c359SLee Daly /* SPDX-License-Identifier: BSD-3-Clause 2f0e7c359SLee Daly * Copyright(c) 2016 Intel Corporation. 32193b746SGowrishankar Muthukrishnan * Copyright(c) 2017 IBM Corporation. 42193b746SGowrishankar Muthukrishnan * All rights reserved. 52193b746SGowrishankar Muthukrishnan */ 62193b746SGowrishankar Muthukrishnan 72193b746SGowrishankar Muthukrishnan #ifndef _L3FWD_ALTIVEC_H_ 82193b746SGowrishankar Muthukrishnan #define _L3FWD_ALTIVEC_H_ 92193b746SGowrishankar Muthukrishnan 102193b746SGowrishankar Muthukrishnan #include "l3fwd.h" 11732115ceSRahul Bhansali #include "altivec/port_group.h" 122193b746SGowrishankar Muthukrishnan #include "l3fwd_common.h" 132193b746SGowrishankar Muthukrishnan 14*ebab0e8bSKonstantin Ananyev #undef SENDM_PORT_OVERHEAD 15*ebab0e8bSKonstantin Ananyev #define SENDM_PORT_OVERHEAD(x) ((x) + 2 * FWDSTEP) 16*ebab0e8bSKonstantin Ananyev 172193b746SGowrishankar Muthukrishnan /* 182193b746SGowrishankar Muthukrishnan * Update source and destination MAC addresses in the ethernet header. 192193b746SGowrishankar Muthukrishnan * Perform RFC1812 checks and updates for IPV4 packets. 202193b746SGowrishankar Muthukrishnan */ 212193b746SGowrishankar Muthukrishnan static inline void 222193b746SGowrishankar Muthukrishnan processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP]) 232193b746SGowrishankar Muthukrishnan { 2464fcadeaSThomas Monjalon __vector unsigned int te[FWDSTEP]; 2564fcadeaSThomas Monjalon __vector unsigned int ve[FWDSTEP]; 2664fcadeaSThomas Monjalon __vector unsigned int *p[FWDSTEP]; 272193b746SGowrishankar Muthukrishnan 2864fcadeaSThomas Monjalon p[0] = rte_pktmbuf_mtod(pkt[0], __vector unsigned int *); 2964fcadeaSThomas Monjalon p[1] = rte_pktmbuf_mtod(pkt[1], __vector unsigned int *); 3064fcadeaSThomas Monjalon p[2] = rte_pktmbuf_mtod(pkt[2], __vector unsigned int *); 3164fcadeaSThomas Monjalon p[3] = rte_pktmbuf_mtod(pkt[3], __vector unsigned int *); 322193b746SGowrishankar Muthukrishnan 3364fcadeaSThomas Monjalon ve[0] = (__vector unsigned int)val_eth[dst_port[0]]; 342193b746SGowrishankar Muthukrishnan te[0] = *p[0]; 352193b746SGowrishankar Muthukrishnan 3664fcadeaSThomas Monjalon ve[1] = (__vector unsigned int)val_eth[dst_port[1]]; 372193b746SGowrishankar Muthukrishnan te[1] = *p[1]; 382193b746SGowrishankar Muthukrishnan 3964fcadeaSThomas Monjalon ve[2] = (__vector unsigned int)val_eth[dst_port[2]]; 402193b746SGowrishankar Muthukrishnan te[2] = *p[2]; 412193b746SGowrishankar Muthukrishnan 4264fcadeaSThomas Monjalon ve[3] = (__vector unsigned int)val_eth[dst_port[3]]; 432193b746SGowrishankar Muthukrishnan te[3] = *p[3]; 442193b746SGowrishankar Muthukrishnan 452193b746SGowrishankar Muthukrishnan /* Update first 12 bytes, keep rest bytes intact. */ 4664fcadeaSThomas Monjalon te[0] = (__vector unsigned int)vec_sel( 4764fcadeaSThomas Monjalon (__vector unsigned short)ve[0], 4864fcadeaSThomas Monjalon (__vector unsigned short)te[0], 4964fcadeaSThomas Monjalon (__vector unsigned short) {0, 0, 0, 0, 502193b746SGowrishankar Muthukrishnan 0, 0, 0xffff, 0xffff}); 512193b746SGowrishankar Muthukrishnan 5264fcadeaSThomas Monjalon te[1] = (__vector unsigned int)vec_sel( 5364fcadeaSThomas Monjalon (__vector unsigned short)ve[1], 5464fcadeaSThomas Monjalon (__vector unsigned short)te[1], 5564fcadeaSThomas Monjalon (__vector unsigned short) {0, 0, 0, 0, 562193b746SGowrishankar Muthukrishnan 0, 0, 0xffff, 0xffff}); 572193b746SGowrishankar Muthukrishnan 5864fcadeaSThomas Monjalon te[2] = (__vector unsigned int)vec_sel( 5964fcadeaSThomas Monjalon (__vector unsigned short)ve[2], 6064fcadeaSThomas Monjalon (__vector unsigned short)te[2], 6164fcadeaSThomas Monjalon (__vector unsigned short) {0, 0, 0, 0, 0, 622193b746SGowrishankar Muthukrishnan 0, 0xffff, 0xffff}); 632193b746SGowrishankar Muthukrishnan 6464fcadeaSThomas Monjalon te[3] = (__vector unsigned int)vec_sel( 6564fcadeaSThomas Monjalon (__vector unsigned short)ve[3], 6664fcadeaSThomas Monjalon (__vector unsigned short)te[3], 6764fcadeaSThomas Monjalon (__vector unsigned short) {0, 0, 0, 0, 682193b746SGowrishankar Muthukrishnan 0, 0, 0xffff, 0xffff}); 692193b746SGowrishankar Muthukrishnan 702193b746SGowrishankar Muthukrishnan *p[0] = te[0]; 712193b746SGowrishankar Muthukrishnan *p[1] = te[1]; 722193b746SGowrishankar Muthukrishnan *p[2] = te[2]; 732193b746SGowrishankar Muthukrishnan *p[3] = te[3]; 742193b746SGowrishankar Muthukrishnan 75a7c528e5SOlivier Matz rfc1812_process((struct rte_ipv4_hdr *) 76a7c528e5SOlivier Matz ((struct rte_ether_hdr *)p[0] + 1), 772193b746SGowrishankar Muthukrishnan &dst_port[0], pkt[0]->packet_type); 78a7c528e5SOlivier Matz rfc1812_process((struct rte_ipv4_hdr *) 79a7c528e5SOlivier Matz ((struct rte_ether_hdr *)p[1] + 1), 802193b746SGowrishankar Muthukrishnan &dst_port[1], pkt[1]->packet_type); 81a7c528e5SOlivier Matz rfc1812_process((struct rte_ipv4_hdr *) 82a7c528e5SOlivier Matz ((struct rte_ether_hdr *)p[2] + 1), 832193b746SGowrishankar Muthukrishnan &dst_port[2], pkt[2]->packet_type); 84a7c528e5SOlivier Matz rfc1812_process((struct rte_ipv4_hdr *) 85a7c528e5SOlivier Matz ((struct rte_ether_hdr *)p[3] + 1), 862193b746SGowrishankar Muthukrishnan &dst_port[3], pkt[3]->packet_type); 872193b746SGowrishankar Muthukrishnan } 882193b746SGowrishankar Muthukrishnan 892193b746SGowrishankar Muthukrishnan /** 902193b746SGowrishankar Muthukrishnan * Process one packet: 912193b746SGowrishankar Muthukrishnan * Update source and destination MAC addresses in the ethernet header. 922193b746SGowrishankar Muthukrishnan * Perform RFC1812 checks and updates for IPV4 packets. 932193b746SGowrishankar Muthukrishnan */ 942193b746SGowrishankar Muthukrishnan static inline void 952193b746SGowrishankar Muthukrishnan process_packet(struct rte_mbuf *pkt, uint16_t *dst_port) 962193b746SGowrishankar Muthukrishnan { 976d13ea8eSOlivier Matz struct rte_ether_hdr *eth_hdr; 9864fcadeaSThomas Monjalon __vector unsigned int te, ve; 992193b746SGowrishankar Muthukrishnan 1006d13ea8eSOlivier Matz eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *); 1012193b746SGowrishankar Muthukrishnan 10264fcadeaSThomas Monjalon te = *(__vector unsigned int *)eth_hdr; 10364fcadeaSThomas Monjalon ve = (__vector unsigned int)val_eth[dst_port[0]]; 1042193b746SGowrishankar Muthukrishnan 105a7c528e5SOlivier Matz rfc1812_process((struct rte_ipv4_hdr *)(eth_hdr + 1), dst_port, 1062193b746SGowrishankar Muthukrishnan pkt->packet_type); 1072193b746SGowrishankar Muthukrishnan 1082193b746SGowrishankar Muthukrishnan /* dynamically vec_sel te and ve for MASK_ETH (0x3f) */ 10964fcadeaSThomas Monjalon te = (__vector unsigned int)vec_sel( 11064fcadeaSThomas Monjalon (__vector unsigned short)ve, 11164fcadeaSThomas Monjalon (__vector unsigned short)te, 11264fcadeaSThomas Monjalon (__vector unsigned short){0, 0, 0, 0, 1132193b746SGowrishankar Muthukrishnan 0, 0, 0xffff, 0xffff}); 1142193b746SGowrishankar Muthukrishnan 11564fcadeaSThomas Monjalon *(__vector unsigned int *)eth_hdr = te; 1162193b746SGowrishankar Muthukrishnan } 1172193b746SGowrishankar Muthukrishnan 1182193b746SGowrishankar Muthukrishnan /** 1192193b746SGowrishankar Muthukrishnan * Send packets burst from pkts_burst to the ports in dst_port array 1202193b746SGowrishankar Muthukrishnan */ 1212193b746SGowrishankar Muthukrishnan static __rte_always_inline void 1222193b746SGowrishankar Muthukrishnan send_packets_multi(struct lcore_conf *qconf, struct rte_mbuf **pkts_burst, 123*ebab0e8bSKonstantin Ananyev uint16_t dst_port[SENDM_PORT_OVERHEAD(MAX_PKT_BURST)], 124*ebab0e8bSKonstantin Ananyev int nb_rx) 1252193b746SGowrishankar Muthukrishnan { 1262193b746SGowrishankar Muthukrishnan int32_t k; 1272193b746SGowrishankar Muthukrishnan int j = 0; 1282193b746SGowrishankar Muthukrishnan uint16_t dlp; 1292193b746SGowrishankar Muthukrishnan uint16_t *lp; 1302193b746SGowrishankar Muthukrishnan uint16_t pnum[MAX_PKT_BURST + 1]; 1312193b746SGowrishankar Muthukrishnan 1322193b746SGowrishankar Muthukrishnan /* 1332193b746SGowrishankar Muthukrishnan * Finish packet processing and group consecutive 1342193b746SGowrishankar Muthukrishnan * packets with the same destination port. 1352193b746SGowrishankar Muthukrishnan */ 1362193b746SGowrishankar Muthukrishnan k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); 1372193b746SGowrishankar Muthukrishnan if (k != 0) { 13864fcadeaSThomas Monjalon __vector unsigned short dp1, dp2; 1392193b746SGowrishankar Muthukrishnan 1402193b746SGowrishankar Muthukrishnan lp = pnum; 1412193b746SGowrishankar Muthukrishnan lp[0] = 1; 1422193b746SGowrishankar Muthukrishnan 1432193b746SGowrishankar Muthukrishnan processx4_step3(pkts_burst, dst_port); 1442193b746SGowrishankar Muthukrishnan 1452193b746SGowrishankar Muthukrishnan /* dp1: <d[0], d[1], d[2], d[3], ... > */ 14664fcadeaSThomas Monjalon dp1 = *(__vector unsigned short *)dst_port; 1472193b746SGowrishankar Muthukrishnan 1482193b746SGowrishankar Muthukrishnan for (j = FWDSTEP; j != k; j += FWDSTEP) { 1492193b746SGowrishankar Muthukrishnan processx4_step3(&pkts_burst[j], &dst_port[j]); 1502193b746SGowrishankar Muthukrishnan 1512193b746SGowrishankar Muthukrishnan /* 1522193b746SGowrishankar Muthukrishnan * dp2: 1532193b746SGowrishankar Muthukrishnan * <d[j-3], d[j-2], d[j-1], d[j], ... > 1542193b746SGowrishankar Muthukrishnan */ 15564fcadeaSThomas Monjalon dp2 = *((__vector unsigned short *) 1562193b746SGowrishankar Muthukrishnan &dst_port[j - FWDSTEP + 1]); 1572193b746SGowrishankar Muthukrishnan lp = port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); 1582193b746SGowrishankar Muthukrishnan 1592193b746SGowrishankar Muthukrishnan /* 1602193b746SGowrishankar Muthukrishnan * dp1: 1612193b746SGowrishankar Muthukrishnan * <d[j], d[j+1], d[j+2], d[j+3], ... > 1622193b746SGowrishankar Muthukrishnan */ 16364fcadeaSThomas Monjalon dp1 = vec_sro(dp2, (__vector unsigned char) { 1642193b746SGowrishankar Muthukrishnan 0, 0, 0, 0, 0, 0, 0, 0, 1652193b746SGowrishankar Muthukrishnan 0, 0, 0, (FWDSTEP - 1) * sizeof(dst_port[0])}); 1662193b746SGowrishankar Muthukrishnan } 1672193b746SGowrishankar Muthukrishnan 1682193b746SGowrishankar Muthukrishnan /* 1692193b746SGowrishankar Muthukrishnan * dp2: <d[j-3], d[j-2], d[j-1], d[j-1], ... > 1702193b746SGowrishankar Muthukrishnan */ 17164fcadeaSThomas Monjalon dp2 = vec_perm(dp1, (__vector unsigned short){}, 17264fcadeaSThomas Monjalon (__vector unsigned char){0xf9}); 1732193b746SGowrishankar Muthukrishnan lp = port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); 1742193b746SGowrishankar Muthukrishnan 1752193b746SGowrishankar Muthukrishnan /* 1762193b746SGowrishankar Muthukrishnan * remove values added by the last repeated 1772193b746SGowrishankar Muthukrishnan * dst port. 1782193b746SGowrishankar Muthukrishnan */ 1792193b746SGowrishankar Muthukrishnan lp[0]--; 1802193b746SGowrishankar Muthukrishnan dlp = dst_port[j - 1]; 1812193b746SGowrishankar Muthukrishnan } else { 1822193b746SGowrishankar Muthukrishnan /* set dlp and lp to the never used values. */ 1832193b746SGowrishankar Muthukrishnan dlp = BAD_PORT - 1; 1842193b746SGowrishankar Muthukrishnan lp = pnum + MAX_PKT_BURST; 1852193b746SGowrishankar Muthukrishnan } 1862193b746SGowrishankar Muthukrishnan 1872193b746SGowrishankar Muthukrishnan /* Process up to last 3 packets one by one. */ 1882193b746SGowrishankar Muthukrishnan switch (nb_rx % FWDSTEP) { 1892193b746SGowrishankar Muthukrishnan case 3: 1902193b746SGowrishankar Muthukrishnan process_packet(pkts_burst[j], dst_port + j); 1912193b746SGowrishankar Muthukrishnan GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); 1922193b746SGowrishankar Muthukrishnan j++; 1932193b746SGowrishankar Muthukrishnan /* fall-through */ 1942193b746SGowrishankar Muthukrishnan case 2: 1952193b746SGowrishankar Muthukrishnan process_packet(pkts_burst[j], dst_port + j); 1962193b746SGowrishankar Muthukrishnan GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); 1972193b746SGowrishankar Muthukrishnan j++; 1982193b746SGowrishankar Muthukrishnan /* fall-through */ 1992193b746SGowrishankar Muthukrishnan case 1: 2002193b746SGowrishankar Muthukrishnan process_packet(pkts_burst[j], dst_port + j); 2012193b746SGowrishankar Muthukrishnan GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); 2022193b746SGowrishankar Muthukrishnan j++; 2032193b746SGowrishankar Muthukrishnan } 2042193b746SGowrishankar Muthukrishnan 2052193b746SGowrishankar Muthukrishnan /* 2062193b746SGowrishankar Muthukrishnan * Send packets out, through destination port. 2072193b746SGowrishankar Muthukrishnan * Consecutive packets with the same destination port 2082193b746SGowrishankar Muthukrishnan * are already grouped together. 2092193b746SGowrishankar Muthukrishnan * If destination port for the packet equals BAD_PORT, 2102193b746SGowrishankar Muthukrishnan * then free the packet without sending it out. 2112193b746SGowrishankar Muthukrishnan */ 2122193b746SGowrishankar Muthukrishnan for (j = 0; j < nb_rx; j += k) { 2132193b746SGowrishankar Muthukrishnan 2142193b746SGowrishankar Muthukrishnan int32_t m; 2152193b746SGowrishankar Muthukrishnan uint16_t pn; 2162193b746SGowrishankar Muthukrishnan 2172193b746SGowrishankar Muthukrishnan pn = dst_port[j]; 2182193b746SGowrishankar Muthukrishnan k = pnum[j]; 2192193b746SGowrishankar Muthukrishnan 2202193b746SGowrishankar Muthukrishnan if (likely(pn != BAD_PORT)) 2212193b746SGowrishankar Muthukrishnan send_packetsx4(qconf, pn, pkts_burst + j, k); 2222193b746SGowrishankar Muthukrishnan else 2232193b746SGowrishankar Muthukrishnan for (m = j; m != j + k; m++) 2242193b746SGowrishankar Muthukrishnan rte_pktmbuf_free(pkts_burst[m]); 2252193b746SGowrishankar Muthukrishnan 2262193b746SGowrishankar Muthukrishnan } 2272193b746SGowrishankar Muthukrishnan } 2282193b746SGowrishankar Muthukrishnan 229b140e970SPavan Nikhilesh static __rte_always_inline uint16_t 230b140e970SPavan Nikhilesh process_dst_port(uint16_t *dst_ports, uint16_t nb_elem) 231b140e970SPavan Nikhilesh { 232b140e970SPavan Nikhilesh uint16_t i = 0, res; 233b140e970SPavan Nikhilesh 234b140e970SPavan Nikhilesh while (nb_elem > 7) { 235b140e970SPavan Nikhilesh __vector unsigned short dp1; 236b140e970SPavan Nikhilesh __vector unsigned short dp; 237b140e970SPavan Nikhilesh 238b140e970SPavan Nikhilesh dp = (__vector unsigned short)vec_splats((short)dst_ports[0]); 239b140e970SPavan Nikhilesh dp1 = *((__vector unsigned short *)&dst_ports[i]); 240b140e970SPavan Nikhilesh res = vec_all_eq(dp1, dp); 241b140e970SPavan Nikhilesh if (!res) 242b140e970SPavan Nikhilesh return BAD_PORT; 243b140e970SPavan Nikhilesh 244b140e970SPavan Nikhilesh nb_elem -= 8; 245b140e970SPavan Nikhilesh i += 8; 246b140e970SPavan Nikhilesh } 247b140e970SPavan Nikhilesh 248b140e970SPavan Nikhilesh while (nb_elem) { 249b140e970SPavan Nikhilesh if (dst_ports[i] != dst_ports[0]) 250b140e970SPavan Nikhilesh return BAD_PORT; 251b140e970SPavan Nikhilesh nb_elem--; 252b140e970SPavan Nikhilesh i++; 253b140e970SPavan Nikhilesh } 254b140e970SPavan Nikhilesh 255b140e970SPavan Nikhilesh return dst_ports[0]; 256b140e970SPavan Nikhilesh } 257b140e970SPavan Nikhilesh 2582193b746SGowrishankar Muthukrishnan #endif /* _L3FWD_ALTIVEC_H_ */ 259