[dpdk-dev,v2,2/2] examples/ipsec-secgw: add target queues in flow actions
Checks
Commit Message
Mellanox INNOVA NIC needs to have final target queue actions to perform
inline crypto.
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
Changes in v2:
* Test the rule by PASSTHRU/RSS/QUEUE and apply the first one validated.
---
examples/ipsec-secgw/ipsec.c | 81 ++++++++++++++++++++++++++++++++++++++++----
examples/ipsec-secgw/ipsec.h | 2 +-
2 files changed, 76 insertions(+), 7 deletions(-)
Comments
Hi Nelio,
On 12/04/2017 07:41 PM, Nelio Laranjeiro wrote:
> Mellanox INNOVA NIC needs to have final target queue actions to perform
> inline crypto.
>
> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
>
> ---
>
> Changes in v2:
>
> * Test the rule by PASSTHRU/RSS/QUEUE and apply the first one validated.
> ---
> examples/ipsec-secgw/ipsec.c | 81 ++++++++++++++++++++++++++++++++++++++++----
> examples/ipsec-secgw/ipsec.h | 2 +-
> 2 files changed, 76 insertions(+), 7 deletions(-)
>
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index 17bd7620d..f8823fb94 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -142,6 +142,7 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> rte_eth_dev_get_sec_ctx(
> sa->portid);
> const struct rte_security_capability *sec_cap;
> + int ret = 0;
>
> sa->sec_session = rte_security_session_create(ctx,
> &sess_conf, ipsec_ctx->session_pool);
> @@ -173,6 +174,10 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> return -1;
> }
>
> + sa->attr.egress = (sa->direction ==
> + RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> + sa->attr.ingress = (sa->direction ==
> + RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> sa->ol_flags = sec_cap->ol_flags;
> sa->security_ctx = ctx;
> sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> @@ -201,15 +206,79 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
> sa->action[0].conf = sa->sec_session;
>
> - sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> -
> - sa->attr.egress = (sa->direction ==
> - RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> - sa->attr.ingress = (sa->direction ==
> - RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> + if (sa->attr.ingress) {
> + uint8_t rss_key[40];
> + struct rte_eth_rss_conf rss_conf = {
> + .rss_key = rss_key,
> + .rss_key_len = 40,
> + };
> + struct rte_eth_dev *eth_dev;
> + union {
> + struct rte_flow_action_rss rss;
> + struct {
> + const struct rte_eth_rss_conf *rss_conf;
> + uint16_t num;
> + uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
> + } local;
> + } action_rss;
> + unsigned int i;
> + unsigned int j;
> +
> + sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
> + /*
> + * Try implicitly PASSTHRU, it can also be
> + * explicit.
> + */
May be we can get rid of this check. You can do the check with RSS and
then QUEUE. That should be fine. SECURITY is terminating on Cavium
hardware, but according to the spec it is a non-terminating meta action.
We can stick to that. For Cavium hardware the PMD will give success to
SECURITY+QUEUE. That should resolve the issue.
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (!ret)
> + goto flow_create;
> + /* Try RSS. */
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;
> + sa->action[1].conf = &action_rss;
> + eth_dev = ctx->device;
> + rte_eth_dev_rss_hash_conf_get(sa->portid,
> + &rss_conf);
> + for (i = 0, j = 0;
> + i < eth_dev->data->nb_rx_queues; ++i)
> + if (eth_dev->data->rx_queues[i])
> + action_rss.local.queue[j++] = i;
> + action_rss.local.num = j;
> + action_rss.local.rss_conf = &rss_conf;
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (!ret)
> + goto flow_create;
> + /* Try Queue. */
> + for (i = 0;
> + i < eth_dev->data->nb_rx_queues; ++i)
> + if (eth_dev->data->rx_queues[i])
> + break;
> + if (i != eth_dev->data->nb_rx_queues)
> + return -1;
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> + sa->action[1].conf =
> + &(struct rte_flow_action_queue){
> + .index = i,
> + };
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (ret)
> + goto flow_create_failure;
> + } else {
> + sa->action[1].type =
> + RTE_FLOW_ACTION_TYPE_PASSTHRU;
> + sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
> + }
> +flow_create:
> sa->flow = rte_flow_create(sa->portid,
> &sa->attr, sa->pattern, sa->action, &err);
> if (sa->flow == NULL) {
> +flow_create_failure:
> RTE_LOG(ERR, IPSEC,
> "Failed to create ipsec flow msg: %s\n",
> err.message);
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 775b316ff..82ffc1c6d 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -133,7 +133,7 @@ struct ipsec_sa {
> uint32_t ol_flags;
>
> #define MAX_RTE_FLOW_PATTERN (4)
> -#define MAX_RTE_FLOW_ACTIONS (2)
> +#define MAX_RTE_FLOW_ACTIONS (4)
> struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
> struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
> struct rte_flow_attr attr;
Hi Anoob,
On Thu, Dec 07, 2017 at 03:17:40PM +0530, Anoob wrote:
> Hi Nelio,
>
>
> On 12/04/2017 07:41 PM, Nelio Laranjeiro wrote:
> > Mellanox INNOVA NIC needs to have final target queue actions to perform
> > inline crypto.
> >
> > Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
> >
> > ---
> >
> > Changes in v2:
> >
> > * Test the rule by PASSTHRU/RSS/QUEUE and apply the first one validated.
> > ---
> > examples/ipsec-secgw/ipsec.c | 81 ++++++++++++++++++++++++++++++++++++++++----
> > examples/ipsec-secgw/ipsec.h | 2 +-
> > 2 files changed, 76 insertions(+), 7 deletions(-)
> >
> > diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> > index 17bd7620d..f8823fb94 100644
> > --- a/examples/ipsec-secgw/ipsec.c
> > +++ b/examples/ipsec-secgw/ipsec.c
> > @@ -142,6 +142,7 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> > rte_eth_dev_get_sec_ctx(
> > sa->portid);
> > const struct rte_security_capability *sec_cap;
> > + int ret = 0;
> > sa->sec_session = rte_security_session_create(ctx,
> > &sess_conf, ipsec_ctx->session_pool);
> > @@ -173,6 +174,10 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> > return -1;
> > }
> > + sa->attr.egress = (sa->direction ==
> > + RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> > + sa->attr.ingress = (sa->direction ==
> > + RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> > sa->ol_flags = sec_cap->ol_flags;
> > sa->security_ctx = ctx;
> > sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > @@ -201,15 +206,79 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> > sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
> > sa->action[0].conf = sa->sec_session;
> > - sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > -
> > - sa->attr.egress = (sa->direction ==
> > - RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> > - sa->attr.ingress = (sa->direction ==
> > - RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> > + if (sa->attr.ingress) {
> > + uint8_t rss_key[40];
> > + struct rte_eth_rss_conf rss_conf = {
> > + .rss_key = rss_key,
> > + .rss_key_len = 40,
> > + };
> > + struct rte_eth_dev *eth_dev;
> > + union {
> > + struct rte_flow_action_rss rss;
> > + struct {
> > + const struct rte_eth_rss_conf *rss_conf;
> > + uint16_t num;
> > + uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
> > + } local;
> > + } action_rss;
> > + unsigned int i;
> > + unsigned int j;
> > +
> > + sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
> > + /*
> > + * Try implicitly PASSTHRU, it can also be
> > + * explicit.
> > + */
> May be we can get rid of this check. You can do the check with RSS and then
> QUEUE. That should be fine. SECURITY is terminating on Cavium hardware, but
> according to the spec it is a non-terminating meta action. We can stick to
> that. For Cavium hardware the PMD will give success to SECURITY+QUEUE. That
> should resolve the issue.
<snip>
I'll remove it in a v3, I will send it tomorrow to let a little more
time for other people to review.
Thanks,
Hi Nelio,
On 12/04/2017 07:41 PM, Nelio Laranjeiro wrote:
> Mellanox INNOVA NIC needs to have final target queue actions to perform
> inline crypto.
>
> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
>
> ---
>
> Changes in v2:
>
> * Test the rule by PASSTHRU/RSS/QUEUE and apply the first one validated.
> ---
> examples/ipsec-secgw/ipsec.c | 81 ++++++++++++++++++++++++++++++++++++++++----
> examples/ipsec-secgw/ipsec.h | 2 +-
> 2 files changed, 76 insertions(+), 7 deletions(-)
>
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index 17bd7620d..f8823fb94 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -142,6 +142,7 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> rte_eth_dev_get_sec_ctx(
> sa->portid);
> const struct rte_security_capability *sec_cap;
> + int ret = 0;
>
> sa->sec_session = rte_security_session_create(ctx,
> &sess_conf, ipsec_ctx->session_pool);
> @@ -173,6 +174,10 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> return -1;
> }
>
> + sa->attr.egress = (sa->direction ==
> + RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> + sa->attr.ingress = (sa->direction ==
> + RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> sa->ol_flags = sec_cap->ol_flags;
> sa->security_ctx = ctx;
> sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> @@ -201,15 +206,79 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
> sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
> sa->action[0].conf = sa->sec_session;
>
> - sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> -
> - sa->attr.egress = (sa->direction ==
> - RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
> - sa->attr.ingress = (sa->direction ==
> - RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
> + if (sa->attr.ingress) {
> + uint8_t rss_key[40];
> + struct rte_eth_rss_conf rss_conf = {
> + .rss_key = rss_key,
> + .rss_key_len = 40,
> + };
> + struct rte_eth_dev *eth_dev;
> + union {
> + struct rte_flow_action_rss rss;
> + struct {
> + const struct rte_eth_rss_conf *rss_conf;
> + uint16_t num;
> + uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
> + } local;
> + } action_rss;
> + unsigned int i;
> + unsigned int j;
> +
> + sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
> + /*
> + * Try implicitly PASSTHRU, it can also be
> + * explicit.
> + */
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (!ret)
> + goto flow_create;
> + /* Try RSS. */
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;
> + sa->action[1].conf = &action_rss;
> + eth_dev = ctx->device;
> + rte_eth_dev_rss_hash_conf_get(sa->portid,
> + &rss_conf);
> + for (i = 0, j = 0;
> + i < eth_dev->data->nb_rx_queues; ++i)
> + if (eth_dev->data->rx_queues[i])
> + action_rss.local.queue[j++] = i;
> + action_rss.local.num = j;
> + action_rss.local.rss_conf = &rss_conf;
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (!ret)
> + goto flow_create;
> + /* Try Queue. */
> + for (i = 0;
> + i < eth_dev->data->nb_rx_queues; ++i)
> + if (eth_dev->data->rx_queues[i])
> + break;
Is the following check correct?
> + if (i != eth_dev->data->nb_rx_queues)
> + return -1;
> + sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> + sa->action[1].conf =
> + &(struct rte_flow_action_queue){
> + .index = i,
> + };
> + ret = rte_flow_validate(sa->portid, &sa->attr,
> + sa->pattern, sa->action,
> + &err);
> + if (ret)
> + goto flow_create_failure;
> + } else {
> + sa->action[1].type =
> + RTE_FLOW_ACTION_TYPE_PASSTHRU;
> + sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
> + }
> +flow_create:
> sa->flow = rte_flow_create(sa->portid,
> &sa->attr, sa->pattern, sa->action, &err);
> if (sa->flow == NULL) {
> +flow_create_failure:
> RTE_LOG(ERR, IPSEC,
> "Failed to create ipsec flow msg: %s\n",
> err.message);
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 775b316ff..82ffc1c6d 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -133,7 +133,7 @@ struct ipsec_sa {
> uint32_t ol_flags;
>
> #define MAX_RTE_FLOW_PATTERN (4)
> -#define MAX_RTE_FLOW_ACTIONS (2)
> +#define MAX_RTE_FLOW_ACTIONS (4)
> struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
> struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
> struct rte_flow_attr attr;
On Fri, Dec 08, 2017 at 07:30:03PM +0530, Anoob wrote:
> Hi Nelio,
>
>
[...]
> > + goto flow_create;
> > + /* Try Queue. */
> > + for (i = 0;
> > + i < eth_dev->data->nb_rx_queues; ++i)
> > + if (eth_dev->data->rx_queues[i])
> > + break;
> Is the following check correct?
[...]
For an application, it seems not necessary. The application knows which
queues are configured in the drivers has it has made the configuration.
Removing it in the v3.
Thanks,
HI Nelio,
On 08-12-2017 20:10, Nelio Laranjeiro wrote:
> On Fri, Dec 08, 2017 at 07:30:03PM +0530, Anoob wrote:
>> Hi Nelio,
>>
>>
> [...]
>>> + goto flow_create;
>>> + /* Try Queue. */
>>> + for (i = 0;
>>> + i < eth_dev->data->nb_rx_queues; ++i)
>>> + if (eth_dev->data->rx_queues[i])
>>> + break;
>> Is the following check correct?
> [...]
>
> For an application, it seems not necessary. The application knows which
> queues are configured in the drivers has it has made the configuration.
>
> Removing it in the v3.
I think you misunderstood me here.
I was talking about the following line.
+ if (i != eth_dev->data->nb_rx_queues)
+ return -1;
Shouldn't it be?
+ if (i == eth_dev->data->nb_rx_queues)
+ return -1;
Thanks,
Anoob
Hi Anoob,
On Fri, Dec 08, 2017 at 10:10:28PM +0530, Anoob Joseph wrote:
> HI Nelio,
>
>
> On 08-12-2017 20:10, Nelio Laranjeiro wrote:
> > On Fri, Dec 08, 2017 at 07:30:03PM +0530, Anoob wrote:
> > > Hi Nelio,
> > >
> > >
> > [...]
> > > > + goto flow_create;
> > > > + /* Try Queue. */
> > > > + for (i = 0;
> > > > + i < eth_dev->data->nb_rx_queues; ++i)
> > > > + if (eth_dev->data->rx_queues[i])
> > > > + break;
> > > Is the following check correct?
> > [...]
> >
> > For an application, it seems not necessary. The application knows which
> > queues are configured in the drivers has it has made the configuration.
> >
> > Removing it in the v3.
> I think you misunderstood me here.
Indeed, I misunderstood,
> I was talking about the following line.
>
> + if (i != eth_dev->data->nb_rx_queues)
> + return -1;
>
> Shouldn't it be?
>
> + if (i == eth_dev->data->nb_rx_queues)
> + return -1;
Yes it should.
Anyway, I don't thing it is necessary to keep this check, from what I
saw in the application source code, it initialise all Rx queues up to
nb_rx_queues without leaving any hole.
According to this, I'll just remove this verification, is it okay for
you?
Thanks,
Hi Nelio,
On 12/11/2017 01:51 PM, Nelio Laranjeiro wrote:
> Hi Anoob,
>
> On Fri, Dec 08, 2017 at 10:10:28PM +0530, Anoob Joseph wrote:
>> HI Nelio,
>>
>>
>> On 08-12-2017 20:10, Nelio Laranjeiro wrote:
>>> On Fri, Dec 08, 2017 at 07:30:03PM +0530, Anoob wrote:
>>>> Hi Nelio,
>>>>
>>>>
>>> [...]
>>>>> + goto flow_create;
>>>>> + /* Try Queue. */
>>>>> + for (i = 0;
>>>>> + i < eth_dev->data->nb_rx_queues; ++i)
>>>>> + if (eth_dev->data->rx_queues[i])
>>>>> + break;
>>>> Is the following check correct?
>>> [...]
>>>
>>> For an application, it seems not necessary. The application knows which
>>> queues are configured in the drivers has it has made the configuration.
>>>
>>> Removing it in the v3.
>> I think you misunderstood me here.
> Indeed, I misunderstood,
>
>> I was talking about the following line.
>>
>> + if (i != eth_dev->data->nb_rx_queues)
>> + return -1;
>>
>> Shouldn't it be?
>>
>> + if (i == eth_dev->data->nb_rx_queues)
>> + return -1;
> Yes it should.
>
> Anyway, I don't thing it is necessary to keep this check, from what I
> saw in the application source code, it initialise all Rx queues up to
> nb_rx_queues without leaving any hole.
> According to this, I'll just remove this verification, is it okay for
> you?
I think you can just use Queue 0 here. So you can get rid of the checks
etc. For real applications, we should have an entry in SA structure
which will determine the Queue to be used. Even for RSS, something like
that would be required.
Thanks,
Anoob
@@ -142,6 +142,7 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
rte_eth_dev_get_sec_ctx(
sa->portid);
const struct rte_security_capability *sec_cap;
+ int ret = 0;
sa->sec_session = rte_security_session_create(ctx,
&sess_conf, ipsec_ctx->session_pool);
@@ -173,6 +174,10 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
return -1;
}
+ sa->attr.egress = (sa->direction ==
+ RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
+ sa->attr.ingress = (sa->direction ==
+ RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
sa->ol_flags = sec_cap->ol_flags;
sa->security_ctx = ctx;
sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
@@ -201,15 +206,79 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa)
sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
sa->action[0].conf = sa->sec_session;
- sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
-
- sa->attr.egress = (sa->direction ==
- RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
- sa->attr.ingress = (sa->direction ==
- RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
+ if (sa->attr.ingress) {
+ uint8_t rss_key[40];
+ struct rte_eth_rss_conf rss_conf = {
+ .rss_key = rss_key,
+ .rss_key_len = 40,
+ };
+ struct rte_eth_dev *eth_dev;
+ union {
+ struct rte_flow_action_rss rss;
+ struct {
+ const struct rte_eth_rss_conf *rss_conf;
+ uint16_t num;
+ uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
+ } local;
+ } action_rss;
+ unsigned int i;
+ unsigned int j;
+
+ sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
+ /*
+ * Try implicitly PASSTHRU, it can also be
+ * explicit.
+ */
+ sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+ ret = rte_flow_validate(sa->portid, &sa->attr,
+ sa->pattern, sa->action,
+ &err);
+ if (!ret)
+ goto flow_create;
+ /* Try RSS. */
+ sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;
+ sa->action[1].conf = &action_rss;
+ eth_dev = ctx->device;
+ rte_eth_dev_rss_hash_conf_get(sa->portid,
+ &rss_conf);
+ for (i = 0, j = 0;
+ i < eth_dev->data->nb_rx_queues; ++i)
+ if (eth_dev->data->rx_queues[i])
+ action_rss.local.queue[j++] = i;
+ action_rss.local.num = j;
+ action_rss.local.rss_conf = &rss_conf;
+ ret = rte_flow_validate(sa->portid, &sa->attr,
+ sa->pattern, sa->action,
+ &err);
+ if (!ret)
+ goto flow_create;
+ /* Try Queue. */
+ for (i = 0;
+ i < eth_dev->data->nb_rx_queues; ++i)
+ if (eth_dev->data->rx_queues[i])
+ break;
+ if (i != eth_dev->data->nb_rx_queues)
+ return -1;
+ sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+ sa->action[1].conf =
+ &(struct rte_flow_action_queue){
+ .index = i,
+ };
+ ret = rte_flow_validate(sa->portid, &sa->attr,
+ sa->pattern, sa->action,
+ &err);
+ if (ret)
+ goto flow_create_failure;
+ } else {
+ sa->action[1].type =
+ RTE_FLOW_ACTION_TYPE_PASSTHRU;
+ sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
+ }
+flow_create:
sa->flow = rte_flow_create(sa->portid,
&sa->attr, sa->pattern, sa->action, &err);
if (sa->flow == NULL) {
+flow_create_failure:
RTE_LOG(ERR, IPSEC,
"Failed to create ipsec flow msg: %s\n",
err.message);
@@ -133,7 +133,7 @@ struct ipsec_sa {
uint32_t ol_flags;
#define MAX_RTE_FLOW_PATTERN (4)
-#define MAX_RTE_FLOW_ACTIONS (2)
+#define MAX_RTE_FLOW_ACTIONS (4)
struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
struct rte_flow_attr attr;