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__ */
> +
prev parent 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).