From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 7E2B55A73 for ; Mon, 30 Mar 2015 12:23:07 +0200 (CEST) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga103.fm.intel.com with ESMTP; 30 Mar 2015 03:22:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,493,1422950400"; d="scan'208";a="474358227" Received: from irsmsx108.ger.corp.intel.com ([163.33.3.3]) by FMSMGA003.fm.intel.com with ESMTP; 30 Mar 2015 03:22:58 -0700 Received: from irsmsx104.ger.corp.intel.com ([169.254.5.132]) by IRSMSX108.ger.corp.intel.com ([163.33.3.3]) with mapi id 14.03.0224.002; Mon, 30 Mar 2015 11:22:56 +0100 From: "Walukiewicz, Miroslaw" To: "Gajdzica, MaciejX T" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH 2/3] port: added ethdev_writer_nodrop port Thread-Index: AQHQatFwOYLJjcxM70qguGX2kHt5r500zaKQ Date: Mon, 30 Mar 2015 10:22:55 +0000 Message-ID: <7C4248CAE043B144B1CD242D275626532FE81E11@IRSMSX104.ger.corp.intel.com> References: <1427709404-28921-1-git-send-email-maciejx.t.gajdzica@intel.com> <1427709404-28921-3-git-send-email-maciejx.t.gajdzica@intel.com> In-Reply-To: <1427709404-28921-3-git-send-email-maciejx.t.gajdzica@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [163.33.239.182] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH 2/3] port: added ethdev_writer_nodrop port X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Mar 2015 10:23:08 -0000 > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Maciej Gajdzica > Sent: Monday, March 30, 2015 11:57 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH 2/3] port: added ethdev_writer_nodrop port >=20 > When ethdev_writer_nodrop port fails to send data, it tries to resend. > Operation > is aborted when maximum number of retries is reached. >=20 > --- > lib/librte_port/rte_port_ethdev.c | 230 > +++++++++++++++++++++++++++++++++++++ > lib/librte_port/rte_port_ethdev.h | 19 +++ > 2 files changed, 249 insertions(+) >=20 > diff --git a/lib/librte_port/rte_port_ethdev.c > b/lib/librte_port/rte_port_ethdev.c > index d014913..1f77cb5 100644 > --- a/lib/librte_port/rte_port_ethdev.c > +++ b/lib/librte_port/rte_port_ethdev.c > @@ -31,6 +31,7 @@ > * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > */ > #include > +#include >=20 > #include > #include > @@ -288,6 +289,227 @@ rte_port_ethdev_writer_free(void *port) > } >=20 > /* > + * Port ETHDEV Writer Nodrop > + */ > +#define RTE_PORT_ETHDEV_WRITER_NODROP_APPROACH 1 > + > +struct rte_port_ethdev_writer_nodrop { > + struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; > + uint32_t tx_burst_sz; > + uint16_t tx_buf_count; > + uint64_t bsz_mask; > + uint64_t n_retries; > + uint16_t queue_id; > + uint8_t port_id; > +}; > + > +static void * > +rte_port_ethdev_writer_nodrop_create(void *params, int socket_id) > +{ > + struct rte_port_ethdev_writer_nodrop_params *conf =3D > + (struct rte_port_ethdev_writer_nodrop_params *) > params; > + struct rte_port_ethdev_writer_nodrop *port; > + > + /* Check input parameters */ > + if ((conf =3D=3D NULL) || > + (conf->tx_burst_sz =3D=3D 0) || > + (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || > + (!rte_is_power_of_2(conf->tx_burst_sz))) { > + RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", > __func__); > + return NULL; > + } > + > + /* Memory allocation */ > + port =3D rte_zmalloc_socket("PORT", sizeof(*port), > + RTE_CACHE_LINE_SIZE, socket_id); > + if (port =3D=3D NULL) { > + RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", > __func__); > + return NULL; > + } > + > + /* Initialization */ > + port->port_id =3D conf->port_id; > + port->queue_id =3D conf->queue_id; > + port->tx_burst_sz =3D conf->tx_burst_sz; > + port->tx_buf_count =3D 0; > + port->bsz_mask =3D 1LLU << (conf->tx_burst_sz - 1); > + > + /* > + * When n_retries is 0 it means that we should wait for every packet > to > + * send no matter how many retries should it take. To limit number of > + * branches in fast path, we use UINT64_MAX instead of branching. > + */ > + port->n_retries =3D (conf->n_retries =3D=3D 0) ? UINT64_MAX : conf- > >n_retries; > + > + return port; > +} > + > +static inline void > +send_burst_nodrop(struct rte_port_ethdev_writer_nodrop *p) > +{ > + uint32_t nb_tx =3D 0, i; > + > + nb_tx =3D rte_eth_tx_burst(p->port_id, p->queue_id, p->tx_buf, > + p->tx_buf_count); > + > + /* We sent all the packets in a first try */ > + if (nb_tx >=3D p->tx_buf_count) > + return; > + > + for (i =3D 0; i < p->n_retries; i++) { > + nb_tx +=3D rte_eth_tx_burst(p->port_id, p->queue_id, > + p->tx_buf + nb_tx, p- > >tx_buf_count - nb_tx); > + > + /* We sent all the packets in more than one try */ > + if (nb_tx >=3D p->tx_buf_count) > + return; > + I think that this method will work only for single output port in pipeline.= =20 For multiport configurations especially when TX HW rings are continuously o= verloaded=20 The driver will wait all the time on this loop.=20 As example Imagine that you have single TX thread in DPDK pipeline and you = have multiple output Ethernet ports with different speeds 10G and 40G calling +send_burst_nodrop - both overloaded. The effect will b= e that 10G port will wait most of time and limit the speed of the 40G so=20 The effect expected is that 40G works on 10G speed ;-( Similar effect possible when same speed ports are accessed by send_burst_no= drop and the DCB/or any other L2 flow control is enabled that limits the TX= speed The speed of whole system will be the speed of the slowest link. } > + > + /* We didn't send the packets in maximum allowed attempts */ > + for ( ; nb_tx < p->tx_buf_count; nb_tx++) > + rte_pktmbuf_free(p->tx_buf[nb_tx]); > + > + p->tx_buf_count =3D 0; > +} > + > +static int > +rte_port_ethdev_writer_nodrop_tx(void *port, struct rte_mbuf *pkt) > +{ > + struct rte_port_ethdev_writer_nodrop *p =3D > + (struct rte_port_ethdev_writer_nodrop *) port; > + > + p->tx_buf[p->tx_buf_count++] =3D pkt; > + if (p->tx_buf_count >=3D p->tx_burst_sz) > + send_burst_nodrop(p); > + > + return 0; > +} > + > +#if RTE_PORT_ETHDEV_WRITER_NODROP_APPROACH =3D=3D 0 > + > +static int > +rte_port_ethdev_writer_nodrop_tx_bulk(void *port, > + struct rte_mbuf **pkts, > + uint64_t pkts_mask) > +{ > + struct rte_port_ethdev_writer_nodrop *p =3D > + (struct rte_port_ethdev_writer_nodrop *) port; > + > + if ((pkts_mask & (pkts_mask + 1)) =3D=3D 0) { > + uint64_t n_pkts =3D __builtin_popcountll(pkts_mask); > + uint32_t i; > + > + for (i =3D 0; i < n_pkts; i++) { > + struct rte_mbuf *pkt =3D pkts[i]; > + > + p->tx_buf[p->tx_buf_count++] =3D pkt; > + if (p->tx_buf_count >=3D p->tx_burst_sz) > + send_burst_nodrop(p); > + } > + } else { > + for ( ; pkts_mask; ) { > + uint32_t pkt_index =3D __builtin_ctzll(pkts_mask); > + uint64_t pkt_mask =3D 1LLU << pkt_index; > + struct rte_mbuf *pkt =3D pkts[pkt_index]; > + > + p->tx_buf[p->tx_buf_count++] =3D pkt; > + if (p->tx_buf_count >=3D p->tx_burst_sz) > + send_burst_nodrop(p); > + pkts_mask &=3D ~pkt_mask; > + } > + } > + > + return 0; > +} > + > +#elif RTE_PORT_ETHDEV_WRITER_NODROP_APPROACH =3D=3D 1 > + > +static int > +rte_port_ethdev_writer_nodrop_tx_bulk(void *port, > + struct rte_mbuf **pkts, > + uint64_t pkts_mask) > +{ > + struct rte_port_ethdev_writer_nodrop *p =3D > + (struct rte_port_ethdev_writer_nodrop *) port; > + > + uint32_t bsz_mask =3D p->bsz_mask; > + uint32_t tx_buf_count =3D p->tx_buf_count; > + uint64_t expr =3D (pkts_mask & (pkts_mask + 1)) | > + ((pkts_mask & bsz_mask) ^ bsz_mask); > + > + if (expr =3D=3D 0) { > + uint64_t n_pkts =3D __builtin_popcountll(pkts_mask); > + uint32_t n_pkts_ok; > + > + if (tx_buf_count) > + send_burst_nodrop(p); > + > + n_pkts_ok =3D rte_eth_tx_burst(p->port_id, p->queue_id, pkts, > + n_pkts); > + > + if (n_pkts_ok >=3D n_pkts) > + return 0; > + > + /* > + * If we didnt manage to send all packets in single burst, move > + * remaining packets to the buffer and call send burst. > + */ > + for (; n_pkts_ok < n_pkts; n_pkts_ok++) { > + struct rte_mbuf *pkt =3D pkts[n_pkts_ok]; > + p->tx_buf[p->tx_buf_count++] =3D pkt; > + } > + send_burst_nodrop(p); > + } else { > + for ( ; pkts_mask; ) { > + uint32_t pkt_index =3D __builtin_ctzll(pkts_mask); > + uint64_t pkt_mask =3D 1LLU << pkt_index; > + struct rte_mbuf *pkt =3D pkts[pkt_index]; > + > + p->tx_buf[tx_buf_count++] =3D pkt; > + pkts_mask &=3D ~pkt_mask; > + } > + > + p->tx_buf_count =3D tx_buf_count; > + if (tx_buf_count >=3D p->tx_burst_sz) > + send_burst_nodrop(p); > + } > + > + return 0; > +} > + > +#else > + > +#error Invalid value for RTE_PORT_ETHDEV_WRITER_NODROP_APPROACH > + > +#endif > + > +static int > +rte_port_ethdev_writer_nodrop_flush(void *port) > +{ > + struct rte_port_ethdev_writer_nodrop *p =3D > + (struct rte_port_ethdev_writer_nodrop *) port; > + > + if (p->tx_buf_count > 0) > + send_burst_nodrop(p); > + > + return 0; > +} > + > +static int > +rte_port_ethdev_writer_nodrop_free(void *port) > +{ > + if (port =3D=3D NULL) { > + RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); > + return -EINVAL; > + } > + > + rte_port_ethdev_writer_nodrop_flush(port); > + rte_free(port); > + > + return 0; > +} > + > +/* > * Summary of port operations > */ > struct rte_port_in_ops rte_port_ethdev_reader_ops =3D { > @@ -303,3 +525,11 @@ struct rte_port_out_ops > rte_port_ethdev_writer_ops =3D { > .f_tx_bulk =3D rte_port_ethdev_writer_tx_bulk, > .f_flush =3D rte_port_ethdev_writer_flush, > }; > + > +struct rte_port_out_ops rte_port_ethdev_writer_nodrop_ops =3D { > + .f_create =3D rte_port_ethdev_writer_nodrop_create, > + .f_free =3D rte_port_ethdev_writer_nodrop_free, > + .f_tx =3D rte_port_ethdev_writer_nodrop_tx, > + .f_tx_bulk =3D rte_port_ethdev_writer_nodrop_tx_bulk, > + .f_flush =3D rte_port_ethdev_writer_nodrop_flush, > +}; > diff --git a/lib/librte_port/rte_port_ethdev.h > b/lib/librte_port/rte_port_ethdev.h > index af67a12..201a79e 100644 > --- a/lib/librte_port/rte_port_ethdev.h > +++ b/lib/librte_port/rte_port_ethdev.h > @@ -79,6 +79,25 @@ struct rte_port_ethdev_writer_params { > /** ethdev_writer port operations */ > extern struct rte_port_out_ops rte_port_ethdev_writer_ops; >=20 > +/** ethdev_writer_nodrop port parameters */ > +struct rte_port_ethdev_writer_nodrop_params { > + /** NIC RX port ID */ > + uint8_t port_id; > + > + /** NIC RX queue ID */ > + uint16_t queue_id; > + > + /** Recommended burst size to NIC TX queue. The actual burst size > can be > + bigger or smaller than this value. */ > + uint32_t tx_burst_sz; > + > + /** Maximum number of retries, 0 for no limit */ > + uint32_t n_retries; > +}; > + > +/** ethdev_writer_nodrop port operations */ > +extern struct rte_port_out_ops rte_port_ethdev_writer_nodrop_ops; > + > #ifdef __cplusplus > } > #endif > -- > 1.7.9.5