xref: /dpdk/examples/l3fwd/l3fwd_altivec.h (revision ebab0e8b2257aa049dd35dedc7efd230b0f45b88)
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