DPDK patches and discussions
 help / color / mirror / Atom feed
From: Jerin Jacob <jerinjacobk@gmail.com>
To: Sunil Kumar Kori <skori@marvell.com>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH] examples/l2fwd-event: add l2fwd with eventdev mode
Date: Fri, 13 Sep 2019 14:54:47 +0530	[thread overview]
Message-ID: <CALBAE1M7PaYqsZTpFFp9vgvk2zHiHWzA2V=UaGMLGTkuhnXGyg@mail.gmail.com> (raw)
In-Reply-To: <1567758021-8631-2-git-send-email-skori@marvell.com>

On Fri, Sep 6, 2019 at 1:50 PM Sunil Kumar Kori <skori@marvell.com> wrote:
>
> Patchset adds a new application to demonstrate usage of poll
> and eventdev mode.
>
> Following is the summary of newly added features:
> 1. Exposing following new command line parameters.
>  - mode: It dictates the mode of operation i.e. poll or eventdev.
>  - eventq_sync: It dictates eventq synchronization method i.e.
>                 atomic or ordered. Currently only atomic and
>                 ordered methods are implemented.
>
> 2. By default, application will be working into eventdev mode.
> 3. All the eventdev resources are initialized with default values.
>         no configuration are exposed to the user.
>
>         Following is the summary of default configuration:
>          - Single instance of eventdev supported.
>          - Number of event ports are equal to number of worker thread.
>          - Number of event queue are equal number of ethernet ports.
>          - Each event port is linked to all existing event queues.
>          - Dedicated Rx adapter for each Ethernet port and all Ethernet
>                 port Rx queues are added to respective Rx adapter.
>          - Dedicated Tx adapter for each Ethernet port and all Ethernet
>                 port Rx queues are added to respective Rx adapter.
>
> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> ---
>  examples/Makefile                     |   1 +
>  examples/l2fwd-event/Makefile         |  57 +++
>  examples/l2fwd-event/l2fwd_common.h   |  46 ++
>  examples/l2fwd-event/l2fwd_eventdev.c | 686 ++++++++++++++++++++++++++++++
>  examples/l2fwd-event/l2fwd_eventdev.h |  82 ++++
>  examples/l2fwd-event/main.c           | 771 ++++++++++++++++++++++++++++++++++
>  examples/l2fwd-event/meson.build      |  12 +

# Please add the documentation
# Split this patch to more logical patches
# Update the maintainers file
# Make sure it works with both eventdev HW and SW PMD.


>  7 files changed, 1655 insertions(+)
>  create mode 100644 examples/l2fwd-event/Makefile
>  create mode 100644 examples/l2fwd-event/l2fwd_common.h
>  create mode 100644 examples/l2fwd-event/l2fwd_eventdev.c
>  create mode 100644 examples/l2fwd-event/l2fwd_eventdev.h
>  create mode 100644 examples/l2fwd-event/main.c
>  create mode 100644 examples/l2fwd-event/meson.build
>
> diff --git a/examples/l2fwd-event/l2fwd_common.h b/examples/l2fwd-event/l2fwd_common.h
> new file mode 100644
> index 0000000..28919e4
> --- /dev/null
> +++ b/examples/l2fwd-event/l2fwd_common.h
> @@ -0,0 +1,46 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2019 Marvell International Ltd.
> + */
> +
> +#ifndef __L2FWD_COMMON_H__
> +#define __L2FWD_COMMON_H__
> +
> +#define MAX_PKT_BURST 32
> +#define MAX_RX_QUEUE_PER_LCORE 16
> +#define MAX_TX_QUEUE_PER_PORT 16
> +
> +#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
> +
> +struct lcore_queue_conf {
> +       uint32_t rx_port_list[MAX_RX_QUEUE_PER_LCORE];
> +       uint32_t n_rx_port;
> +} __rte_cache_aligned;
> +
> +/* Per-port statistics struct */
> +struct l2fwd_port_statistics {
> +       uint64_t dropped;
> +       uint64_t tx;
> +       uint64_t rx;
> +} __rte_cache_aligned;
> +
> +extern struct rte_mempool *l2fwd_pktmbuf_pool;
> +
> +extern struct rte_ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
> +
> +extern uint32_t l2fwd_enabled_port_mask;
> +
> +extern int mac_updating;
> +
> +extern uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
> +
> +extern struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
> +
> +extern volatile bool force_quit;
> +
> +extern uint64_t timer_period;

Remove all the global variable and move to common structure.

> +
> +void l2fwd_mac_updating(struct rte_mbuf *m, uint32_t dest_portid);
> +
> +void print_stats(void);
> +
> +#endif /* __L2FWD_EVENTDEV_H__ */
> diff --git a/examples/l2fwd-event/l2fwd_eventdev.c b/examples/l2fwd-event/l2fwd_eventdev.c
> new file mode 100644
> index 0000000..744040e
> --- /dev/null
> +++ b/examples/l2fwd-event/l2fwd_eventdev.c
> @@ -0,0 +1,686 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2019 Marvell International Ltd.
> + */
> +
> +#include <stdbool.h>
> +#include <getopt.h>
> +
> +#include <rte_cycles.h>
> +#include <rte_ethdev.h>
> +#include <rte_eventdev.h>
> +#include <rte_event_eth_rx_adapter.h>
> +#include <rte_event_eth_tx_adapter.h>
> +#include <rte_lcore.h>
> +#include <rte_log.h>
> +#include <rte_spinlock.h>
> +
> +#include "l2fwd_common.h"
> +#include "l2fwd_eventdev.h"
> +
> +enum {
> +       CMD_LINE_OPT_MODE_NUM = 265,
> +       CMD_LINE_OPT_EVENTQ_SYNC_NUM,
> +};
> +
> +static const struct option eventdev_lgopts[] = {
> +       {CMD_LINE_OPT_MODE, 1, 0, CMD_LINE_OPT_MODE_NUM},
> +       {CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
> +       {NULL, 0, 0, 0}
> +};
> +
> +/* Eventdev command line options */
> +int evd_argc;
> +char *evd_argv[3];
> +
> +/* Default configurations */
> +int pkt_transfer_mode = PACKET_TRANSFER_MODE_EVENTDEV;
> +int eventq_sync_mode = RTE_SCHED_TYPE_ATOMIC;
> +uint32_t num_workers = RTE_MAX_LCORE;
> +struct eventdev_resources eventdev_rsrc;

Remove global variables.


> +static struct rte_eth_conf port_config = {
> +       .rxmode = {
> +               .mq_mode = ETH_MQ_RX_RSS,
> +               .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
> +               .split_hdr_size = 0,
> +               .offloads = DEV_RX_OFFLOAD_CHECKSUM
> +       },
> +       .rx_adv_conf = {
> +               .rss_conf = {
> +                       .rss_key = NULL,
> +                       .rss_hf = ETH_RSS_IP,

RSS not required here. I understand, SW Rx adapter need  mbuf.hash so
select the same based on internal port avilable or not?

> +               }
> +       },
> +       .txmode = {
> +               .mq_mode = ETH_MQ_TX_NONE,
> +       }
> +};
> +
> +static struct rte_event_dev_config event_d_conf = {
> +       .nb_event_queues = 1,
> +       .nb_event_ports = RTE_MAX_LCORE,
> +       .nb_events_limit  = 4096,
> +       .nb_event_queue_flows = 1024,
> +       .nb_event_port_dequeue_depth = 128,
> +       .nb_event_port_enqueue_depth = 128
> +};
> +
> +static struct rte_event_port_conf event_p_conf = {
> +       .dequeue_depth = 32,
> +       .enqueue_depth = 32,
> +       .new_event_threshold = 4096
> +};
> +
> +static struct rte_event_queue_conf event_q_conf = {
> +       .nb_atomic_flows = 1024,
> +       .nb_atomic_order_sequences = 1024,
> +       .event_queue_cfg = 0,
> +       .schedule_type = RTE_SCHED_TYPE_ATOMIC,
> +       .priority = RTE_EVENT_DEV_PRIORITY_HIGHEST
> +};
> +
> +static struct rte_event_eth_rx_adapter_queue_conf eth_q_conf = {
> +       .rx_queue_flags = 0,
> +       .servicing_weight = 1,
> +       .ev = {
> +               .queue_id = 0,
> +               .priority = RTE_EVENT_DEV_PRIORITY_HIGHEST,
> +               .sched_type = RTE_SCHED_TYPE_ATOMIC
> +       }
> +};

This all thing can be local to that function in the stack.

> +
> +/* Send burst of packets on an output interface */
> +static inline int send_burst_eventdev_generic(struct rte_mbuf *m[], uint16_t n,
> +                                             uint16_t event_p_id)
> +{
> +       struct rte_event events[MAX_PKT_BURST];
> +       uint8_t event_d_id;
> +       int ret, i;
> +
> +       event_d_id = eventdev_rsrc.event_d_id;

Remove the access to global variable.

> +
> +       for (i = 0; i < n; i++) {
> +               events[i].queue_id = 0;

It should be Tx queue.

> +               events[i].op = RTE_EVENT_OP_FORWARD;
> +               events[i].mbuf = m[i];
> +       }
> +
> +       ret = rte_event_enqueue_burst(event_d_id, event_p_id, events, n);
> +       if (unlikely(ret < n)) {
> +               do {
> +                       rte_pktmbuf_free(m[ret]);
> +               } while (++ret < n);
> +       }
> +
> +       return 0;
> +}
> +
> +/* Send burst of packets on an output interface */
> +static inline int send_burst_eventdev_adapter(struct rte_mbuf *m[], uint16_t n,
> +                                             uint16_t event_p_id)
> +{
> +       struct rte_event events[MAX_PKT_BURST];
> +       uint8_t event_d_id;
> +       int32_t ret, i;
> +
> +       event_d_id = eventdev_rsrc.event_d_id;
> +
> +       for (i = 0; i < n; i++) {
> +               events[i].queue_id = 0;
> +               events[i].op = RTE_EVENT_OP_FORWARD;
> +               events[i].mbuf = m[i];
> +               rte_event_eth_tx_adapter_txq_set(events[i].mbuf, 0);
> +       }

A lot of common code between send_burst_eventdev_generic()  and this function.
Please use compile-time builtin constant scheme create runtime workers.


> +
> +       ret = rte_event_eth_tx_adapter_enqueue(event_d_id, event_p_id,
> +                                              events, n);
> +       if (unlikely(ret < n)) {
> +               do {
> +                       rte_pktmbuf_free(m[ret]);
> +               } while (++ret < n);
> +       }
> +
> +       return 0;
> +}
> +

> +static void
> +l2fwd_eventdev_forward(struct rte_mbuf *m[], uint32_t portid,
> +                      uint16_t nb_rx, uint16_t event_p_id)
> +{
> +       uint32_t dst_port, i;
> +
> +       dst_port = l2fwd_dst_ports[portid];
> +
> +       for (i = 0; i < nb_rx; i++) {
> +               if (mac_updating)
> +                       l2fwd_mac_updating(m[i], dst_port);
> +
> +               m[i]->port = dst_port;
> +       }
> +
> +       port_statistics[dst_port].tx += nb_rx;
> +       eventdev_rsrc.send_burst_eventdev(m, nb_rx, event_p_id);

Remove this function pointer scheme.


> +}
> +
> +/* main eventdev processing loop */
> +void l2fwd_main_loop_eventdev(void)

Have seperate worker for burst and non burst.

> +{
> +       uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
> +       struct rte_event events[MAX_PKT_BURST];
> +       struct rte_mbuf *mbuf[MAX_PKT_BURST];
> +       uint32_t i, j = 0, nb_rx;
> +       uint16_t event_d_id;
> +       uint16_t event_p_id;
> +       uint32_t lcore_id;
> +       uint16_t deq_len;
> +       uint32_t portid;
> +
> +       prev_tsc = 0;
> +       timer_tsc = 0;
> +
> +       /* Assign dedicated event port for enqueue/dequeue operation */
> +       deq_len = event_d_conf.nb_event_port_dequeue_depth;
> +       event_d_id = eventdev_rsrc.event_d_id;
> +       event_p_id = get_free_event_port();
> +       lcore_id = rte_lcore_id();
> +
> +       RTE_LOG(INFO, L2FWD, "entering eventdev main loop on lcore %u\n",
> +               lcore_id);
> +
> +       while (!force_quit) {
> +
> +               /* if timer is enabled */
> +               if (timer_period > 0) {
> +                       cur_tsc = rte_rdtsc();
> +                       diff_tsc = cur_tsc - prev_tsc;
> +
> +                       /* advance the timer */
> +                       timer_tsc += diff_tsc;
> +
> +                       /* if timer has reached its timeout */
> +                       if (unlikely(timer_tsc >= timer_period)) {
> +
> +                               /* do this only on master core */
> +                               if (lcore_id == rte_get_master_lcore()) {
> +                                       print_stats();
> +
> +                                       /* reset the timer */
> +                                       timer_tsc = 0;
> +                               }
> +                       }
> +                       prev_tsc = cur_tsc;
> +               }
> +
> +               /* Read packet from eventdev */
> +               nb_rx = rte_event_dequeue_burst(event_d_id, event_p_id,
> +                                               events, deq_len, 0);
> +               if (nb_rx == 0) {
> +                       rte_pause();
> +                       continue;
> +               }
> +
> +               for (i = 0; i < nb_rx; i++) {
> +                       mbuf[i] = events[i].mbuf;
> +                       rte_prefetch0(rte_pktmbuf_mtod(mbuf[i], void *));

Please prefetch ahead.

> +               }
> +
> +               portid = mbuf[0]->port;
> +               port_statistics[portid].rx++;
> +               for (i = 1; i < nb_rx; i++) {
> +                       if (portid != mbuf[i]->port) {
> +                               l2fwd_eventdev_forward(&mbuf[j], portid, i - j,
> +                                                      event_p_id);
> +                               j = i;
> +                               portid = mbuf[i]->port;
> +                       }
> +                       port_statistics[portid].rx++;
> +               }
> +
> +               /* Send remaining packets */
> +               l2fwd_eventdev_forward(&mbuf[j], portid, i - j, event_p_id);
> +       }
> +}
> +
> +#define EVENT_DEV_PARAM_PRESENT        0x8000  /* Random value*/

I think, we can remove this.


> +
> +/* Packet transfer mode of the application */
> +#define PACKET_TRANSFER_MODE_POLL  1
> +#define PACKET_TRANSFER_MODE_EVENTDEV  2
> +
> +#define CMD_LINE_OPT_MODE "mode"
> +#define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sync"
> +
> +typedef int (*tx_eventdev_t)(struct rte_mbuf *m[], uint16_t n, uint16_t port);
> +
> +struct eventdev_queues {
> +       uint8_t *event_q_id;
> +       uint8_t nb_queues;
> +};
> +
> +struct eventdev_ports {
> +       uint8_t *event_p_id;
> +       uint8_t nb_ports;
> +       rte_spinlock_t lock;
> +};
> +
> +struct eventdev_rx_adptr {
> +       uint8_t nb_rx_adptr;
> +       uint8_t *rx_adptr;
> +};
> +
> +struct eventdev_tx_adptr {
> +       uint8_t nb_tx_adptr;
> +       uint8_t *tx_adptr;
> +};
> +
> +struct eventdev_resources {
> +       tx_eventdev_t   send_burst_eventdev;
> +       struct eventdev_rx_adptr rx_adptr;
> +       struct eventdev_tx_adptr tx_adptr;
> +       struct eventdev_queues evq;
> +       struct eventdev_ports evp;
> +       uint8_t event_d_id;
> +};
> +
> +extern int pkt_transfer_mode;
> +extern int eventq_sync_mode;
> +extern struct eventdev_resources eventdev_rsrc;
> +extern int evd_argc;
> +extern char *evd_argv[3];

Remove global variables.


> +
> +/* Event device and required resource setup function */
> +int eventdev_resource_setup(int argc, char **argv);
> +
> +/* Returns next available event port */
> +int get_free_event_port(void);
> +
> +/* Event processing function */
> +void l2fwd_main_loop_eventdev(void);
> +
> +#endif /* __L2FWD_EVENTDEV_H__ */
> +

      reply	other threads:[~2019-09-13  9:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-06  8:20 [dpdk-dev] [PATCH] add l2fwd-event application Sunil Kumar Kori
2019-09-06  8:20 ` [dpdk-dev] [PATCH] examples/l2fwd-event: add l2fwd with eventdev mode Sunil Kumar Kori
2019-09-13  9:24   ` Jerin Jacob [this message]

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='CALBAE1M7PaYqsZTpFFp9vgvk2zHiHWzA2V=UaGMLGTkuhnXGyg@mail.gmail.com' \
    --to=jerinjacobk@gmail.com \
    --cc=dev@dpdk.org \
    --cc=skori@marvell.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).