From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by dpdk.org (Postfix) with ESMTP id 034B123A for ; Thu, 28 Sep 2017 03:59:57 +0200 (CEST) Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v8S1wXlb084332 for ; Wed, 27 Sep 2017 21:59:57 -0400 Received: from e23smtp03.au.ibm.com (e23smtp03.au.ibm.com [202.81.31.145]) by mx0b-001b2d01.pphosted.com with ESMTP id 2d8p7hvdfj-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 27 Sep 2017 21:59:57 -0400 Received: from localhost by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 28 Sep 2017 11:59:53 +1000 Received: from d23relay09.au.ibm.com (202.81.31.228) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 28 Sep 2017 11:59:52 +1000 Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay09.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v8S1xq0N39059498 for ; Thu, 28 Sep 2017 11:59:52 +1000 Received: from d23av01.au.ibm.com (localhost [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v8S1xq0g000618 for ; Thu, 28 Sep 2017 11:59:53 +1000 Received: from ADMINIB2M8Q79C (adminib-2m8q79c.crl.ibm.com [9.186.50.233]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v8S1xpjv000573; Thu, 28 Sep 2017 11:59:51 +1000 From: "Chao Zhu" To: "'Gowrishankar'" , Cc: "'Tomasz Kantecki'" References: In-Reply-To: Date: Thu, 28 Sep 2017 09:59:50 +0800 MIME-Version: 1.0 Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: quoted-printable X-Mailer: Microsoft Outlook 15.0 Thread-Index: AQIfZHDqJb9ojn3a5oJPGXnGM3GpTAHfjtG8oiI1hsA= Content-Language: zh-cn X-TM-AS-MML: disable x-cbid: 17092801-0008-0000-0000-00000158DD9F X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17092801-0009-0000-0000-0000098E7A2C Message-Id: <000901d337fd$79110b10$6b332130$@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-09-28_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1709280028 Subject: Re: [dpdk-dev] [PATCH v2] examples/l3fwd: optimised packet processing on powerpc X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Sep 2017 01:59:58 -0000 > -----Original Message----- > From: Gowrishankar [mailto:gowrishankar.m@linux.vnet.ibm.com] > Sent: 2017=C4=EA9=D4=C221=C8=D5 18:05 > To: dev@dpdk.org > Cc: Chao Zhu ; Tomasz Kantecki > ; Gowrishankar Muthukrishnan > > Subject: [PATCH v2] examples/l3fwd: optimised packet processing on = powerpc >=20 > From: Gowrishankar Muthukrishnan >=20 > This patch adds altivec support for lpm packet processing in powerpc. >=20 > Signed-off-by: Gowrishankar Muthukrishnan > > --- > v2: > * coding style standards >=20 > MAINTAINERS | 1 + > examples/l3fwd/l3fwd_altivec.h | 284 > +++++++++++++++++++++++++++++++++++++ > examples/l3fwd/l3fwd_lpm.c | 5 +- > examples/l3fwd/l3fwd_lpm_altivec.h | 164 +++++++++++++++++++++ > 4 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 > examples/l3fwd/l3fwd_altivec.h create mode 100644 > examples/l3fwd/l3fwd_lpm_altivec.h >=20 > diff --git a/MAINTAINERS b/MAINTAINERS > index a0cd75e..0010b6c 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -168,6 +168,7 @@ M: Chao Zhu > F: lib/librte_eal/common/arch/ppc_64/ > F: lib/librte_eal/common/include/arch/ppc_64/ > F: drivers/net/i40e/i40e_rxtx_vec_altivec.c > +F: examples/l3fwd/*altivec.h >=20 > Intel x86 > M: Bruce Richardson diff --git > a/examples/l3fwd/l3fwd_altivec.h b/examples/l3fwd/l3fwd_altivec.h new = file > mode 100644 index 0000000..29c2627 > --- /dev/null > +++ b/examples/l3fwd/l3fwd_altivec.h > @@ -0,0 +1,284 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * Copyright(c) 2017 IBM Corporation. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or = without > + * modification, are permitted provided that the following = conditions > + * are met: > + * > + * * Redistributions of source code must retain the above = copyright > + * notice, this list of conditions and the following = disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer = in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products = derived > + * from this software without specific prior written = permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; > LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > + > +#ifndef _L3FWD_ALTIVEC_H_ > +#define _L3FWD_ALTIVEC_H_ > + > +#include "l3fwd.h" > +#include "l3fwd_common.h" > + > +/* > + * Update source and destination MAC addresses in the ethernet = header. > + * Perform RFC1812 checks and updates for IPV4 packets. > + */ > +static inline void > +processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t > +dst_port[FWDSTEP]) { > + vector unsigned int te[FWDSTEP]; > + vector unsigned int ve[FWDSTEP]; > + vector unsigned int *p[FWDSTEP]; > + > + p[0] =3D rte_pktmbuf_mtod(pkt[0], vector unsigned int *); > + p[1] =3D rte_pktmbuf_mtod(pkt[1], vector unsigned int *); > + p[2] =3D rte_pktmbuf_mtod(pkt[2], vector unsigned int *); > + p[3] =3D rte_pktmbuf_mtod(pkt[3], vector unsigned int *); > + > + ve[0] =3D (vector unsigned int)val_eth[dst_port[0]]; > + te[0] =3D *p[0]; > + > + ve[1] =3D (vector unsigned int)val_eth[dst_port[1]]; > + te[1] =3D *p[1]; > + > + ve[2] =3D (vector unsigned int)val_eth[dst_port[2]]; > + te[2] =3D *p[2]; > + > + ve[3] =3D (vector unsigned int)val_eth[dst_port[3]]; > + te[3] =3D *p[3]; > + > + /* Update first 12 bytes, keep rest bytes intact. */ > + te[0] =3D (vector unsigned int)vec_sel( > + (vector unsigned short)ve[0], > + (vector unsigned short)te[0], > + (vector unsigned short) {0, 0, 0, 0, > + 0, 0, 0xffff, 0xffff}); > + > + te[1] =3D (vector unsigned int)vec_sel( > + (vector unsigned short)ve[1], > + (vector unsigned short)te[1], > + (vector unsigned short) {0, 0, 0, 0, > + 0, 0, 0xffff, 0xffff}); > + > + te[2] =3D (vector unsigned int)vec_sel( > + (vector unsigned short)ve[2], > + (vector unsigned short)te[2], > + (vector unsigned short) {0, 0, 0, 0, 0, > + 0, 0xffff, 0xffff}); > + > + te[3] =3D (vector unsigned int)vec_sel( > + (vector unsigned short)ve[3], > + (vector unsigned short)te[3], > + (vector unsigned short) {0, 0, 0, 0, > + 0, 0, 0xffff, 0xffff}); > + > + *p[0] =3D te[0]; > + *p[1] =3D te[1]; > + *p[2] =3D te[2]; > + *p[3] =3D te[3]; > + > + rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1), > + &dst_port[0], pkt[0]->packet_type); > + rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1), > + &dst_port[1], pkt[1]->packet_type); > + rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1), > + &dst_port[2], pkt[2]->packet_type); > + rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1), > + &dst_port[3], pkt[3]->packet_type); > +} > + > +/* > + * Group consecutive packets with the same destination port in bursts = of 4. > + * Suppose we have array of destionation ports: > + * dst_port[] =3D {a, b, c, d,, e, ... } > + * dp1 should contain: , dp2: . > + * We doing 4 comparisons at once and the result is 4 bit mask. > + * This mask is used as an index into prebuild array of pnum values. > + */ > +static inline uint16_t * > +port_groupx4(uint16_t pn[FWDSTEP + 1], uint16_t *lp, vector unsigned short > dp1, > + vector unsigned short dp2) > +{ > + union { > + uint16_t u16[FWDSTEP + 1]; > + uint64_t u64; > + } *pnum =3D (void *)pn; > + > + int32_t v; > + > + v =3D vec_any_eq(dp1, dp2); > + > + > + /* update last port counter. */ > + lp[0] +=3D gptbl[v].lpv; > + > + /* if dest port value has changed. */ > + if (v !=3D GRPMSK) { > + pnum->u64 =3D gptbl[v].pnum; > + pnum->u16[FWDSTEP] =3D 1; > + lp =3D pnum->u16 + gptbl[v].idx; > + } > + > + return lp; > +} > + > +/** > + * Process one packet: > + * Update source and destination MAC addresses in the ethernet = header. > + * Perform RFC1812 checks and updates for IPV4 packets. > + */ > +static inline void > +process_packet(struct rte_mbuf *pkt, uint16_t *dst_port) { > + struct ether_hdr *eth_hdr; > + vector unsigned int te, ve; > + > + eth_hdr =3D rte_pktmbuf_mtod(pkt, struct ether_hdr *); > + > + te =3D *(vector unsigned int *)eth_hdr; > + ve =3D (vector unsigned int)val_eth[dst_port[0]]; > + > + rfc1812_process((struct ipv4_hdr *)(eth_hdr + 1), dst_port, > + pkt->packet_type); > + > + /* dynamically vec_sel te and ve for MASK_ETH (0x3f) */ > + te =3D (vector unsigned int)vec_sel( > + (vector unsigned short)ve, > + (vector unsigned short)te, > + (vector unsigned short){0, 0, 0, 0, > + 0, 0, 0xffff, 0xffff}); > + > + *(vector unsigned int *)eth_hdr =3D te; > +} > + > +/** > + * Send packets burst from pkts_burst to the ports in dst_port array > +*/ static __rte_always_inline void send_packets_multi(struct = lcore_conf > +*qconf, struct rte_mbuf **pkts_burst, > + uint16_t dst_port[MAX_PKT_BURST], int nb_rx) { > + int32_t k; > + int j =3D 0; > + uint16_t dlp; > + uint16_t *lp; > + uint16_t pnum[MAX_PKT_BURST + 1]; > + > + /* > + * Finish packet processing and group consecutive > + * packets with the same destination port. > + */ > + k =3D RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); > + if (k !=3D 0) { > + vector unsigned short dp1, dp2; > + > + lp =3D pnum; > + lp[0] =3D 1; > + > + processx4_step3(pkts_burst, dst_port); > + > + /* dp1: */ > + dp1 =3D *(vector unsigned short *)dst_port; > + > + for (j =3D FWDSTEP; j !=3D k; j +=3D FWDSTEP) { > + processx4_step3(&pkts_burst[j], &dst_port[j]); > + > + /* > + * dp2: > + * > + */ > + dp2 =3D *((vector unsigned short *) > + &dst_port[j - FWDSTEP + 1]); > + lp =3D port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); > + > + /* > + * dp1: > + * > + */ > + dp1 =3D vec_sro(dp2, (vector unsigned char) { > + 0, 0, 0, 0, 0, 0, 0, 0, > + 0, 0, 0, (FWDSTEP - 1) * sizeof(dst_port[0])}); > + } > + > + /* > + * dp2: > + */ > + dp2 =3D vec_perm(dp1, (vector unsigned short){}, > + (vector unsigned char){0xf9}); > + lp =3D port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); > + > + /* > + * remove values added by the last repeated > + * dst port. > + */ > + lp[0]--; > + dlp =3D dst_port[j - 1]; > + } else { > + /* set dlp and lp to the never used values. */ > + dlp =3D BAD_PORT - 1; > + lp =3D pnum + MAX_PKT_BURST; > + } > + > + /* Process up to last 3 packets one by one. */ > + switch (nb_rx % FWDSTEP) { > + case 3: > + process_packet(pkts_burst[j], dst_port + j); > + GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); > + j++; > + /* fall-through */ > + case 2: > + process_packet(pkts_burst[j], dst_port + j); > + GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); > + j++; > + /* fall-through */ > + case 1: > + process_packet(pkts_burst[j], dst_port + j); > + GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); > + j++; > + } > + > + /* > + * Send packets out, through destination port. > + * Consecutive packets with the same destination port > + * are already grouped together. > + * If destination port for the packet equals BAD_PORT, > + * then free the packet without sending it out. > + */ > + for (j =3D 0; j < nb_rx; j +=3D k) { > + > + int32_t m; > + uint16_t pn; > + > + pn =3D dst_port[j]; > + k =3D pnum[j]; > + > + if (likely(pn !=3D BAD_PORT)) > + send_packetsx4(qconf, pn, pkts_burst + j, k); > + else > + for (m =3D j; m !=3D j + k; m++) > + rte_pktmbuf_free(pkts_burst[m]); > + > + } > +} > + > +#endif /* _L3FWD_ALTIVEC_H_ */ > diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c = index > ff1e403..b508886 100644 > --- a/examples/l3fwd/l3fwd_lpm.c > +++ b/examples/l3fwd/l3fwd_lpm.c > @@ -191,6 +191,8 @@ struct ipv6_l3fwd_lpm_route { #include > "l3fwd_lpm_sse.h" > #elif defined RTE_MACHINE_CPUFLAG_NEON > #include "l3fwd_lpm_neon.h" > +#elif defined(RTE_ARCH_PPC_64) > +#include "l3fwd_lpm_altivec.h" > #else > #include "l3fwd_lpm.h" > #endif > @@ -263,7 +265,8 @@ struct ipv6_l3fwd_lpm_route { > if (nb_rx =3D=3D 0) > continue; >=20 > -#if defined RTE_ARCH_X86 || defined RTE_MACHINE_CPUFLAG_NEON > +#if defined RTE_ARCH_X86 || defined RTE_MACHINE_CPUFLAG_NEON \ > + || defined RTE_ARCH_PPC_64 > l3fwd_lpm_send_packets(nb_rx, pkts_burst, > portid, qconf); > #else > diff --git a/examples/l3fwd/l3fwd_lpm_altivec.h > b/examples/l3fwd/l3fwd_lpm_altivec.h > new file mode 100644 > index 0000000..36ca983 > --- /dev/null > +++ b/examples/l3fwd/l3fwd_lpm_altivec.h > @@ -0,0 +1,164 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. > + * Copyright(c) 2017 IBM Corporation. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or = without > + * modification, are permitted provided that the following = conditions > + * are met: > + * > + * * Redistributions of source code must retain the above = copyright > + * notice, this list of conditions and the following = disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer = in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products = derived > + * from this software without specific prior written = permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; > LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > +#ifndef __L3FWD_LPM_ALTIVEC_H__ > +#define __L3FWD_LPM_ALTIVEC_H__ > + > +#include "l3fwd_altivec.h" > + > +/* > + * Read packet_type and destination IPV4 addresses from 4 mbufs. > + */ > +static inline void > +processx4_step1(struct rte_mbuf *pkt[FWDSTEP], > + vector unsigned int *dip, > + uint32_t *ipv4_flag) > +{ > + struct ipv4_hdr *ipv4_hdr; > + struct ether_hdr *eth_hdr; > + uint32_t x0, x1, x2, x3; > + > + eth_hdr =3D rte_pktmbuf_mtod(pkt[0], struct ether_hdr *); > + ipv4_hdr =3D (struct ipv4_hdr *)(eth_hdr + 1); > + x0 =3D ipv4_hdr->dst_addr; > + ipv4_flag[0] =3D pkt[0]->packet_type & RTE_PTYPE_L3_IPV4; > + > + rte_compiler_barrier(); > + eth_hdr =3D rte_pktmbuf_mtod(pkt[1], struct ether_hdr *); > + ipv4_hdr =3D (struct ipv4_hdr *)(eth_hdr + 1); > + x1 =3D ipv4_hdr->dst_addr; > + ipv4_flag[0] &=3D pkt[1]->packet_type; > + > + rte_compiler_barrier(); > + eth_hdr =3D rte_pktmbuf_mtod(pkt[2], struct ether_hdr *); > + ipv4_hdr =3D (struct ipv4_hdr *)(eth_hdr + 1); > + x2 =3D ipv4_hdr->dst_addr; > + ipv4_flag[0] &=3D pkt[2]->packet_type; > + > + rte_compiler_barrier(); > + eth_hdr =3D rte_pktmbuf_mtod(pkt[3], struct ether_hdr *); > + ipv4_hdr =3D (struct ipv4_hdr *)(eth_hdr + 1); > + x3 =3D ipv4_hdr->dst_addr; > + ipv4_flag[0] &=3D pkt[3]->packet_type; > + > + rte_compiler_barrier(); > + dip[0] =3D (vector unsigned int){x0, x1, x2, x3}; } > + > +/* > + * Lookup into LPM for destination port. > + * If lookup fails, use incoming port (portid) as destination port. > + */ > +static inline void > +processx4_step2(const struct lcore_conf *qconf, > + vector unsigned int dip, > + uint32_t ipv4_flag, > + uint8_t portid, > + struct rte_mbuf *pkt[FWDSTEP], > + uint16_t dprt[FWDSTEP]) > +{ > + rte_xmm_t dst; > + const vector unsigned char bswap_mask =3D (vector unsigned char){ > + 3, 2, 1, 0, > + 7, 6, 5, 4, > + 11, 10, 9, 8, > + 15, 14, 13, 12}; > + > + /* Byte swap 4 IPV4 addresses. */ > + dip =3D (vector unsigned int)vec_perm(*(vector unsigned char *)&dip, > + (vector unsigned char){}, bswap_mask); > + > + /* if all 4 packets are IPV4. */ > + if (likely(ipv4_flag)) { > + rte_lpm_lookupx4(qconf->ipv4_lookup_struct, (xmm_t)dip, > + (uint32_t *)&dst, portid); > + /* get rid of unused upper 16 bit for each dport. */ > + dst.x =3D (xmm_t)vec_packs(dst.x, dst.x); > + *(uint64_t *)dprt =3D dst.u64[0]; > + } else { > + dst.x =3D (xmm_t)dip; > + dprt[0] =3D lpm_get_dst_port_with_ipv4(qconf, pkt[0], > + dst.u32[0], portid); > + dprt[1] =3D lpm_get_dst_port_with_ipv4(qconf, pkt[1], > + dst.u32[1], portid); > + dprt[2] =3D lpm_get_dst_port_with_ipv4(qconf, pkt[2], > + dst.u32[2], portid); > + dprt[3] =3D lpm_get_dst_port_with_ipv4(qconf, pkt[3], > + dst.u32[3], portid); > + } > +} > + > +/* > + * Buffer optimized handling of packets, invoked > + * from main_loop. > + */ > +static inline void > +l3fwd_lpm_send_packets(int nb_rx, struct rte_mbuf **pkts_burst, > + uint8_t portid, struct lcore_conf *qconf) { > + int32_t j; > + uint16_t dst_port[MAX_PKT_BURST]; > + vector unsigned int dip[MAX_PKT_BURST / FWDSTEP]; > + uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP]; > + const int32_t k =3D RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); > + > + for (j =3D 0; j !=3D k; j +=3D FWDSTEP) > + processx4_step1(&pkts_burst[j], &dip[j / FWDSTEP], > + &ipv4_flag[j / FWDSTEP]); > + > + for (j =3D 0; j !=3D k; j +=3D FWDSTEP) > + processx4_step2(qconf, dip[j / FWDSTEP], > + ipv4_flag[j / FWDSTEP], > + portid, &pkts_burst[j], &dst_port[j]); > + > + /* Classify last up to 3 packets one by one */ > + switch (nb_rx % FWDSTEP) { > + case 3: > + dst_port[j] =3D lpm_get_dst_port(qconf, pkts_burst[j], portid); > + j++; > + /* fall-through */ > + case 2: > + dst_port[j] =3D lpm_get_dst_port(qconf, pkts_burst[j], portid); > + j++; > + /* fall-through */ > + case 1: > + dst_port[j] =3D lpm_get_dst_port(qconf, pkts_burst[j], portid); > + j++; > + /* fall-through */ > + } > + > + send_packets_multi(qconf, pkts_burst, dst_port, nb_rx); } > + > +#endif /* __L3FWD_LPM_ALTIVEC_H__ */ > -- > 1.9.1 Acked-by: Chao Zhu >