[04/14] examples/ipsec-secgw: add Rx adapter support

Message ID 1575808249-31135-5-git-send-email-anoobj@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series add eventmode to ipsec-secgw |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Anoob Joseph Dec. 8, 2019, 12:30 p.m. UTC
  Add Rx adapter support. The event helper init routine will initialize
the Rx adapter according to the configuration. If Rx adapter config
is not present it will generate a default config. It will check the
available eth ports and event queues and map them 1:1. So one eth port
will be connected to one event queue. This way event queue ID could
be used to figure out the port on which a packet came in.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
---
 examples/ipsec-secgw/event_helper.c | 289 +++++++++++++++++++++++++++++++++++-
 examples/ipsec-secgw/event_helper.h |  29 ++++
 2 files changed, 317 insertions(+), 1 deletion(-)
  

Comments

Akhil Goyal Dec. 11, 2019, 11:33 a.m. UTC | #1
Hi Anoob,

I have just started looking into this patchset. Will be doing a detailed review soon.
But an initial comment.
Why do you need 1-1 mapping between event queue and ethdev queue.

All eth and crypto queues will be attached to eventdev. And there may be single event queue
Or multiple but not necessarily equal to eth queues.
> +
> +	/* Make sure there is enough event queues for 1:1 mapping */
> +	if (nb_eth_dev > eventdev_config->nb_eventqueue) {
> +		EH_LOG_ERR("Not enough event queues for 1:1 mapping "
> +			"[eth devs: %d, event queues: %d]\n",
> +			nb_eth_dev, eventdev_config->nb_eventqueue);
> +		return -EINVAL;
> +	}
> +
  
Anoob Joseph Dec. 12, 2019, 5:18 a.m. UTC | #2
Hi Akhil,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Wednesday, December 11, 2019 5:04 PM
> To: Anoob Joseph <anoobj@marvell.com>; Radu Nicolau
> <radu.nicolau@intel.com>; Thomas Monjalon <thomas@monjalon.net>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Narayana Prasad Raju
> Athreya <pathreya@marvell.com>; Ankur Dwivedi <adwivedi@marvell.com>;
> Archana Muniganti <marchana@marvell.com>; Tejasree Kondoj
> <ktejasree@marvell.com>; Vamsi Krishna Attunuru <vattunuru@marvell.com>;
> Lukas Bartosik <lbartosik@marvell.com>; Konstantin Ananyev
> <konstantin.ananyev@intel.com>; dev@dpdk.org
> Subject: [EXT] RE: [PATCH 04/14] examples/ipsec-secgw: add Rx adapter
> support
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Anoob,
> 
> I have just started looking into this patchset. Will be doing a detailed review
> soon.
> But an initial comment.
> Why do you need 1-1 mapping between event queue and ethdev queue.
> 
> All eth and crypto queues will be attached to eventdev. And there may be single
> event queue Or multiple but not necessarily equal to eth queues.

[Anoob] You are right. We could have one single event queue which could handle all traffic. But the idea of more event queues is to better isolate independent traffic flows. If all traffic is forwarded to single event queue, it could lead to artificial dependency between otherwise independent flows and underutilization of resources.

But having a single event queue is also a valid case, and we shouldn't have that case failing. So I'll have an else case for the below check and would adjust the code to work with single event queue.
 
> > +
> > +	/* Make sure there is enough event queues for 1:1 mapping */
> > +	if (nb_eth_dev > eventdev_config->nb_eventqueue) {
> > +		EH_LOG_ERR("Not enough event queues for 1:1 mapping "
> > +			"[eth devs: %d, event queues: %d]\n",
> > +			nb_eth_dev, eventdev_config->nb_eventqueue);
> > +		return -EINVAL;
> > +	}
> > +
  
Ananyev, Konstantin Dec. 23, 2019, 6:48 p.m. UTC | #3
> Add Rx adapter support. The event helper init routine will initialize
> the Rx adapter according to the configuration. If Rx adapter config
> is not present it will generate a default config. It will check the
> available eth ports and event queues and map them 1:1. So one eth port
> will be connected to one event queue. This way event queue ID could
> be used to figure out the port on which a packet came in.
> 
> Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
> ---
>  examples/ipsec-secgw/event_helper.c | 289 +++++++++++++++++++++++++++++++++++-
>  examples/ipsec-secgw/event_helper.h |  29 ++++
>  2 files changed, 317 insertions(+), 1 deletion(-)
> 
> diff --git a/examples/ipsec-secgw/event_helper.c b/examples/ipsec-secgw/event_helper.c
> index d0157f4..f0eca01 100644
> --- a/examples/ipsec-secgw/event_helper.c
> +++ b/examples/ipsec-secgw/event_helper.c
> @@ -4,10 +4,60 @@
>  #include <rte_bitmap.h>
>  #include <rte_ethdev.h>
>  #include <rte_eventdev.h>
> +#include <rte_event_eth_rx_adapter.h>
>  #include <rte_malloc.h>
> 
>  #include "event_helper.h"
> 
> +static int
> +eh_get_enabled_cores(struct rte_bitmap *eth_core_mask)
> +{
> +	int i;
> +	int count = 0;
> +
> +	RTE_LCORE_FOREACH(i) {
> +		/* Check if this core is enabled in core mask*/
> +		if (rte_bitmap_get(eth_core_mask, i)) {
> +			/* We have found enabled core */
> +			count++;
> +		}
> +	}
> +	return count;
> +}
> +
> +static inline unsigned int
> +eh_get_next_eth_core(struct eventmode_conf *em_conf)
> +{
> +	static unsigned int prev_core = -1;
> +	unsigned int next_core;
> +
> +	/*
> +	 * Make sure we have at least one eth core running, else the following
> +	 * logic would lead to an infinite loop.
> +	 */
> +	if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
> +		EH_LOG_ERR("No enabled eth core found");
> +		return RTE_MAX_LCORE;
> +	}
> +
> +get_next_core:
> +	/* Get the next core */
> +	next_core = rte_get_next_lcore(prev_core, 0, 1);
> +
> +	/* Check if we have reached max lcores */
> +	if (next_core == RTE_MAX_LCORE)
> +		return next_core;
> +
> +	/* Update prev_core */
> +	prev_core = next_core;
> +
> +	/* Only some cores are marked as eth cores. Skip others */
> +	if (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)))
> +		goto get_next_core;

Are loops statements forbidden in C now? 😉
As a generic comment - too many (unnecessary) gotos in this patch series.
It is not uncommon to see 2-3 labels inside the function and bunch gotos to them.
Would be good to rework the code a bit to get rid of them.

> +
> +	return next_core;
> +}
> +
>  static inline unsigned int
>  eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int prev_core)
>  {
> @@ -154,6 +204,87 @@ eh_set_default_conf_link(struct eventmode_conf *em_conf)
>  }
>
  
Anoob Joseph Jan. 7, 2020, 6:12 a.m. UTC | #4
Hi Konstantin,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Sent: Tuesday, December 24, 2019 12:18 AM
> To: Anoob Joseph <anoobj@marvell.com>; Akhil Goyal <akhil.goyal@nxp.com>;
> Nicolau, Radu <radu.nicolau@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>
> Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; Narayana Prasad Raju
> Athreya <pathreya@marvell.com>; Ankur Dwivedi <adwivedi@marvell.com>;
> Archana Muniganti <marchana@marvell.com>; Tejasree Kondoj
> <ktejasree@marvell.com>; Vamsi Krishna Attunuru <vattunuru@marvell.com>;
> Lukas Bartosik <lbartosik@marvell.com>; dev@dpdk.org
> Subject: [EXT] RE: [PATCH 04/14] examples/ipsec-secgw: add Rx adapter
> support
> 
> External Email
> 
> ----------------------------------------------------------------------
> > Add Rx adapter support. The event helper init routine will initialize
> > the Rx adapter according to the configuration. If Rx adapter config is
> > not present it will generate a default config. It will check the
> > available eth ports and event queues and map them 1:1. So one eth port
> > will be connected to one event queue. This way event queue ID could be
> > used to figure out the port on which a packet came in.
> >
> > Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> > Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
> > ---
> >  examples/ipsec-secgw/event_helper.c | 289
> > +++++++++++++++++++++++++++++++++++-
> >  examples/ipsec-secgw/event_helper.h |  29 ++++
> >  2 files changed, 317 insertions(+), 1 deletion(-)
> >
> > diff --git a/examples/ipsec-secgw/event_helper.c
> > b/examples/ipsec-secgw/event_helper.c
> > index d0157f4..f0eca01 100644
> > --- a/examples/ipsec-secgw/event_helper.c
> > +++ b/examples/ipsec-secgw/event_helper.c
> > @@ -4,10 +4,60 @@
> >  #include <rte_bitmap.h>
> >  #include <rte_ethdev.h>
> >  #include <rte_eventdev.h>
> > +#include <rte_event_eth_rx_adapter.h>
> >  #include <rte_malloc.h>
> >
> >  #include "event_helper.h"
> >
> > +static int
> > +eh_get_enabled_cores(struct rte_bitmap *eth_core_mask) {
> > +	int i;
> > +	int count = 0;
> > +
> > +	RTE_LCORE_FOREACH(i) {
> > +		/* Check if this core is enabled in core mask*/
> > +		if (rte_bitmap_get(eth_core_mask, i)) {
> > +			/* We have found enabled core */
> > +			count++;
> > +		}
> > +	}
> > +	return count;
> > +}
> > +
> > +static inline unsigned int
> > +eh_get_next_eth_core(struct eventmode_conf *em_conf) {
> > +	static unsigned int prev_core = -1;
> > +	unsigned int next_core;
> > +
> > +	/*
> > +	 * Make sure we have at least one eth core running, else the following
> > +	 * logic would lead to an infinite loop.
> > +	 */
> > +	if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
> > +		EH_LOG_ERR("No enabled eth core found");
> > +		return RTE_MAX_LCORE;
> > +	}
> > +
> > +get_next_core:
> > +	/* Get the next core */
> > +	next_core = rte_get_next_lcore(prev_core, 0, 1);
> > +
> > +	/* Check if we have reached max lcores */
> > +	if (next_core == RTE_MAX_LCORE)
> > +		return next_core;
> > +
> > +	/* Update prev_core */
> > +	prev_core = next_core;
> > +
> > +	/* Only some cores are marked as eth cores. Skip others */
> > +	if (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)))
> > +		goto get_next_core;
> 
> Are loops statements forbidden in C now? 😉
> As a generic comment - too many (unnecessary) gotos in this patch series.
> It is not uncommon to see 2-3 labels inside the function and bunch gotos to
> them.
> Would be good to rework the code a bit to get rid of them.

[Anoob] Sure. Will rework the code and see if the gotos can be minimized. In this case, it seemed more straightforward to have goto instead of the loop. Will recheck anyway.
 
> 
> > +
> > +	return next_core;
> > +}
> > +
> >  static inline unsigned int
> >  eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int
> > prev_core)  { @@ -154,6 +204,87 @@ eh_set_default_conf_link(struct
> > eventmode_conf *em_conf)  }
> >
  
Ananyev, Konstantin Jan. 7, 2020, 2:32 p.m. UTC | #5
> > > Add Rx adapter support. The event helper init routine will initialize
> > > the Rx adapter according to the configuration. If Rx adapter config is
> > > not present it will generate a default config. It will check the
> > > available eth ports and event queues and map them 1:1. So one eth port
> > > will be connected to one event queue. This way event queue ID could be
> > > used to figure out the port on which a packet came in.
> > >
> > > Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> > > Signed-off-by: Lukasz Bartosik <lbartosik@marvell.com>
> > > ---
> > >  examples/ipsec-secgw/event_helper.c | 289
> > > +++++++++++++++++++++++++++++++++++-
> > >  examples/ipsec-secgw/event_helper.h |  29 ++++
> > >  2 files changed, 317 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/examples/ipsec-secgw/event_helper.c
> > > b/examples/ipsec-secgw/event_helper.c
> > > index d0157f4..f0eca01 100644
> > > --- a/examples/ipsec-secgw/event_helper.c
> > > +++ b/examples/ipsec-secgw/event_helper.c
> > > @@ -4,10 +4,60 @@
> > >  #include <rte_bitmap.h>
> > >  #include <rte_ethdev.h>
> > >  #include <rte_eventdev.h>
> > > +#include <rte_event_eth_rx_adapter.h>
> > >  #include <rte_malloc.h>
> > >
> > >  #include "event_helper.h"
> > >
> > > +static int
> > > +eh_get_enabled_cores(struct rte_bitmap *eth_core_mask) {
> > > +	int i;
> > > +	int count = 0;
> > > +
> > > +	RTE_LCORE_FOREACH(i) {
> > > +		/* Check if this core is enabled in core mask*/
> > > +		if (rte_bitmap_get(eth_core_mask, i)) {
> > > +			/* We have found enabled core */
> > > +			count++;
> > > +		}
> > > +	}
> > > +	return count;
> > > +}
> > > +
> > > +static inline unsigned int
> > > +eh_get_next_eth_core(struct eventmode_conf *em_conf) {
> > > +	static unsigned int prev_core = -1;
> > > +	unsigned int next_core;
> > > +
> > > +	/*
> > > +	 * Make sure we have at least one eth core running, else the following
> > > +	 * logic would lead to an infinite loop.
> > > +	 */
> > > +	if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
> > > +		EH_LOG_ERR("No enabled eth core found");
> > > +		return RTE_MAX_LCORE;
> > > +	}
> > > +
> > > +get_next_core:
> > > +	/* Get the next core */
> > > +	next_core = rte_get_next_lcore(prev_core, 0, 1);
> > > +
> > > +	/* Check if we have reached max lcores */
> > > +	if (next_core == RTE_MAX_LCORE)
> > > +		return next_core;
> > > +
> > > +	/* Update prev_core */
> > > +	prev_core = next_core;
> > > +
> > > +	/* Only some cores are marked as eth cores. Skip others */
> > > +	if (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)))
> > > +		goto get_next_core;
> >
> > Are loops statements forbidden in C now? 😉
> > As a generic comment - too many (unnecessary) gotos in this patch series.
> > It is not uncommon to see 2-3 labels inside the function and bunch gotos to
> > them.
> > Would be good to rework the code a bit to get rid of them.
> 
> [Anoob] Sure. Will rework the code and see if the gotos can be minimized. In this case, it seemed more straightforward to have goto
> instead of the loop. Will recheck anyway.

The code above looks like a classical do {..} while (...); example, no?

> 
> >
> > > +
> > > +	return next_core;
> > > +}
> > > +
> > >  static inline unsigned int
> > >  eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int
> > > prev_core)  { @@ -154,6 +204,87 @@ eh_set_default_conf_link(struct
> > > eventmode_conf *em_conf)  }
> > >
  

Patch

diff --git a/examples/ipsec-secgw/event_helper.c b/examples/ipsec-secgw/event_helper.c
index d0157f4..f0eca01 100644
--- a/examples/ipsec-secgw/event_helper.c
+++ b/examples/ipsec-secgw/event_helper.c
@@ -4,10 +4,60 @@ 
 #include <rte_bitmap.h>
 #include <rte_ethdev.h>
 #include <rte_eventdev.h>
+#include <rte_event_eth_rx_adapter.h>
 #include <rte_malloc.h>
 
 #include "event_helper.h"
 
+static int
+eh_get_enabled_cores(struct rte_bitmap *eth_core_mask)
+{
+	int i;
+	int count = 0;
+
+	RTE_LCORE_FOREACH(i) {
+		/* Check if this core is enabled in core mask*/
+		if (rte_bitmap_get(eth_core_mask, i)) {
+			/* We have found enabled core */
+			count++;
+		}
+	}
+	return count;
+}
+
+static inline unsigned int
+eh_get_next_eth_core(struct eventmode_conf *em_conf)
+{
+	static unsigned int prev_core = -1;
+	unsigned int next_core;
+
+	/*
+	 * Make sure we have at least one eth core running, else the following
+	 * logic would lead to an infinite loop.
+	 */
+	if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
+		EH_LOG_ERR("No enabled eth core found");
+		return RTE_MAX_LCORE;
+	}
+
+get_next_core:
+	/* Get the next core */
+	next_core = rte_get_next_lcore(prev_core, 0, 1);
+
+	/* Check if we have reached max lcores */
+	if (next_core == RTE_MAX_LCORE)
+		return next_core;
+
+	/* Update prev_core */
+	prev_core = next_core;
+
+	/* Only some cores are marked as eth cores. Skip others */
+	if (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)))
+		goto get_next_core;
+
+	return next_core;
+}
+
 static inline unsigned int
 eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int prev_core)
 {
@@ -154,6 +204,87 @@  eh_set_default_conf_link(struct eventmode_conf *em_conf)
 }
 
 static int
+eh_set_default_conf_rx_adapter(struct eventmode_conf *em_conf)
+{
+	struct rx_adapter_connection_info *conn;
+	struct eventdev_params *eventdev_config;
+	struct rx_adapter_conf *adapter;
+	int eventdev_id;
+	int nb_eth_dev;
+	int adapter_id;
+	int conn_id;
+	int i;
+
+	/* Create one adapter with all eth queues mapped to event queues 1:1 */
+
+	if (em_conf->nb_eventdev == 0) {
+		EH_LOG_ERR("No event devs registered");
+		return -EINVAL;
+	}
+
+	/* Get the number of eth devs */
+	nb_eth_dev = rte_eth_dev_count_avail();
+
+	/* Use the first event dev */
+	eventdev_config = &(em_conf->eventdev_config[0]);
+
+	/* Get eventdev ID */
+	eventdev_id = eventdev_config->eventdev_id;
+	adapter_id = 0;
+
+	/* Get adapter conf */
+	adapter = &(em_conf->rx_adapter[adapter_id]);
+
+	/* Set adapter conf */
+	adapter->eventdev_id = eventdev_id;
+	adapter->adapter_id = adapter_id;
+	adapter->rx_core_id = eh_get_next_eth_core(em_conf);
+
+	/*
+	 * Map all queues of one eth device (port) to one event
+	 * queue. Each port will have an individual connection.
+	 *
+	 */
+
+	/* Make sure there is enough event queues for 1:1 mapping */
+	if (nb_eth_dev > eventdev_config->nb_eventqueue) {
+		EH_LOG_ERR("Not enough event queues for 1:1 mapping "
+			"[eth devs: %d, event queues: %d]\n",
+			nb_eth_dev, eventdev_config->nb_eventqueue);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nb_eth_dev; i++) {
+
+		/* Use only the ports enabled */
+		if ((em_conf->eth_portmask & (1 << i)) == 0)
+			continue;
+
+		/* Get the connection id */
+		conn_id = adapter->nb_connections;
+
+		/* Get the connection */
+		conn = &(adapter->conn[conn_id]);
+
+		/* Set 1:1 mapping between eth ports & event queues*/
+		conn->ethdev_id = i;
+		conn->eventq_id = i;
+
+		/* Add all eth queues of one eth port to one event queue */
+		conn->ethdev_rx_qid = -1;
+
+		/* Update no of connections */
+		adapter->nb_connections++;
+
+	}
+
+	/* We have setup one adapter */
+	em_conf->nb_rx_adapter = 1;
+
+	return 0;
+}
+
+static int
 eh_validate_conf(struct eventmode_conf *em_conf)
 {
 	int ret;
@@ -178,6 +309,16 @@  eh_validate_conf(struct eventmode_conf *em_conf)
 			return ret;
 	}
 
+	/*
+	 * Check if rx adapters are specified. Else generate a default config
+	 * with one rx adapter and all eth queues - event queue mapped.
+	 */
+	if (em_conf->nb_rx_adapter == 0) {
+		ret = eh_set_default_conf_rx_adapter(em_conf);
+		if (ret != 0)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -336,6 +477,113 @@  eh_initialize_eventdev(struct eventmode_conf *em_conf)
 	return 0;
 }
 
+static int
+eh_rx_adapter_configure(struct eventmode_conf *em_conf,
+	struct rx_adapter_conf *adapter)
+{
+	struct rte_event_eth_rx_adapter_queue_conf queue_conf = {0};
+	struct rte_event_dev_info evdev_default_conf = {0};
+	struct rte_event_port_conf port_conf = {0};
+	struct rx_adapter_connection_info *conn;
+	uint8_t eventdev_id;
+	uint32_t service_id;
+	int ret;
+	int j;
+
+	/* Get event dev ID */
+	eventdev_id = adapter->eventdev_id;
+
+	/* Get default configuration of event dev */
+	ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
+	if (ret < 0) {
+		EH_LOG_ERR("Failed to get event dev info %d", ret);
+		return ret;
+	}
+
+	/* Setup port conf */
+	port_conf.new_event_threshold = 1200;
+	port_conf.dequeue_depth =
+			evdev_default_conf.max_event_port_dequeue_depth;
+	port_conf.enqueue_depth =
+			evdev_default_conf.max_event_port_enqueue_depth;
+
+	/* Create Rx adapter */
+	ret = rte_event_eth_rx_adapter_create(adapter->adapter_id,
+			adapter->eventdev_id,
+			&port_conf);
+	if (ret < 0) {
+		EH_LOG_ERR("Failed to create rx adapter %d", ret);
+		return ret;
+	}
+
+	/* Setup various connections in the adapter */
+
+	queue_conf.rx_queue_flags =
+			RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID;
+
+	for (j = 0; j < adapter->nb_connections; j++) {
+		/* Get connection */
+		conn = &(adapter->conn[j]);
+
+		/* Setup queue conf */
+		queue_conf.ev.queue_id = conn->eventq_id;
+		queue_conf.ev.sched_type = em_conf->ext_params.sched_type;
+
+		/* Set flow ID as ethdev ID */
+		queue_conf.ev.flow_id = conn->ethdev_id;
+
+		/* Add queue to the adapter */
+		ret = rte_event_eth_rx_adapter_queue_add(
+				adapter->adapter_id,
+				conn->ethdev_id,
+				conn->ethdev_rx_qid,
+				&queue_conf);
+		if (ret < 0) {
+			EH_LOG_ERR("Failed to add eth queue to rx adapter %d",
+				   ret);
+			return ret;
+		}
+	}
+
+	/* Get the service ID used by rx adapter */
+	ret = rte_event_eth_rx_adapter_service_id_get(adapter->adapter_id,
+						      &service_id);
+	if (ret != -ESRCH && ret < 0) {
+		EH_LOG_ERR("Failed to get service id used by rx adapter %d",
+			   ret);
+		return ret;
+	}
+
+	rte_service_set_runstate_mapped_check(service_id, 0);
+
+	/* Start adapter */
+	ret = rte_event_eth_rx_adapter_start(adapter->adapter_id);
+	if (ret < 0) {
+		EH_LOG_ERR("Failed to start rx adapter %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+eh_initialize_rx_adapter(struct eventmode_conf *em_conf)
+{
+	struct rx_adapter_conf *adapter;
+	int i, ret;
+
+	/* Configure rx adapters */
+	for (i = 0; i < em_conf->nb_rx_adapter; i++) {
+		adapter = &(em_conf->rx_adapter[i]);
+		ret = eh_rx_adapter_configure(em_conf, adapter);
+		if (ret < 0) {
+			EH_LOG_ERR("Failed to configure rx adapter %d", ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
 int32_t
 eh_devs_init(struct eh_conf *conf)
 {
@@ -359,6 +607,9 @@  eh_devs_init(struct eh_conf *conf)
 	/* Get eventmode conf */
 	em_conf = (struct eventmode_conf *)(conf->mode_params);
 
+	/* Eventmode conf would need eth portmask */
+	em_conf->eth_portmask = conf->eth_portmask;
+
 	/* Validate the requested config */
 	ret = eh_validate_conf(em_conf);
 	if (ret < 0) {
@@ -383,6 +634,13 @@  eh_devs_init(struct eh_conf *conf)
 		return ret;
 	}
 
+	/* Setup Rx adapter */
+	ret = eh_initialize_rx_adapter(em_conf);
+	if (ret < 0) {
+		EH_LOG_ERR("Failed to initialize rx adapter %d", ret);
+		return ret;
+	}
+
 	/* Start eth devices after setting up adapter */
 	RTE_ETH_FOREACH_DEV(port_id) {
 
@@ -405,8 +663,8 @@  int32_t
 eh_devs_uninit(struct eh_conf *conf)
 {
 	struct eventmode_conf *em_conf;
+	int ret, i, j;
 	uint16_t id;
-	int ret, i;
 
 	if (conf == NULL) {
 		EH_LOG_ERR("Invalid event helper configuration");
@@ -424,6 +682,35 @@  eh_devs_uninit(struct eh_conf *conf)
 	/* Get eventmode conf */
 	em_conf = (struct eventmode_conf *)(conf->mode_params);
 
+	/* Stop and release rx adapters */
+	for (i = 0; i < em_conf->nb_rx_adapter; i++) {
+
+		id = em_conf->rx_adapter[i].adapter_id;
+		ret = rte_event_eth_rx_adapter_stop(id);
+		if (ret < 0) {
+			EH_LOG_ERR("Failed to stop rx adapter %d", ret);
+			return ret;
+		}
+
+		for (j = 0; j < em_conf->rx_adapter[i].nb_connections; j++) {
+
+			ret = rte_event_eth_rx_adapter_queue_del(id,
+				em_conf->rx_adapter[i].conn[j].ethdev_id, -1);
+			if (ret < 0) {
+				EH_LOG_ERR(
+				       "Failed to remove rx adapter queues %d",
+				       ret);
+				return ret;
+			}
+		}
+
+		ret = rte_event_eth_rx_adapter_free(id);
+		if (ret < 0) {
+			EH_LOG_ERR("Failed to free rx adapter %d", ret);
+			return ret;
+		}
+	}
+
 	/* Stop and release event devices */
 	for (i = 0; i < em_conf->nb_eventdev; i++) {
 
diff --git a/examples/ipsec-secgw/event_helper.h b/examples/ipsec-secgw/event_helper.h
index 2d217e2..0f89c31 100644
--- a/examples/ipsec-secgw/event_helper.h
+++ b/examples/ipsec-secgw/event_helper.h
@@ -20,6 +20,12 @@  extern "C" {
 /* Max event devices supported */
 #define EVENT_MODE_MAX_EVENT_DEVS RTE_EVENT_MAX_DEVS
 
+/* Max Rx adapters supported */
+#define EVENT_MODE_MAX_RX_ADAPTERS RTE_EVENT_MAX_DEVS
+
+/* Max Rx adapter connections */
+#define EVENT_MODE_MAX_CONNECTIONS_PER_ADAPTER 16
+
 /* Max event queues supported per event device */
 #define EVENT_MODE_MAX_EVENT_QUEUES_PER_DEV RTE_EVENT_MAX_QUEUES_PER_DEV
 
@@ -57,12 +63,33 @@  struct eh_event_link_info {
 		/**< Lcore to be polling on this port */
 };
 
+/* Rx adapter connection info */
+struct rx_adapter_connection_info {
+	uint8_t ethdev_id;
+	uint8_t eventq_id;
+	int32_t ethdev_rx_qid;
+};
+
+/* Rx adapter conf */
+struct rx_adapter_conf {
+	int32_t eventdev_id;
+	int32_t adapter_id;
+	uint32_t rx_core_id;
+	uint8_t nb_connections;
+	struct rx_adapter_connection_info
+			conn[EVENT_MODE_MAX_CONNECTIONS_PER_ADAPTER];
+};
+
 /* Eventmode conf data */
 struct eventmode_conf {
 	int nb_eventdev;
 		/**< No of event devs */
 	struct eventdev_params eventdev_config[EVENT_MODE_MAX_EVENT_DEVS];
 		/**< Per event dev conf */
+	uint8_t nb_rx_adapter;
+		/**< No of Rx adapters */
+	struct rx_adapter_conf rx_adapter[EVENT_MODE_MAX_RX_ADAPTERS];
+		/**< Rx adapter conf */
 	uint8_t nb_link;
 		/**< No of links */
 	struct eh_event_link_info
@@ -70,6 +97,8 @@  struct eventmode_conf {
 		/**< Per link conf */
 	struct rte_bitmap *eth_core_mask;
 		/**< Core mask of cores to be used for software Rx and Tx */
+	uint32_t eth_portmask;
+		/**< Mask of the eth ports to be used */
 	union {
 		RTE_STD_C11
 		struct {