On Thu, Oct 3, 2019 at 2:29 AM <pbhagavatula@marvell.com> wrote:
>
> From: Pavan Nikhilesh <pbhagavatula@marvell.com>
>
> Add event dev main loop based on enabled l2fwd options and eventdev
> capabilities.
>
> Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
> ---
> examples/l2fwd-event/l2fwd_common.c | 6 +
> examples/l2fwd-event/l2fwd_common.h | 2 +
> examples/l2fwd-event/l2fwd_event.c | 294 ++++++++++++++++++++++++++++
> examples/l2fwd-event/l2fwd_event.h | 2 +
> examples/l2fwd-event/main.c | 6 +-
> 5 files changed, 309 insertions(+), 1 deletion(-)
>
> diff --git a/examples/l2fwd-event/l2fwd_common.c b/examples/l2fwd-event/l2fwd_common.c
> index 213652d72..40e933c91 100644
> --- a/examples/l2fwd-event/l2fwd_common.c
> +++ b/examples/l2fwd-event/l2fwd_common.c
> @@ -65,6 +65,12 @@ l2fwd_event_init_ports(struct l2fwd_resources *l2fwd_rsrc)
> uint16_t port_id;
> int ret;
>
> + if (l2fwd_rsrc->event_mode) {
> + port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
> + port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> + port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP;
> + }
> +
> /* Initialise each port */
> RTE_ETH_FOREACH_DEV(port_id) {
> struct rte_eth_conf local_port_conf = port_conf;
> diff --git a/examples/l2fwd-event/l2fwd_common.h b/examples/l2fwd-event/l2fwd_common.h
> index cdafa52c7..852c6d321 100644
> --- a/examples/l2fwd-event/l2fwd_common.h
> +++ b/examples/l2fwd-event/l2fwd_common.h
> @@ -114,7 +114,9 @@ l2fwd_get_rsrc(void)
>
> memset(l2fwd_rsrc, 0, sizeof(struct l2fwd_resources));
> l2fwd_rsrc->mac_updating = true;
> + l2fwd_rsrc->event_mode = true;
> l2fwd_rsrc->rx_queue_per_lcore = 1;
> + l2fwd_rsrc->sched_type = RTE_SCHED_TYPE_ATOMIC;
> l2fwd_rsrc->timer_period = 10 * rte_get_timer_hz();
>
> return mz->addr;
> diff --git a/examples/l2fwd-event/l2fwd_event.c b/examples/l2fwd-event/l2fwd_event.c
> index adba40069..df0b56773 100644
> --- a/examples/l2fwd-event/l2fwd_event.c
> +++ b/examples/l2fwd-event/l2fwd_event.c
> @@ -17,6 +17,12 @@
>
> #include "l2fwd_event.h"
>
> +#define L2FWD_EVENT_SINGLE 0x1
> +#define L2FWD_EVENT_BURST 0x2
> +#define L2FWD_EVENT_TX_DIRECT 0x4
> +#define L2FWD_EVENT_TX_ENQ 0x8
> +#define L2FWD_EVENT_UPDT_MAC 0x10
> +
> static inline int
> l2fwd_event_service_enable(uint32_t service_id)
> {
> @@ -128,11 +134,289 @@ l2fwd_event_capability_setup(struct l2fwd_event_resources *event_rsrc)
> l2fwd_event_set_internal_port_ops(&event_rsrc->ops);
> }
>
> +static __rte_noinline int
> +l2fwd_get_free_event_port(struct l2fwd_event_resources *event_rsrc)
> +{
> + static int index;
> + int port_id;
> +
> + rte_spinlock_lock(&event_rsrc->evp.lock);
> + if (index >= event_rsrc->evp.nb_ports) {
> + printf("No free event port is available\n");
> + return -1;
> + }
> +
> + port_id = event_rsrc->evp.event_p_id[index];
> + index++;
> + rte_spinlock_unlock(&event_rsrc->evp.lock);
> +
> + return port_id;
> +}
> +
> +static __rte_always_inline void
> +l2fwd_event_loop_single(struct l2fwd_resources *l2fwd_rsrc,
> + const uint32_t flags)
> +{
> + const uint8_t is_master = rte_get_master_lcore() == rte_lcore_id();
> + struct l2fwd_event_resources *event_rsrc = l2fwd_rsrc->event_rsrc;
> + const int port_id = l2fwd_get_free_event_port(event_rsrc);
> + uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
> + const uint64_t timer_period = l2fwd_rsrc->timer_period;
> + const uint8_t tx_q_id = event_rsrc->evq.event_q_id[
> + event_rsrc->evq.nb_queues - 1];
See below
> + const uint8_t event_d_id = event_rsrc->event_d_id;
> + struct rte_mbuf *mbuf;
> + uint16_t dst_port;
> + struct rte_event ev;
> +
> + if (port_id < 0)
> + return;
> +
> + printf("%s(): entering eventdev main loop on lcore %u\n", __func__,
> + rte_lcore_id());
> +
> + while (!l2fwd_rsrc->force_quit) {
> + /* if timer is enabled */
> + if (is_master && 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)) {
> + print_stats(l2fwd_rsrc);
> + /* reset the timer */
> + timer_tsc = 0;
> + }
> + prev_tsc = cur_tsc;
> + }
> +
> + /* Read packet from eventdev */
> + if (!rte_event_dequeue_burst(event_d_id, port_id, &ev, 1, 0))
> + continue;
> +
> +
> + mbuf = ev.mbuf;
> + dst_port = l2fwd_rsrc->dst_ports[mbuf->port];
> + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *));
> +
> + if (timer_period > 0)
> + __atomic_fetch_add(
> + &l2fwd_rsrc->port_stats[mbuf->port].rx,
> + 1, __ATOMIC_RELAXED);
> +
> + mbuf->port = dst_port;
> + if (flags & L2FWD_EVENT_UPDT_MAC)
> + l2fwd_mac_updating(mbuf, dst_port,
> + &l2fwd_rsrc->eth_addr[dst_port]);
See below
> +
> + if (flags & L2FWD_EVENT_TX_ENQ) {
> + ev.queue_id = tx_q_id;
> + ev.op = RTE_EVENT_OP_FORWARD;
> + while (rte_event_enqueue_burst(event_d_id, port_id,
> + &ev, 1) &&
> + !l2fwd_rsrc->force_quit)
> + ;
> + }
> +
> + if (flags & L2FWD_EVENT_TX_DIRECT) {
> + rte_event_eth_tx_adapter_txq_set(mbuf, 0);
> + while (!rte_event_eth_tx_adapter_enqueue(event_d_id,
> + port_id,
> + &ev, 1) &&
See below
> + !l2fwd_rsrc->force_quit)
> + ;
> + }
> +
> + if (timer_period > 0)
> + __atomic_fetch_add(
> + &l2fwd_rsrc->port_stats[mbuf->port].tx,
> + 1, __ATOMIC_RELAXED);
As style comment:
# There is a lot of multiline statements in the code, which reduce the
readability of the code. Please find below some options to reduce it.
Could you please check options to reduce it
1) shorten the structure name like
s/event_rsrc/evt_rsrc
s/l2fwd_rsrc/ rsrc
2) I think, rte_exit(EXIT_FAILURE can be replaced to rte_panic in the
application case
3) Adjusting the newline code starts
diff --git a/examples/l2fwd-event/l2fwd_event.c
b/examples/l2fwd-event/l2fwd_event.c
index df0b56773..49665a102 100644
--- a/examples/l2fwd-event/l2fwd_event.c
+++ b/examples/l2fwd-event/l2fwd_event.c
@@ -87,8 +87,8 @@ l2fwd_event_service_setup(struct l2fwd_resources *l2fwd_rsrc)
&service_id);
if (ret != -ESRCH && ret != 0)
rte_exit(EXIT_FAILURE,
- "Error in starting Rx
adapter[%d] service\n",
- event_rsrc->rx_adptr.rx_adptr[i]);
+ "Error in starting Rx adapter[%d] service\n",
+ event_rsrc->rx_adptr.rx_adptr[i]);
l2fwd_event_service_enable(service_id);
}
4) Replace code in the nested loop with static inline function so that code gets
enough space in new function.
@@ -65,6 +65,12 @@ l2fwd_event_init_ports(struct l2fwd_resources *l2fwd_rsrc)
uint16_t port_id;
int ret;
+ if (l2fwd_rsrc->event_mode) {
+ port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+ port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+ port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP;
+ }
+
/* Initialise each port */
RTE_ETH_FOREACH_DEV(port_id) {
struct rte_eth_conf local_port_conf = port_conf;
@@ -114,7 +114,9 @@ l2fwd_get_rsrc(void)
memset(l2fwd_rsrc, 0, sizeof(struct l2fwd_resources));
l2fwd_rsrc->mac_updating = true;
+ l2fwd_rsrc->event_mode = true;
l2fwd_rsrc->rx_queue_per_lcore = 1;
+ l2fwd_rsrc->sched_type = RTE_SCHED_TYPE_ATOMIC;
l2fwd_rsrc->timer_period = 10 * rte_get_timer_hz();
return mz->addr;
@@ -17,6 +17,12 @@
#include "l2fwd_event.h"
+#define L2FWD_EVENT_SINGLE 0x1
+#define L2FWD_EVENT_BURST 0x2
+#define L2FWD_EVENT_TX_DIRECT 0x4
+#define L2FWD_EVENT_TX_ENQ 0x8
+#define L2FWD_EVENT_UPDT_MAC 0x10
+
static inline int
l2fwd_event_service_enable(uint32_t service_id)
{
@@ -128,11 +134,289 @@ l2fwd_event_capability_setup(struct l2fwd_event_resources *event_rsrc)
l2fwd_event_set_internal_port_ops(&event_rsrc->ops);
}
+static __rte_noinline int
+l2fwd_get_free_event_port(struct l2fwd_event_resources *event_rsrc)
+{
+ static int index;
+ int port_id;
+
+ rte_spinlock_lock(&event_rsrc->evp.lock);
+ if (index >= event_rsrc->evp.nb_ports) {
+ printf("No free event port is available\n");
+ return -1;
+ }
+
+ port_id = event_rsrc->evp.event_p_id[index];
+ index++;
+ rte_spinlock_unlock(&event_rsrc->evp.lock);
+
+ return port_id;
+}
+
+static __rte_always_inline void
+l2fwd_event_loop_single(struct l2fwd_resources *l2fwd_rsrc,
+ const uint32_t flags)
+{
+ const uint8_t is_master = rte_get_master_lcore() == rte_lcore_id();
+ struct l2fwd_event_resources *event_rsrc = l2fwd_rsrc->event_rsrc;
+ const int port_id = l2fwd_get_free_event_port(event_rsrc);
+ uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
+ const uint64_t timer_period = l2fwd_rsrc->timer_period;
+ const uint8_t tx_q_id = event_rsrc->evq.event_q_id[
+ event_rsrc->evq.nb_queues - 1];
+ const uint8_t event_d_id = event_rsrc->event_d_id;
+ struct rte_mbuf *mbuf;
+ uint16_t dst_port;
+ struct rte_event ev;
+
+ if (port_id < 0)
+ return;
+
+ printf("%s(): entering eventdev main loop on lcore %u\n", __func__,
+ rte_lcore_id());
+
+ while (!l2fwd_rsrc->force_quit) {
+ /* if timer is enabled */
+ if (is_master && 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)) {
+ print_stats(l2fwd_rsrc);
+ /* reset the timer */
+ timer_tsc = 0;
+ }
+ prev_tsc = cur_tsc;
+ }
+
+ /* Read packet from eventdev */
+ if (!rte_event_dequeue_burst(event_d_id, port_id, &ev, 1, 0))
+ continue;
+
+
+ mbuf = ev.mbuf;
+ dst_port = l2fwd_rsrc->dst_ports[mbuf->port];
+ rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *));
+
+ if (timer_period > 0)
+ __atomic_fetch_add(
+ &l2fwd_rsrc->port_stats[mbuf->port].rx,
+ 1, __ATOMIC_RELAXED);
+
+ mbuf->port = dst_port;
+ if (flags & L2FWD_EVENT_UPDT_MAC)
+ l2fwd_mac_updating(mbuf, dst_port,
+ &l2fwd_rsrc->eth_addr[dst_port]);
+
+ if (flags & L2FWD_EVENT_TX_ENQ) {
+ ev.queue_id = tx_q_id;
+ ev.op = RTE_EVENT_OP_FORWARD;
+ while (rte_event_enqueue_burst(event_d_id, port_id,
+ &ev, 1) &&
+ !l2fwd_rsrc->force_quit)
+ ;
+ }
+
+ if (flags & L2FWD_EVENT_TX_DIRECT) {
+ rte_event_eth_tx_adapter_txq_set(mbuf, 0);
+ while (!rte_event_eth_tx_adapter_enqueue(event_d_id,
+ port_id,
+ &ev, 1) &&
+ !l2fwd_rsrc->force_quit)
+ ;
+ }
+
+ if (timer_period > 0)
+ __atomic_fetch_add(
+ &l2fwd_rsrc->port_stats[mbuf->port].tx,
+ 1, __ATOMIC_RELAXED);
+ }
+}
+
+static __rte_always_inline void
+l2fwd_event_loop_burst(struct l2fwd_resources *l2fwd_rsrc,
+ const uint32_t flags)
+{
+ const uint8_t is_master = rte_get_master_lcore() == rte_lcore_id();
+ struct l2fwd_event_resources *event_rsrc = l2fwd_rsrc->event_rsrc;
+ const int port_id = l2fwd_get_free_event_port(event_rsrc);
+ uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
+ const uint64_t timer_period = l2fwd_rsrc->timer_period;
+ const uint8_t tx_q_id = event_rsrc->evq.event_q_id[
+ event_rsrc->evq.nb_queues - 1];
+ const uint8_t event_d_id = event_rsrc->event_d_id;
+ const uint8_t deq_len = event_rsrc->deq_depth;
+ struct rte_event ev[MAX_PKT_BURST];
+ struct rte_mbuf *mbuf;
+ uint16_t nb_rx, nb_tx;
+ uint16_t dst_port;
+ uint8_t i;
+
+ if (port_id < 0)
+ return;
+
+ printf("%s(): entering eventdev main loop on lcore %u\n", __func__,
+ rte_lcore_id());
+
+ while (!l2fwd_rsrc->force_quit) {
+ /* if timer is enabled */
+ if (is_master && 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)) {
+ print_stats(l2fwd_rsrc);
+ /* reset the timer */
+ timer_tsc = 0;
+ }
+ prev_tsc = cur_tsc;
+ }
+
+ /* Read packet from eventdev */
+ nb_rx = rte_event_dequeue_burst(event_d_id, port_id, ev,
+ deq_len, 0);
+ if (nb_rx == 0)
+ continue;
+
+
+ for (i = 0; i < nb_rx; i++) {
+ mbuf = ev[i].mbuf;
+ dst_port = l2fwd_rsrc->dst_ports[mbuf->port];
+ rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *));
+
+ if (timer_period > 0) {
+ __atomic_fetch_add(
+ &l2fwd_rsrc->port_stats[mbuf->port].rx,
+ 1, __ATOMIC_RELAXED);
+ __atomic_fetch_add(
+ &l2fwd_rsrc->port_stats[mbuf->port].tx,
+ 1, __ATOMIC_RELAXED);
+ }
+ mbuf->port = dst_port;
+ if (flags & L2FWD_EVENT_UPDT_MAC)
+ l2fwd_mac_updating(mbuf, dst_port,
+ &l2fwd_rsrc->eth_addr[
+ dst_port]);
+
+ if (flags & L2FWD_EVENT_TX_ENQ) {
+ ev[i].queue_id = tx_q_id;
+ ev[i].op = RTE_EVENT_OP_FORWARD;
+ }
+
+ if (flags & L2FWD_EVENT_TX_DIRECT)
+ rte_event_eth_tx_adapter_txq_set(mbuf, 0);
+
+ }
+
+ if (flags & L2FWD_EVENT_TX_ENQ) {
+ nb_tx = rte_event_enqueue_burst(event_d_id, port_id,
+ ev, nb_rx);
+ while (nb_tx < nb_rx && !l2fwd_rsrc->force_quit)
+ nb_tx += rte_event_enqueue_burst(event_d_id,
+ port_id, ev + nb_tx,
+ nb_rx - nb_tx);
+ }
+
+ if (flags & L2FWD_EVENT_TX_DIRECT) {
+ nb_tx = rte_event_eth_tx_adapter_enqueue(event_d_id,
+ port_id, ev,
+ nb_rx);
+ while (nb_tx < nb_rx && !l2fwd_rsrc->force_quit)
+ nb_tx += rte_event_eth_tx_adapter_enqueue(
+ event_d_id, port_id,
+ ev + nb_tx, nb_rx - nb_tx);
+ }
+ }
+}
+
+static __rte_always_inline void
+l2fwd_event_loop(struct l2fwd_resources *l2fwd_rsrc,
+ const uint32_t flags)
+{
+ if (flags & L2FWD_EVENT_SINGLE)
+ l2fwd_event_loop_single(l2fwd_rsrc, flags);
+ if (flags & L2FWD_EVENT_BURST)
+ l2fwd_event_loop_burst(l2fwd_rsrc, flags);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_d(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc,
+ L2FWD_EVENT_TX_DIRECT | L2FWD_EVENT_SINGLE);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_d_brst(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_TX_DIRECT | L2FWD_EVENT_BURST);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_q(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_TX_ENQ | L2FWD_EVENT_SINGLE);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_q_brst(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_TX_ENQ | L2FWD_EVENT_BURST);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_d_mac(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_UPDT_MAC |
+ L2FWD_EVENT_TX_DIRECT | L2FWD_EVENT_SINGLE);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_d_brst_mac(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_UPDT_MAC |
+ L2FWD_EVENT_TX_DIRECT | L2FWD_EVENT_BURST);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_q_mac(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_UPDT_MAC |
+ L2FWD_EVENT_TX_ENQ | L2FWD_EVENT_SINGLE);
+}
+
+static void __rte_noinline
+l2fwd_event_main_loop_tx_q_brst_mac(struct l2fwd_resources *l2fwd_rsrc)
+{
+ l2fwd_event_loop(l2fwd_rsrc, L2FWD_EVENT_UPDT_MAC |
+ L2FWD_EVENT_TX_ENQ | L2FWD_EVENT_BURST);
+}
+
void
l2fwd_event_resource_setup(struct l2fwd_resources *l2fwd_rsrc)
{
+ /* [MAC_UPDT][TX_MODE][BURST] */
+ const event_loop_cb event_loop[2][2][2] = {
+ [0][0][0] = l2fwd_event_main_loop_tx_d,
+ [0][0][1] = l2fwd_event_main_loop_tx_d_brst,
+ [0][1][0] = l2fwd_event_main_loop_tx_q,
+ [0][1][1] = l2fwd_event_main_loop_tx_q_brst,
+ [1][0][0] = l2fwd_event_main_loop_tx_d_mac,
+ [1][0][1] = l2fwd_event_main_loop_tx_d_brst_mac,
+ [1][1][0] = l2fwd_event_main_loop_tx_q_mac,
+ [1][1][1] = l2fwd_event_main_loop_tx_q_brst_mac,
+ };
struct l2fwd_event_resources *event_rsrc;
uint32_t event_queue_cfg;
+ int ret;
if (!rte_event_dev_count())
rte_exit(EXIT_FAILURE, "No Eventdev found\n");
@@ -158,4 +442,14 @@ l2fwd_event_resource_setup(struct l2fwd_resources *l2fwd_rsrc)
/* Rx/Tx adapters configuration */
event_rsrc->ops.adapter_setup(l2fwd_rsrc);
+
+ /* Start event device */
+ ret = rte_event_dev_start(event_rsrc->event_d_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error in starting eventdev");
+
+ event_rsrc->ops.l2fwd_event_loop = event_loop
+ [l2fwd_rsrc->mac_updating]
+ [event_rsrc->tx_mode_q]
+ [event_rsrc->has_burst];
}
@@ -18,6 +18,7 @@ typedef void (*event_port_setup_cb)(struct l2fwd_resources *l2fwd_rsrc);
typedef void (*event_queue_setup_cb)(struct l2fwd_resources *l2fwd_rsrc,
uint32_t event_queue_cfg);
typedef void (*adapter_setup_cb)(struct l2fwd_resources *l2fwd_rsrc);
+typedef void (*event_loop_cb)(struct l2fwd_resources *l2fwd_rsrc);
struct event_queues {
uint8_t *event_q_id;
@@ -47,6 +48,7 @@ struct event_setup_ops {
event_queue_setup_cb event_queue_setup;
event_port_setup_cb event_port_setup;
adapter_setup_cb adapter_setup;
+ event_loop_cb l2fwd_event_loop;
};
struct l2fwd_event_resources {
@@ -212,8 +212,12 @@ l2fwd_launch_one_lcore(void *args)
{
struct l2fwd_resources *l2fwd_rsrc = args;
struct l2fwd_poll_resources *poll_rsrc = l2fwd_rsrc->poll_rsrc;
+ struct l2fwd_event_resources *event_rsrc = l2fwd_rsrc->event_rsrc;
- poll_rsrc->poll_main_loop(l2fwd_rsrc);
+ if (l2fwd_rsrc->event_mode)
+ event_rsrc->ops.l2fwd_event_loop(l2fwd_rsrc);
+ else
+ poll_rsrc->poll_main_loop(l2fwd_rsrc);
return 0;
}