All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Chao Zhu" <chaozhu@linux.vnet.ibm.com>
To: "'Gowrishankar'" <gowrishankar.m@linux.vnet.ibm.com>, <dev@dpdk.org>
Cc: "'Tomasz Kantecki'" <tomasz.kantecki@intel.com>
Subject: Re: [PATCH v2] examples/l3fwd: optimised packet processing on powerpc
Date: Thu, 28 Sep 2017 09:59:50 +0800	[thread overview]
Message-ID: <000901d337fd$79110b10$6b332130$@linux.vnet.ibm.com> (raw)
In-Reply-To: <da62dfab60bd883cfd7af6216ea7dd45f051f5a5.1505986146.git.gowrishankar.m@linux.vnet.ibm.com>

> -----Original Message-----
> From: Gowrishankar [mailto:gowrishankar.m@linux.vnet.ibm.com]
> Sent: 2017年9月21日 18:05
> To: dev@dpdk.org
> Cc: Chao Zhu <chaozhu@linux.vnet.ibm.com>; Tomasz Kantecki
> <tomasz.kantecki@intel.com>; Gowrishankar Muthukrishnan
> <gowrishankar.m@linux.vnet.ibm.com>
> Subject: [PATCH v2] examples/l3fwd: optimised packet processing on powerpc
> 
> From: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
> 
> This patch adds altivec support for lpm packet processing in powerpc.
> 
> Signed-off-by: Gowrishankar Muthukrishnan
> <gowrishankar.m@linux.vnet.ibm.com>
> ---
> v2:
>  * coding style standards
> 
>  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
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a0cd75e..0010b6c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -168,6 +168,7 @@ M: Chao Zhu <chaozhu@linux.vnet.ibm.com>
>  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
> 
>  Intel x86
>  M: Bruce Richardson <bruce.richardson@intel.com> 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] = rte_pktmbuf_mtod(pkt[0], vector unsigned int *);
> +	p[1] = rte_pktmbuf_mtod(pkt[1], vector unsigned int *);
> +	p[2] = rte_pktmbuf_mtod(pkt[2], vector unsigned int *);
> +	p[3] = rte_pktmbuf_mtod(pkt[3], vector unsigned int *);
> +
> +	ve[0] = (vector unsigned int)val_eth[dst_port[0]];
> +	te[0] = *p[0];
> +
> +	ve[1] = (vector unsigned int)val_eth[dst_port[1]];
> +	te[1] = *p[1];
> +
> +	ve[2] = (vector unsigned int)val_eth[dst_port[2]];
> +	te[2] = *p[2];
> +
> +	ve[3] = (vector unsigned int)val_eth[dst_port[3]];
> +	te[3] = *p[3];
> +
> +	/* Update first 12 bytes, keep rest bytes intact. */
> +	te[0] = (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] = (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] = (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] = (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] = te[0];
> +	*p[1] = te[1];
> +	*p[2] = te[2];
> +	*p[3] = 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[] = {a, b, c, d,, e, ... }
> + * dp1 should contain: <a, b, c, d>, dp2: <b, c, d, e>.
> + * 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 = (void *)pn;
> +
> +	int32_t v;
> +
> +	v = vec_any_eq(dp1, dp2);
> +
> +
> +	/* update last port counter. */
> +	lp[0] += gptbl[v].lpv;
> +
> +	/* if dest port value has changed. */
> +	if (v != GRPMSK) {
> +		pnum->u64 = gptbl[v].pnum;
> +		pnum->u16[FWDSTEP] = 1;
> +		lp = 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 = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
> +
> +	te = *(vector unsigned int *)eth_hdr;
> +	ve = (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 = (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 = 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 = 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 = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP);
> +	if (k != 0) {
> +		vector unsigned short dp1, dp2;
> +
> +		lp = pnum;
> +		lp[0] = 1;
> +
> +		processx4_step3(pkts_burst, dst_port);
> +
> +		/* dp1: <d[0], d[1], d[2], d[3], ... > */
> +		dp1 = *(vector unsigned short *)dst_port;
> +
> +		for (j = FWDSTEP; j != k; j += FWDSTEP) {
> +			processx4_step3(&pkts_burst[j], &dst_port[j]);
> +
> +			/*
> +			 * dp2:
> +			 * <d[j-3], d[j-2], d[j-1], d[j], ... >
> +			 */
> +			dp2 = *((vector unsigned short *)
> +					&dst_port[j - FWDSTEP + 1]);
> +			lp  = port_groupx4(&pnum[j - FWDSTEP], lp, dp1,
dp2);
> +
> +			/*
> +			 * dp1:
> +			 * <d[j], d[j+1], d[j+2], d[j+3], ... >
> +			 */
> +			dp1 = vec_sro(dp2, (vector unsigned char) {
> +				0, 0, 0, 0, 0, 0, 0, 0,
> +				0, 0, 0, (FWDSTEP - 1) *
sizeof(dst_port[0])});
> +		}
> +
> +		/*
> +		 * dp2: <d[j-3], d[j-2], d[j-1], d[j-1], ... >
> +		 */
> +		dp2 = vec_perm(dp1, (vector unsigned short){},
> +				(vector unsigned char){0xf9});
> +		lp  = port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2);
> +
> +		/*
> +		 * remove values added by the last repeated
> +		 * dst port.
> +		 */
> +		lp[0]--;
> +		dlp = dst_port[j - 1];
> +	} else {
> +		/* set dlp and lp to the never used values. */
> +		dlp = BAD_PORT - 1;
> +		lp = 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 = 0; j < nb_rx; j += k) {
> +
> +		int32_t m;
> +		uint16_t pn;
> +
> +		pn = dst_port[j];
> +		k = pnum[j];
> +
> +		if (likely(pn != BAD_PORT))
> +			send_packetsx4(qconf, pn, pkts_burst + j, k);
> +		else
> +			for (m = j; m != 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 == 0)
>  				continue;
> 
> -#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 = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *);
> +	ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
> +	x0 = ipv4_hdr->dst_addr;
> +	ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4;
> +
> +	rte_compiler_barrier();
> +	eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *);
> +	ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
> +	x1 = ipv4_hdr->dst_addr;
> +	ipv4_flag[0] &= pkt[1]->packet_type;
> +
> +	rte_compiler_barrier();
> +	eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *);
> +	ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
> +	x2 = ipv4_hdr->dst_addr;
> +	ipv4_flag[0] &= pkt[2]->packet_type;
> +
> +	rte_compiler_barrier();
> +	eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *);
> +	ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
> +	x3 = ipv4_hdr->dst_addr;
> +	ipv4_flag[0] &= pkt[3]->packet_type;
> +
> +	rte_compiler_barrier();
> +	dip[0] = (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 = (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 = (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 = (xmm_t)vec_packs(dst.x, dst.x);
> +		*(uint64_t *)dprt = dst.u64[0];
> +	} else {
> +		dst.x = (xmm_t)dip;
> +		dprt[0] = lpm_get_dst_port_with_ipv4(qconf, pkt[0],
> +							dst.u32[0], portid);
> +		dprt[1] = lpm_get_dst_port_with_ipv4(qconf, pkt[1],
> +							dst.u32[1], portid);
> +		dprt[2] = lpm_get_dst_port_with_ipv4(qconf, pkt[2],
> +							dst.u32[2], portid);
> +		dprt[3] = 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 = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP);
> +
> +	for (j = 0; j != k; j += FWDSTEP)
> +		processx4_step1(&pkts_burst[j], &dip[j / FWDSTEP],
> +				&ipv4_flag[j / FWDSTEP]);
> +
> +	for (j = 0; j != k; j += 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] = lpm_get_dst_port(qconf, pkts_burst[j],
portid);
> +		j++;
> +		/* fall-through */
> +	case 2:
> +		dst_port[j] = lpm_get_dst_port(qconf, pkts_burst[j],
portid);
> +		j++;
> +		/* fall-through */
> +	case 1:
> +		dst_port[j] = 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 <chaozhu@linux.vnet.ibm.com>
>

  reply	other threads:[~2017-09-28  1:59 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-21  8:37 [PATCH] examples/l3fwd: optimised packet processing on powerpc Gowrishankar
2017-09-21 10:05 ` [PATCH v2] " Gowrishankar
2017-09-28  1:59   ` Chao Zhu [this message]
2017-10-13 22:52     ` Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='000901d337fd$79110b10$6b332130$@linux.vnet.ibm.com' \
    --to=chaozhu@linux.vnet.ibm.com \
    --cc=dev@dpdk.org \
    --cc=gowrishankar.m@linux.vnet.ibm.com \
    --cc=tomasz.kantecki@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.