* [PATCH v3 0/7] virtio_user as an alternative exception path
From: Jianfeng Tan @ 2017-01-04 3:59 UTC (permalink / raw)
To: dev; +Cc: yuanhan.liu, ferruh.yigit, cunming.liang, Jianfeng Tan
In-Reply-To: <1480689075-66977-1-git-send-email-jianfeng.tan@intel.com>
v3:
- Drop the patch to postpone driver ok sending patch, superseded it
with a bug fix to disable all virtqueues and re-init the device.
(you might wonder why not just send reset owner msg. Under my test,
it causes spinlock deadlock problem when killing the program).
- Avoid compiling error on 32-bit system for pointer convert.
- Fix a bug in patch "abstract virtio user backend ops", vhostfd is
not properly assigned.
- Fix a "MQ cannot be used" bug in v2, which is related to strip
some feature bits that vhost kernel does not recognize.
- Update release note.
v2: (Lots of them are from yuanhan's comment)
- Add offloding feature.
- Add multiqueue support.
- Add a new patch to postpone the sending of driver ok notification.
- Put fix patch ahead of the whole patch series.
- Split original 0001 patch into 0003 and 0004 patches.
- Remove the original vhost_internal design, just add those into
struct virtio_user_dev for simplicity.
- Reword "control" to "send_request".
- Reword "host_features" to "device_features".
In v16.07, we upstreamed a virtual device, virtio_user (with vhost-user
as the backend). The path to go with a vhost-kernel backend has been
dropped for bad performance comparing to vhost-user and code simplicity.
But after a second thought, virtio_user + vhost-kernel is a good
candidate as an exceptional path, such as KNI, which exchanges packets
with kernel networking stack.
- maintenance: vhost-net (kernel) is upstreamed and extensively used
kernel module. We don't need any out-of-tree module like KNI.
- performance: as with KNI, this solution would use one or more
kthreads to send/receive packets from user space DPDK applications,
which has little impact on user space polling thread (except that
it might enter into kernel space to wake up those kthreads if
necessary).
- features: vhost-net is born to be a networking solution, which has
lots of networking related featuers, like multi queue, tso, multi-seg
mbuf, etc.
Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
Jianfeng Tan (7):
net/virtio_user: fix wrongly set features
net/virtio_user: fix not properly reset device
net/virtio_user: move vhost user specific code
net/virtio_user: abstract virtio user backend ops
net/virtio_user: add vhost kernel support
net/virtio_user: enable offloading
net/virtio_user: enable multiqueue with vhost kernel
doc/guides/rel_notes/release_17_02.rst | 20 +
drivers/net/virtio/Makefile | 1 +
drivers/net/virtio/virtio_user/vhost.h | 51 +--
drivers/net/virtio/virtio_user/vhost_kernel.c | 487 +++++++++++++++++++++++
drivers/net/virtio/virtio_user/vhost_user.c | 97 +++--
drivers/net/virtio/virtio_user/virtio_user_dev.c | 138 ++++---
drivers/net/virtio/virtio_user/virtio_user_dev.h | 16 +-
drivers/net/virtio/virtio_user_ethdev.c | 19 +-
8 files changed, 705 insertions(+), 124 deletions(-)
create mode 100644 drivers/net/virtio/virtio_user/vhost_kernel.c
--
2.7.4
^ permalink raw reply
* Re: [PATCH v3 1/4] ethdev: add firmware information get
From: Yang, Qiming @ 2017-01-04 3:33 UTC (permalink / raw)
To: Yigit, Ferruh; +Cc: dev@dpdk.org, Horton, Remy, Thomas Monjalon
In-Reply-To: <dd3cff72-0433-bfee-4dfa-9662025e5bee@intel.com>
Yes, in my opinion it is. And I use this name already exist in the share code from ND team.
-----Original Message-----
From: Yigit, Ferruh
Sent: Tuesday, January 3, 2017 10:49 PM
To: Yang, Qiming <qiming.yang@intel.com>
Cc: dev@dpdk.org; Horton, Remy <remy.horton@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>
Subject: Re: [PATCH v3 1/4] ethdev: add firmware information get
On 1/3/2017 9:05 AM, Yang, Qiming wrote:
> Hi, Ferruh
> Please see the question below. In my opinion, etrack_id is just a name used to define the ID of one NIC.
> In kernel version ethtool, it will print this ID in the line of firmware verison.
> I know what is etrack_id mean, but I really don't know why this named etrack_id.
Hi Qiming,
I suggested the API based on fields you already used in your patch.
So, this API is to get FW version, is etrack_id something that defines (part of) firmware version?
Thanks,
ferruh
> Can you explain this question?
>
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Tuesday, January 3, 2017 4:40 PM
> To: Yang, Qiming <qiming.yang@intel.com>
> Subject: Re: [PATCH v3 1/4] ethdev: add firmware information get
>
> Please reply below the question and on the mailing list.
> You'll have to explain why this name etrack_id.
>
> 2017-01-03 03:28, Yang, Qiming:
>> Hi, Thomas
>> etrack_id is not a terminology, it's decided by me.
>> Which is store the unique number of the firmware.
>> firmware-version: 5.04 0x800024ca
>> 800024ca is the etrack_id of this NIC.
>>
>> -----Original Message-----
>> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
>> Sent: Monday, January 2, 2017 11:39 PM
>> To: Yang, Qiming <qiming.yang@intel.com>
>> Cc: dev@dpdk.org; Horton, Remy <remy.horton@intel.com>; Yigit, Ferruh
>> <ferruh.yigit@intel.com>
>> Subject: Re: [PATCH v3 1/4] ethdev: add firmware information get
>>
>> 2016-12-27 20:30, Qiming Yang:
>>> /**
>>> + * Retrieve the firmware version of a device.
>>> + *
>>> + * @param port_id
>>> + * The port identifier of the device.
>>> + * @param fw_major
>>> + * A array pointer to store the major firmware version of a device.
>>> + * @param fw_minor
>>> + * A array pointer to store the minor firmware version of a device.
>>> + * @param fw_patch
>>> + * A array pointer to store the firmware patch number of a device.
>>> + * @param etrack_id
>>> + * A array pointer to store the nvm version of a device.
>>> + */
>>> +void rte_eth_dev_fw_info_get(uint8_t port_id, uint32_t *fw_major,
>>> + uint32_t *fw_minor, uint32_t *fw_patch, uint32_t *etrack_id);
>>
>> I have a reserve about the naming etrack_id.
>> Please could you point to a document explaining this ID?
>> Is it known outside of Intel?
>
>
^ permalink raw reply
* [PATCH v5 17/17] net/i40e: flush tunnel filters
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_tunnel_filter_flush function
to flush all tunnel filters, including filters in
SW and HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 2e696d3..c8eae4f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -105,6 +105,7 @@ static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
static int i40e_fdir_filter_flush(struct i40e_pf *pf);
static int i40e_ethertype_filter_flush(struct i40e_pf *pf);
+static int i40e_tunnel_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1671,6 +1672,14 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
return -rte_errno;
}
+ ret = i40e_tunnel_filter_flush(pf);
+ if (ret) {
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to flush tunnel flows.");
+ return -rte_errno;
+ }
+
return ret;
}
@@ -1733,3 +1742,31 @@ i40e_ethertype_filter_flush(struct i40e_pf *pf)
return ret;
}
+
+/* Flush all tunnel filters */
+static int
+i40e_tunnel_filter_flush(struct i40e_pf *pf)
+{
+ struct i40e_tunnel_filter_list
+ *tunnel_list = &pf->tunnel.tunnel_list;
+ struct i40e_tunnel_filter *filter;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret = 0;
+
+ while ((filter = TAILQ_FIRST(tunnel_list))) {
+ ret = i40e_dev_destroy_tunnel_filter(pf, filter);
+ if (ret)
+ return ret;
+ }
+
+ /* Delete tunnel flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_TUNNEL) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 16/17] net/i40e: flush ethertype filters
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_ethertype_filter_flush function
to flush all ethertype filters, including filters in
SW and HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index bc8a76c..2e696d3 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -104,6 +104,7 @@ static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
static int i40e_fdir_filter_flush(struct i40e_pf *pf);
+static int i40e_ethertype_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1655,10 +1656,20 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
int ret;
ret = i40e_fdir_filter_flush(pf);
- if (ret)
+ if (ret) {
rte_flow_error_set(error, -ret,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"Failed to flush FDIR flows.");
+ return -rte_errno;
+ }
+
+ ret = i40e_ethertype_filter_flush(pf);
+ if (ret) {
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to ethertype flush flows.");
+ return -rte_errno;
+ }
return ret;
}
@@ -1694,3 +1705,31 @@ i40e_fdir_filter_flush(struct i40e_pf *pf)
return ret;
}
+
+/* Flush all ethertype filters */
+static int
+i40e_ethertype_filter_flush(struct i40e_pf *pf)
+{
+ struct i40e_ethertype_filter_list
+ *ethertype_list = &pf->ethertype.ethertype_list;
+ struct i40e_ethertype_filter *filter;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret = 0;
+
+ while ((filter = TAILQ_FIRST(ethertype_list))) {
+ ret = i40e_dev_destroy_ethertype_filter(pf, filter);
+ if (ret)
+ return ret;
+ }
+
+ /* Delete ethertype flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_ETHERTYPE) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 15/17] net/i40e: add flow flush function
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_flush function to flush all
filters for users. And flow director flush function
is involved first.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/i40e_fdir.c | 4 +---
drivers/net/i40e/i40e_flow.c | 51 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index b33910d..57fd796 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -788,6 +788,7 @@ int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
uint8_t add);
+int i40e_fdir_flush(struct rte_eth_dev *dev);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 91d91aa..67d63ff 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -119,8 +119,6 @@ static int i40e_fdir_filter_programming(struct i40e_pf *pf,
enum i40e_filter_pctype pctype,
const struct rte_eth_fdir_filter *filter,
bool add);
-static int i40e_fdir_flush(struct rte_eth_dev *dev);
-
static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
struct i40e_fdir_filter *filter);
static struct i40e_fdir_filter *
@@ -1325,7 +1323,7 @@ i40e_fdir_filter_programming(struct i40e_pf *pf,
* i40e_fdir_flush - clear all filters of Flow Director table
* @pf: board private structure
*/
-static int
+int
i40e_fdir_flush(struct rte_eth_dev *dev)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 2674c2c..bc8a76c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -68,6 +68,8 @@ static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static int i40e_flow_flush(struct rte_eth_dev *dev,
+ struct rte_flow_error *error);
static int i40e_flow_destroy(struct rte_eth_dev *dev,
struct rte_flow *flow,
struct rte_flow_error *error);
@@ -101,11 +103,13 @@ static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
+static int i40e_fdir_filter_flush(struct i40e_pf *pf);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
.create = i40e_flow_create,
.destroy = i40e_flow_destroy,
+ .flush = i40e_flow_flush,
};
union i40e_filter_t cons_filter;
@@ -1643,3 +1647,50 @@ i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
return ret;
}
+
+static int
+i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ int ret;
+
+ ret = i40e_fdir_filter_flush(pf);
+ if (ret)
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to flush FDIR flows.");
+
+ return ret;
+}
+
+static int
+i40e_fdir_filter_flush(struct i40e_pf *pf)
+{
+ struct rte_eth_dev *dev = pf->adapter->eth_dev;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *fdir_filter;
+ struct i40e_flow *flow;
+ void *temp;
+ int ret;
+
+ ret = i40e_fdir_flush(dev);
+ if (!ret) {
+ /* Delete FDIR filters in FDIR list. */
+ while ((fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list))) {
+ ret = i40e_sw_fdir_filter_del(pf,
+ &fdir_filter->fdir.input);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Delete FDIR flows in flow list. */
+ TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
+ if (flow->filter_type == RTE_ETH_FILTER_FDIR) {
+ TAILQ_REMOVE(&pf->flow_list, flow, node);
+ rte_free(flow);
+ }
+ }
+ }
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 14/17] net/i40e: destroy flow directory filter
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch supports destroying a flow directory filter
for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index f334844..2674c2c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1552,6 +1552,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
ret = i40e_dev_destroy_tunnel_filter(pf,
(struct i40e_tunnel_filter *)pmd_flow->rule);
break;
+ case RTE_ETH_FILTER_FDIR:
+ ret = i40e_add_del_fdir_filter(dev,
+ &((struct i40e_fdir_filter *)pmd_flow->rule)->fdir, 0);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
--
2.5.5
^ permalink raw reply related
* [PATCH v5 13/17] net/i40e: destroy tunnel filter
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_dev_destroy_tunnel_filter function
to destroy a tunnel filter for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 2940058..f334844 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -99,6 +99,8 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
+static int i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *filter);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1546,6 +1548,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
ret = i40e_dev_destroy_ethertype_filter(pf,
(struct i40e_ethertype_filter *)pmd_flow->rule);
break;
+ case RTE_ETH_FILTER_TUNNEL:
+ ret = i40e_dev_destroy_tunnel_filter(pf,
+ (struct i40e_tunnel_filter *)pmd_flow->rule);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
@@ -1598,3 +1604,38 @@ i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
return ret;
}
+
+static int
+i40e_dev_destroy_tunnel_filter(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *filter)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_vsi *vsi = pf->main_vsi;
+ struct i40e_aqc_add_remove_cloud_filters_element_data cld_filter;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_tunnel_filter *node;
+ int ret = 0;
+
+ memset(&cld_filter, 0, sizeof(cld_filter));
+ ether_addr_copy((struct ether_addr *)&filter->input.outer_mac,
+ (struct ether_addr *)&cld_filter.outer_mac);
+ ether_addr_copy((struct ether_addr *)&filter->input.inner_mac,
+ (struct ether_addr *)&cld_filter.inner_mac);
+ cld_filter.inner_vlan = filter->input.inner_vlan;
+ cld_filter.flags = filter->input.flags;
+ cld_filter.tenant_id = filter->input.tenant_id;
+ cld_filter.queue_number = filter->queue;
+
+ ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
+ &cld_filter, 1);
+ if (ret < 0)
+ return ret;
+
+ node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &filter->input);
+ if (!node)
+ return -EINVAL;
+
+ ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 12/17] net/i40e: destroy ethertype filter
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_dev_destroy_ethertype_filter function
to destroy a ethertype filter for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index ece9f89..2940058 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -49,6 +49,7 @@
#include "i40e_logs.h"
#include "base/i40e_type.h"
+#include "base/i40e_prototype.h"
#include "i40e_ethdev.h"
#define I40E_IPV4_TC_SHIFT 4
@@ -96,6 +97,8 @@ static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
struct rte_eth_tunnel_filter_conf *filter);
static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
+static int i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter);
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
@@ -1539,6 +1542,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
int ret = 0;
switch (filter_type) {
+ case RTE_ETH_FILTER_ETHERTYPE:
+ ret = i40e_dev_destroy_ethertype_filter(pf,
+ (struct i40e_ethertype_filter *)pmd_flow->rule);
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
@@ -1556,3 +1563,38 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
return ret;
}
+
+static int
+i40e_dev_destroy_ethertype_filter(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_ethertype_filter *node;
+ struct i40e_control_filter_stats stats;
+ uint16_t flags = 0;
+ int ret = 0;
+
+ if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
+ if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
+
+ memset(&stats, 0, sizeof(stats));
+ ret = i40e_aq_add_rem_control_packet_filter(hw,
+ filter->input.mac_addr.addr_bytes,
+ filter->input.ether_type,
+ flags, pf->main_vsi->seid,
+ filter->queue, 0, &stats, NULL);
+ if (ret < 0)
+ return ret;
+
+ node = i40e_sw_ethertype_filter_lookup(ethertype_rule, &filter->input);
+ if (!node)
+ return -EINVAL;
+
+ ret = i40e_sw_ethertype_filter_del(pf, &node->input);
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 11/17] net/i40e: add flow destroy function
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_destroy function to destroy
a flow for users.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 3114368..ece9f89 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -67,6 +67,9 @@ static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static int i40e_flow_destroy(struct rte_eth_dev *dev,
+ struct rte_flow *flow,
+ struct rte_flow_error *error);
static int i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
@@ -97,6 +100,7 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
.create = i40e_flow_create,
+ .destroy = i40e_flow_destroy,
};
union i40e_filter_t cons_filter;
@@ -1523,3 +1527,32 @@ i40e_flow_create(struct rte_eth_dev *dev,
rte_free(flow);
return NULL;
}
+
+static int
+i40e_flow_destroy(struct rte_eth_dev *dev,
+ struct rte_flow *flow,
+ struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_flow *pmd_flow = (struct i40e_flow *)flow;
+ enum rte_filter_type filter_type = pmd_flow->filter_type;
+ int ret = 0;
+
+ switch (filter_type) {
+ default:
+ PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+ filter_type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret) {
+ TAILQ_REMOVE(&pf->flow_list, pmd_flow, node);
+ rte_free(pmd_flow);
+ } else
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to destroy flow.");
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 10/17] net/i40e: add flow create function
From: Beilei Xing @ 2017-01-04 3:23 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_create function to create a
rule. It will check if a flow matches ethertype filter
or flow director filter or tunnel filter, if the flow
matches some kind of filter, then set the filter to HW.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 16 ++++++---
drivers/net/i40e/i40e_ethdev.h | 21 ++++++++++++
drivers/net/i40e/i40e_fdir.c | 2 +-
drivers/net/i40e/i40e_flow.c | 77 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index bcf28cf..bbc43dc 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -353,9 +353,6 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
struct rte_eth_udp_tunnel *udp_tunnel);
static void i40e_filter_input_set_init(struct i40e_pf *pf);
-static int i40e_ethertype_filter_set(struct i40e_pf *pf,
- struct rte_eth_ethertype_filter *filter,
- bool add);
static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
enum rte_filter_op filter_op,
void *arg);
@@ -1233,6 +1230,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_fdir_hash_map_alloc;
}
+ TAILQ_INIT(&pf->flow_list);
+
return 0;
err_fdir_hash_map_alloc:
@@ -1273,6 +1272,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
struct rte_pci_device *pci_dev;
struct i40e_hw *hw;
struct i40e_filter_control_settings settings;
+ struct i40e_flow *p_flow;
struct i40e_ethertype_filter *p_ethertype;
struct i40e_tunnel_filter *p_tunnel;
struct i40e_fdir_filter *p_fdir;
@@ -1297,6 +1297,12 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
+ /* Remove all flows */
+ while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
+ TAILQ_REMOVE(&pf->flow_list, p_flow, node);
+ rte_free(p_flow);
+ }
+
/* Remove all ethertype director rules and hash */
if (ethertype_rule->hash_map)
rte_free(ethertype_rule->hash_map);
@@ -6611,7 +6617,7 @@ i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
return 0;
}
-static int
+int
i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
uint8_t add)
@@ -8256,7 +8262,7 @@ i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
* Configure ethertype filter, which can director packet by filtering
* with mac address and ether_type or only ether_type
*/
-static int
+int
i40e_ethertype_filter_set(struct i40e_pf *pf,
struct rte_eth_ethertype_filter *filter,
bool add)
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 9e3a48d..b33910d 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -536,6 +536,17 @@ struct i40e_mirror_rule {
TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule);
/*
+ * Struct to store flow created.
+ */
+struct i40e_flow {
+ TAILQ_ENTRY(i40e_flow) node;
+ enum rte_filter_type filter_type;
+ void *rule;
+};
+
+TAILQ_HEAD(i40e_flow_list, i40e_flow);
+
+/*
* Structure to store private data specific for PF instance.
*/
struct i40e_pf {
@@ -592,6 +603,7 @@ struct i40e_pf {
bool floating_veb; /* The flag to use the floating VEB */
/* The floating enable flag for the specific VF */
bool floating_veb_list[I40E_MAX_VF];
+ struct i40e_flow_list flow_list;
};
enum pending_msg {
@@ -767,6 +779,15 @@ i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
struct i40e_tunnel_filter_input *input);
uint64_t i40e_get_default_input_set(uint16_t pctype);
+int i40e_ethertype_filter_set(struct i40e_pf *pf,
+ struct rte_eth_ethertype_filter *filter,
+ bool add);
+int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
+ const struct rte_eth_fdir_filter *filter,
+ bool add);
+int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
+ struct rte_eth_tunnel_filter_conf *tunnel_filter,
+ uint8_t add);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index f89dbc9..91d91aa 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1099,7 +1099,7 @@ i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
* @filter: fdir filter entry
* @add: 0 - delete, 1 - add
*/
-static int
+int
i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
const struct rte_eth_fdir_filter *filter,
bool add)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 42ebe5e..3114368 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -62,6 +62,11 @@ static int i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct rte_flow_error *error);
+static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
static int i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
@@ -91,9 +96,11 @@ static int i40e_parse_attr(const struct rte_flow_attr *attr,
const struct rte_flow_ops i40e_flow_ops = {
.validate = i40e_flow_validate,
+ .create = i40e_flow_create,
};
union i40e_filter_t cons_filter;
+enum rte_filter_type cons_filter_type = RTE_ETH_FILTER_NONE;
/* Pattern matched ethertype filter */
static enum rte_flow_item_type pattern_ethertype[] = {
@@ -267,6 +274,8 @@ i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_ETHERTYPE;
+
return ret;
}
@@ -294,6 +303,8 @@ i40e_parse_fdir_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_FDIR;
+
if (dev->data->dev_conf.fdir_conf.mode !=
RTE_FDIR_MODE_PERFECT) {
rte_flow_error_set(error, ENOTSUP,
@@ -330,6 +341,8 @@ i40e_parse_tunnel_filter(struct rte_eth_dev *dev,
if (ret)
return ret;
+ cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
return ret;
}
@@ -1446,3 +1459,67 @@ i40e_flow_validate(struct rte_eth_dev *dev,
return ret;
}
+
+static struct rte_flow *
+i40e_flow_create(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_flow *flow;
+ int ret;
+
+ flow = rte_zmalloc("i40e_flow", sizeof(struct i40e_flow), 0);
+ if (!flow) {
+ rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to allocate memory");
+ return (struct rte_flow *)flow;
+ }
+
+ ret = i40e_flow_validate(dev, attr, pattern, actions, error);
+ if (ret < 0)
+ return NULL;
+
+ switch (cons_filter_type) {
+ case RTE_ETH_FILTER_ETHERTYPE:
+ ret = i40e_ethertype_filter_set(pf,
+ &cons_filter.ethertype_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->ethertype.ethertype_list,
+ i40e_ethertype_filter_list);
+ break;
+ case RTE_ETH_FILTER_FDIR:
+ ret = i40e_add_del_fdir_filter(dev,
+ &cons_filter.fdir_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->fdir.fdir_list,
+ i40e_fdir_filter_list);
+ break;
+ case RTE_ETH_FILTER_TUNNEL:
+ ret = i40e_dev_tunnel_filter_set(pf,
+ &cons_filter.tunnel_filter, 1);
+ if (ret)
+ goto free_flow;
+ flow->rule = TAILQ_LAST(&pf->tunnel.tunnel_list,
+ i40e_tunnel_filter_list);
+ break;
+ default:
+ goto free_flow;
+ }
+
+ flow->filter_type = cons_filter_type;
+ TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
+ return (struct rte_flow *)flow;
+
+free_flow:
+ rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to create flow.");
+ rte_free(flow);
+ return NULL;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 09/17] net/i40e: parse tunnel filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_parse_tunnel_filter to check if
a rule is a tunnel rule according to items of the flow
pattern, and the function also gets the tunnel info.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_flow.c | 394 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 394 insertions(+)
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 64b4ab6..42ebe5e 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -54,6 +54,8 @@
#define I40E_IPV4_TC_SHIFT 4
#define I40E_IPV6_TC_MASK (0x00FF << I40E_IPV4_TC_SHIFT)
#define I40E_IPV6_FRAG_HEADER 44
+#define I40E_TENANT_ARRAY_NUM 3
+#define I40E_TCI_MASK 0xFFFF
static int i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -76,6 +78,14 @@ static int i40e_parse_fdir_act(struct rte_eth_dev *dev,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct rte_eth_fdir_filter *filter);
+static int i40e_parse_tunnel_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter);
+static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter);
static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
@@ -192,6 +202,45 @@ static enum rte_flow_item_type pattern_fdir_ipv6_sctp_ext[] = {
RTE_FLOW_ITEM_TYPE_END,
};
+/* Pattern matched tunnel filter */
+static enum rte_flow_item_type pattern_vxlan_1[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_2[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_3[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_VLAN,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_vxlan_4[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_VXLAN,
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_VLAN,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
static int
i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -257,6 +306,33 @@ i40e_parse_fdir_filter(struct rte_eth_dev *dev,
return 0;
}
+static int
+i40e_parse_tunnel_filter(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error,
+ union i40e_filter_t *filter)
+{
+ struct rte_eth_tunnel_filter_conf *tunnel_filter =
+ &filter->tunnel_filter;
+ int ret;
+
+ ret = i40e_parse_tunnel_pattern(dev, pattern, error, tunnel_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_tunnel_act(dev, actions, error, tunnel_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_attr(attr, error);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
static struct i40e_valid_pattern i40e_supported_patterns[] = {
/* Ethertype */
{ pattern_ethertype, i40e_parse_ethertype_filter },
@@ -277,6 +353,11 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
{ pattern_fdir_ipv6_tcp_ext, i40e_parse_fdir_filter },
{ pattern_fdir_ipv6_sctp, i40e_parse_fdir_filter },
{ pattern_fdir_ipv6_sctp_ext, i40e_parse_fdir_filter },
+ /* tunnel */
+ { pattern_vxlan_1, i40e_parse_tunnel_filter },
+ { pattern_vxlan_2, i40e_parse_tunnel_filter },
+ { pattern_vxlan_3, i40e_parse_tunnel_filter },
+ { pattern_vxlan_4, i40e_parse_tunnel_filter },
};
#define NEXT_ITEM_OF_ACTION(act, actions, index) \
@@ -991,6 +1072,319 @@ i40e_parse_fdir_act(struct rte_eth_dev *dev,
return 0;
}
+/* Parse to get the action info of a tunnle filter */
+static int i40e_parse_tunnel_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ const struct rte_flow_action *act;
+ const struct rte_flow_action_queue *act_q;
+ uint32_t index = 0;
+
+ /* Check if the first non-void action is QUEUE. */
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ act_q = (const struct rte_flow_action_queue *)act->conf;
+ filter->queue_id = act_q->index;
+ if (filter->queue_id >= pf->dev_data->nb_rx_queues) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid queue ID for tunnel filter");
+ return -rte_errno;
+ }
+
+ /* Check if the next non-void item is END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+i40e_check_tenant_id_mask(const uint8_t *mask)
+{
+ uint32_t j;
+ int is_masked = 0;
+
+ for (j = 0; j < I40E_TENANT_ARRAY_NUM; j++) {
+ if (*(mask + j) == UINT8_MAX) {
+ if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+ return -EINVAL;
+ is_masked = 0;
+ } else if (*(mask + j) == 0) {
+ if (j > 0 && (*(mask + j) != *(mask + j - 1)))
+ return -EINVAL;
+ is_masked = 1;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ return is_masked;
+}
+
+static int
+i40e_parse_vxlan_pattern(const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ const struct rte_flow_item *item = pattern;
+ const struct rte_flow_item_eth *eth_spec;
+ const struct rte_flow_item_eth *eth_mask;
+ const struct rte_flow_item_eth *o_eth_spec = NULL;
+ const struct rte_flow_item_eth *o_eth_mask = NULL;
+ const struct rte_flow_item_vxlan *vxlan_spec = NULL;
+ const struct rte_flow_item_vxlan *vxlan_mask = NULL;
+ const struct rte_flow_item_eth *i_eth_spec = NULL;
+ const struct rte_flow_item_eth *i_eth_mask = NULL;
+ const struct rte_flow_item_vlan *vlan_spec = NULL;
+ const struct rte_flow_item_vlan *vlan_mask = NULL;
+ bool is_vni_masked = 0;
+ enum rte_flow_item_type item_type;
+ bool vxlan_flag = 0;
+
+ for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+ if (item->last) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Not support range");
+ return -rte_errno;
+ }
+ item_type = item->type;
+ switch (item_type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ eth_spec = (const struct rte_flow_item_eth *)item->spec;
+ eth_mask = (const struct rte_flow_item_eth *)item->mask;
+ if ((!eth_spec && eth_mask) ||
+ (eth_spec && !eth_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ether spec/mask");
+ return -rte_errno;
+ }
+
+ if (eth_spec && eth_mask) {
+ /* DST address of inner MAC shouldn't be masked.
+ * SRC address of Inner MAC should be masked.
+ */
+ if (!is_broadcast_ether_addr(ð_mask->dst) ||
+ !is_zero_ether_addr(ð_mask->src) ||
+ eth_mask->type) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ether spec/mask");
+ return -rte_errno;
+ }
+
+ if (!vxlan_flag)
+ rte_memcpy(&filter->outer_mac,
+ ð_spec->dst,
+ ETHER_ADDR_LEN);
+ else
+ rte_memcpy(&filter->inner_mac,
+ ð_spec->dst,
+ ETHER_ADDR_LEN);
+ }
+
+ if (!vxlan_flag) {
+ o_eth_spec = eth_spec;
+ o_eth_mask = eth_mask;
+ } else {
+ i_eth_spec = eth_spec;
+ i_eth_mask = eth_mask;
+ }
+
+ break;
+ case RTE_FLOW_ITEM_TYPE_VLAN:
+ vlan_spec =
+ (const struct rte_flow_item_vlan *)item->spec;
+ vlan_mask =
+ (const struct rte_flow_item_vlan *)item->mask;
+ if (vxlan_flag) {
+ vlan_spec =
+ (const struct rte_flow_item_vlan *)item->spec;
+ vlan_mask =
+ (const struct rte_flow_item_vlan *)item->mask;
+ if (!(vlan_spec && vlan_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid vlan item");
+ return -rte_errno;
+ }
+ } else {
+ if (vlan_spec || vlan_mask)
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid vlan item");
+ return -rte_errno;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ /* IPv4/IPv6/UDP are used to describe protocol,
+ * spec amd mask should be NULL.
+ */
+ if (item->spec || item->mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid IPv4 item");
+ return -rte_errno;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ vxlan_spec =
+ (const struct rte_flow_item_vxlan *)item->spec;
+ vxlan_mask =
+ (const struct rte_flow_item_vxlan *)item->mask;
+ /* Check if VXLAN item is used to describe protocol.
+ * If yes, both spec and mask should be NULL.
+ * If no, either spec or mask shouldn't be NULL.
+ */
+ if ((!vxlan_spec && vxlan_mask) ||
+ (vxlan_spec && !vxlan_mask)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid VXLAN item");
+ return -rte_errno;
+ }
+
+ /* Check if VNI is masked. */
+ if (vxlan_mask) {
+ is_vni_masked =
+ i40e_check_tenant_id_mask(vxlan_mask->vni);
+ if (is_vni_masked < 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid VNI mask");
+ return -rte_errno;
+ }
+ }
+ vxlan_flag = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Check specification and mask to get the filter type */
+ if (vlan_spec && vlan_mask &&
+ (vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
+ /* If there's inner vlan */
+ filter->inner_vlan = rte_be_to_cpu_16(vlan_spec->tci)
+ & I40E_TCI_MASK;
+ if (vxlan_spec && vxlan_mask && !is_vni_masked) {
+ /* If there's vxlan */
+ rte_memcpy(&filter->tenant_id, vxlan_spec->vni,
+ RTE_DIM(vxlan_spec->vni));
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID;
+ else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else if (!vxlan_spec && !vxlan_mask) {
+ /* If there's no vxlan */
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN;
+ else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else if ((!vlan_spec && !vlan_mask) ||
+ (vlan_spec && vlan_mask && vlan_mask->tci == 0x0)) {
+ /* If there's no inner vlan */
+ if (vxlan_spec && vxlan_mask && !is_vni_masked) {
+ /* If there's vxlan */
+ rte_memcpy(&filter->tenant_id, vxlan_spec->vni,
+ RTE_DIM(vxlan_spec->vni));
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_IMAC_TENID;
+ else if (o_eth_spec && o_eth_mask &&
+ i_eth_spec && i_eth_mask)
+ filter->filter_type =
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC;
+ } else if (!vxlan_spec && !vxlan_mask) {
+ /* If there's no vxlan */
+ if (!o_eth_spec && !o_eth_mask &&
+ i_eth_spec && i_eth_mask) {
+ filter->filter_type = ETH_TUNNEL_FILTER_IMAC;
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Invalid filter type");
+ return -rte_errno;
+ }
+ } else {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Not supported by tunnel filter.");
+ return -rte_errno;
+ }
+
+ filter->tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ return 0;
+}
+
+static int
+i40e_parse_tunnel_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_tunnel_filter_conf *filter)
+{
+ int ret;
+
+ ret = i40e_parse_vxlan_pattern(pattern, error, filter);
+
+ return ret;
+}
+
static int
i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
--
2.5.5
^ permalink raw reply related
* [PATCH v5 08/17] net/i40e: parse flow director filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_parse_fdir_filter to check if a rule
is a flow director rule according to the flow pattern,
and the function also gets the flow director info.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 56 +---
drivers/net/i40e/i40e_ethdev.h | 55 ++++
drivers/net/i40e/i40e_flow.c | 607 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 663 insertions(+), 55 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index edfd52b..bcf28cf 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -139,60 +139,6 @@
#define I40E_DEFAULT_DCB_APP_NUM 1
#define I40E_DEFAULT_DCB_APP_PRIO 3
-#define I40E_INSET_NONE 0x00000000000000000ULL
-
-/* bit0 ~ bit 7 */
-#define I40E_INSET_DMAC 0x0000000000000001ULL
-#define I40E_INSET_SMAC 0x0000000000000002ULL
-#define I40E_INSET_VLAN_OUTER 0x0000000000000004ULL
-#define I40E_INSET_VLAN_INNER 0x0000000000000008ULL
-#define I40E_INSET_VLAN_TUNNEL 0x0000000000000010ULL
-
-/* bit 8 ~ bit 15 */
-#define I40E_INSET_IPV4_SRC 0x0000000000000100ULL
-#define I40E_INSET_IPV4_DST 0x0000000000000200ULL
-#define I40E_INSET_IPV6_SRC 0x0000000000000400ULL
-#define I40E_INSET_IPV6_DST 0x0000000000000800ULL
-#define I40E_INSET_SRC_PORT 0x0000000000001000ULL
-#define I40E_INSET_DST_PORT 0x0000000000002000ULL
-#define I40E_INSET_SCTP_VT 0x0000000000004000ULL
-
-/* bit 16 ~ bit 31 */
-#define I40E_INSET_IPV4_TOS 0x0000000000010000ULL
-#define I40E_INSET_IPV4_PROTO 0x0000000000020000ULL
-#define I40E_INSET_IPV4_TTL 0x0000000000040000ULL
-#define I40E_INSET_IPV6_TC 0x0000000000080000ULL
-#define I40E_INSET_IPV6_FLOW 0x0000000000100000ULL
-#define I40E_INSET_IPV6_NEXT_HDR 0x0000000000200000ULL
-#define I40E_INSET_IPV6_HOP_LIMIT 0x0000000000400000ULL
-#define I40E_INSET_TCP_FLAGS 0x0000000000800000ULL
-
-/* bit 32 ~ bit 47, tunnel fields */
-#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL
-#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL
-#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL
-#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL
-#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL
-#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL
-
-/* bit 48 ~ bit 55 */
-#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL
-
-/* bit 56 ~ bit 63, Flex Payload */
-#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL
-#define I40E_INSET_FLEX_PAYLOAD \
- (I40E_INSET_FLEX_PAYLOAD_W1 | I40E_INSET_FLEX_PAYLOAD_W2 | \
- I40E_INSET_FLEX_PAYLOAD_W3 | I40E_INSET_FLEX_PAYLOAD_W4 | \
- I40E_INSET_FLEX_PAYLOAD_W5 | I40E_INSET_FLEX_PAYLOAD_W6 | \
- I40E_INSET_FLEX_PAYLOAD_W7 | I40E_INSET_FLEX_PAYLOAD_W8)
-
/**
* Below are values for writing un-exposed registers suggested
* by silicon experts
@@ -7617,7 +7563,7 @@ i40e_validate_input_set(enum i40e_filter_pctype pctype,
}
/* default input set fields combination per pctype */
-static uint64_t
+uint64_t
i40e_get_default_input_set(uint16_t pctype)
{
static const uint64_t default_inset_table[] = {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 23f360b..9e3a48d 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -190,6 +190,60 @@ enum i40e_flxpld_layer_idx {
#define FLOATING_VEB_SUPPORTED_FW_MAJ 5
#define FLOATING_VEB_SUPPORTED_FW_MIN 0
+#define I40E_INSET_NONE 0x00000000000000000ULL
+
+/* bit0 ~ bit 7 */
+#define I40E_INSET_DMAC 0x0000000000000001ULL
+#define I40E_INSET_SMAC 0x0000000000000002ULL
+#define I40E_INSET_VLAN_OUTER 0x0000000000000004ULL
+#define I40E_INSET_VLAN_INNER 0x0000000000000008ULL
+#define I40E_INSET_VLAN_TUNNEL 0x0000000000000010ULL
+
+/* bit 8 ~ bit 15 */
+#define I40E_INSET_IPV4_SRC 0x0000000000000100ULL
+#define I40E_INSET_IPV4_DST 0x0000000000000200ULL
+#define I40E_INSET_IPV6_SRC 0x0000000000000400ULL
+#define I40E_INSET_IPV6_DST 0x0000000000000800ULL
+#define I40E_INSET_SRC_PORT 0x0000000000001000ULL
+#define I40E_INSET_DST_PORT 0x0000000000002000ULL
+#define I40E_INSET_SCTP_VT 0x0000000000004000ULL
+
+/* bit 16 ~ bit 31 */
+#define I40E_INSET_IPV4_TOS 0x0000000000010000ULL
+#define I40E_INSET_IPV4_PROTO 0x0000000000020000ULL
+#define I40E_INSET_IPV4_TTL 0x0000000000040000ULL
+#define I40E_INSET_IPV6_TC 0x0000000000080000ULL
+#define I40E_INSET_IPV6_FLOW 0x0000000000100000ULL
+#define I40E_INSET_IPV6_NEXT_HDR 0x0000000000200000ULL
+#define I40E_INSET_IPV6_HOP_LIMIT 0x0000000000400000ULL
+#define I40E_INSET_TCP_FLAGS 0x0000000000800000ULL
+
+/* bit 32 ~ bit 47, tunnel fields */
+#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL
+#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL
+#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL
+#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL
+#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL
+#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL
+
+/* bit 48 ~ bit 55 */
+#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL
+
+/* bit 56 ~ bit 63, Flex Payload */
+#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD \
+ (I40E_INSET_FLEX_PAYLOAD_W1 | I40E_INSET_FLEX_PAYLOAD_W2 | \
+ I40E_INSET_FLEX_PAYLOAD_W3 | I40E_INSET_FLEX_PAYLOAD_W4 | \
+ I40E_INSET_FLEX_PAYLOAD_W5 | I40E_INSET_FLEX_PAYLOAD_W6 | \
+ I40E_INSET_FLEX_PAYLOAD_W7 | I40E_INSET_FLEX_PAYLOAD_W8)
+
struct i40e_adapter;
/**
@@ -712,6 +766,7 @@ i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
const struct i40e_tunnel_filter_input *input);
int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
struct i40e_tunnel_filter_input *input);
+uint64_t i40e_get_default_input_set(uint16_t pctype);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index a9ff73f..64b4ab6 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -51,6 +51,10 @@
#include "base/i40e_type.h"
#include "i40e_ethdev.h"
+#define I40E_IPV4_TC_SHIFT 4
+#define I40E_IPV6_TC_MASK (0x00FF << I40E_IPV4_TC_SHIFT)
+#define I40E_IPV6_FRAG_HEADER 44
+
static int i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
@@ -64,6 +68,14 @@ static int i40e_parse_ethertype_act(struct rte_eth_dev *dev,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct rte_eth_ethertype_filter *filter);
+static int i40e_parse_fdir_pattern(struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_fdir_filter *filter);
+static int i40e_parse_fdir_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_fdir_filter *filter);
static int i40e_parse_attr(const struct rte_flow_attr *attr,
struct rte_flow_error *error);
@@ -79,6 +91,107 @@ static enum rte_flow_item_type pattern_ethertype[] = {
RTE_FLOW_ITEM_TYPE_END,
};
+/* Pattern matched flow director filter */
+static enum rte_flow_item_type pattern_fdir_ipv4[] = {
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_udp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_udp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_tcp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_tcp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_sctp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_sctp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6[] = {
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_udp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_udp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_tcp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_tcp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_sctp[] = {
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_sctp_ext[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV6,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
static int
i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -108,9 +221,62 @@ i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
return ret;
}
+static int
+i40e_parse_fdir_filter(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error,
+ union i40e_filter_t *filter)
+{
+ struct rte_eth_fdir_filter *fdir_filter =
+ &filter->fdir_filter;
+ int ret;
+
+ ret = i40e_parse_fdir_pattern(dev, pattern, error, fdir_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_fdir_act(dev, actions, error, fdir_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_attr(attr, error);
+ if (ret)
+ return ret;
+
+ if (dev->data->dev_conf.fdir_conf.mode !=
+ RTE_FDIR_MODE_PERFECT) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Check the mode in fdir_conf.");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
static struct i40e_valid_pattern i40e_supported_patterns[] = {
/* Ethertype */
{ pattern_ethertype, i40e_parse_ethertype_filter },
+ /* FDIR */
+ { pattern_fdir_ipv4, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_udp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_udp_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_tcp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_tcp_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_sctp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv4_sctp_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_udp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_udp_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_tcp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_tcp_ext, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_sctp, i40e_parse_fdir_filter },
+ { pattern_fdir_ipv6_sctp_ext, i40e_parse_fdir_filter },
};
#define NEXT_ITEM_OF_ACTION(act, actions, index) \
@@ -385,6 +551,447 @@ i40e_parse_ethertype_act(struct rte_eth_dev *dev,
}
static int
+i40e_parse_fdir_pattern(struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_fdir_filter *filter)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ const struct rte_flow_item *item = pattern;
+ const struct rte_flow_item_eth *eth_spec, *eth_mask;
+ const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
+ const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
+ const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+ const struct rte_flow_item_udp *udp_spec, *udp_mask;
+ const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+ const struct rte_flow_item_vf *vf_spec;
+ uint32_t flow_type = RTE_ETH_FLOW_UNKNOWN;
+ enum i40e_filter_pctype pctype;
+ uint64_t input_set = I40E_INSET_NONE;
+ uint16_t flag_offset;
+ enum rte_flow_item_type item_type;
+ enum rte_flow_item_type l3 = RTE_FLOW_ITEM_TYPE_END;
+ uint32_t j;
+
+ for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+ if (item->last) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Not support range");
+ return -rte_errno;
+ }
+ item_type = item->type;
+ switch (item_type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ eth_spec = (const struct rte_flow_item_eth *)item->spec;
+ eth_mask = (const struct rte_flow_item_eth *)item->mask;
+ if (eth_spec || eth_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ETH spec/mask");
+ return -rte_errno;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ l3 = RTE_FLOW_ITEM_TYPE_IPV4;
+ ipv4_spec =
+ (const struct rte_flow_item_ipv4 *)item->spec;
+ ipv4_mask =
+ (const struct rte_flow_item_ipv4 *)item->mask;
+ if (!ipv4_spec || !ipv4_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL IPv4 spec/mask");
+ return -rte_errno;
+ }
+
+ /* Check IPv4 mask and update input set */
+ if (ipv4_mask->hdr.version_ihl ||
+ ipv4_mask->hdr.total_length ||
+ ipv4_mask->hdr.packet_id ||
+ ipv4_mask->hdr.fragment_offset ||
+ ipv4_mask->hdr.hdr_checksum) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid IPv4 mask.");
+ return -rte_errno;
+ }
+
+ if (ipv4_mask->hdr.src_addr == UINT32_MAX)
+ input_set |= I40E_INSET_IPV4_SRC;
+ if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
+ input_set |= I40E_INSET_IPV4_DST;
+ if (ipv4_mask->hdr.type_of_service == UINT8_MAX)
+ input_set |= I40E_INSET_IPV4_TOS;
+ if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
+ input_set |= I40E_INSET_IPV4_TTL;
+ if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
+ input_set |= I40E_INSET_IPV4_PROTO;
+
+ /* Get filter info */
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER;
+ /* Check if it is fragment. */
+ flag_offset =
+ rte_be_to_cpu_16(ipv4_spec->hdr.fragment_offset);
+ if (flag_offset & IPV4_HDR_OFFSET_MASK ||
+ flag_offset & IPV4_HDR_MF_FLAG)
+ flow_type = RTE_ETH_FLOW_FRAG_IPV4;
+
+ /* Get the filter info */
+ filter->input.flow.ip4_flow.proto =
+ ipv4_spec->hdr.next_proto_id;
+ filter->input.flow.ip4_flow.tos =
+ ipv4_spec->hdr.type_of_service;
+ filter->input.flow.ip4_flow.ttl =
+ ipv4_spec->hdr.time_to_live;
+ filter->input.flow.ip4_flow.src_ip =
+ ipv4_spec->hdr.src_addr;
+ filter->input.flow.ip4_flow.dst_ip =
+ ipv4_spec->hdr.dst_addr;
+
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ l3 = RTE_FLOW_ITEM_TYPE_IPV6;
+ ipv6_spec =
+ (const struct rte_flow_item_ipv6 *)item->spec;
+ ipv6_mask =
+ (const struct rte_flow_item_ipv6 *)item->mask;
+ if (!ipv6_spec || !ipv6_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL IPv6 spec/mask");
+ return -rte_errno;
+ }
+
+ /* Check IPv6 mask and update input set */
+ if (ipv6_mask->hdr.payload_len) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid IPv6 mask");
+ return -rte_errno;
+ }
+
+ /* SCR and DST address of IPv6 shouldn't be masked */
+ for (j = 0; j < RTE_DIM(ipv6_mask->hdr.src_addr); j++) {
+ if (ipv6_mask->hdr.src_addr[j] != UINT8_MAX ||
+ ipv6_mask->hdr.dst_addr[j] != UINT8_MAX) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid IPv6 mask");
+ return -rte_errno;
+ }
+ }
+
+ input_set |= I40E_INSET_IPV6_SRC;
+ input_set |= I40E_INSET_IPV6_DST;
+
+ if ((ipv6_mask->hdr.vtc_flow &
+ rte_cpu_to_be_16(I40E_IPV6_TC_MASK))
+ == rte_cpu_to_be_16(I40E_IPV6_TC_MASK))
+ input_set |= I40E_INSET_IPV6_TC;
+ if (ipv6_mask->hdr.proto == UINT8_MAX)
+ input_set |= I40E_INSET_IPV6_NEXT_HDR;
+ if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
+ input_set |= I40E_INSET_IPV6_HOP_LIMIT;
+
+ /* Get filter info */
+ filter->input.flow.ipv6_flow.tc =
+ (uint8_t)(ipv6_spec->hdr.vtc_flow <<
+ I40E_IPV4_TC_SHIFT);
+ filter->input.flow.ipv6_flow.proto =
+ ipv6_spec->hdr.proto;
+ filter->input.flow.ipv6_flow.hop_limits =
+ ipv6_spec->hdr.hop_limits;
+
+ rte_memcpy(filter->input.flow.ipv6_flow.src_ip,
+ ipv6_spec->hdr.src_addr, 16);
+ rte_memcpy(filter->input.flow.ipv6_flow.dst_ip,
+ ipv6_spec->hdr.dst_addr, 16);
+
+ /* Check if it is fragment. */
+ if (ipv6_spec->hdr.proto == I40E_IPV6_FRAG_HEADER)
+ flow_type = RTE_ETH_FLOW_FRAG_IPV6;
+ else
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV6_OTHER;
+ break;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ tcp_spec = (const struct rte_flow_item_tcp *)item->spec;
+ tcp_mask = (const struct rte_flow_item_tcp *)item->mask;
+ if (!tcp_spec || !tcp_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL TCP spec/mask");
+ return -rte_errno;
+ }
+
+ /* Check TCP mask and update input set */
+ if (tcp_mask->hdr.sent_seq ||
+ tcp_mask->hdr.recv_ack ||
+ tcp_mask->hdr.data_off ||
+ tcp_mask->hdr.tcp_flags ||
+ tcp_mask->hdr.rx_win ||
+ tcp_mask->hdr.cksum ||
+ tcp_mask->hdr.tcp_urp) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid TCP mask");
+ return -rte_errno;
+ }
+
+ if (tcp_mask->hdr.src_port != UINT16_MAX ||
+ tcp_mask->hdr.dst_port != UINT16_MAX) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid TCP mask");
+ return -rte_errno;
+ }
+
+ input_set |= I40E_INSET_SRC_PORT;
+ input_set |= I40E_INSET_DST_PORT;
+
+ /* Get filter info */
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV4_TCP;
+ else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV6_TCP;
+
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+ filter->input.flow.tcp4_flow.src_port =
+ tcp_spec->hdr.src_port;
+ filter->input.flow.tcp4_flow.dst_port =
+ tcp_spec->hdr.dst_port;
+ } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+ filter->input.flow.tcp6_flow.src_port =
+ tcp_spec->hdr.src_port;
+ filter->input.flow.tcp6_flow.dst_port =
+ tcp_spec->hdr.dst_port;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ udp_spec = (const struct rte_flow_item_udp *)item->spec;
+ udp_mask = (const struct rte_flow_item_udp *)item->mask;
+ if (!udp_spec || !udp_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL UDP spec/mask");
+ return -rte_errno;
+ }
+
+ /* Check UDP mask and update input set*/
+ if (udp_mask->hdr.dgram_len ||
+ udp_mask->hdr.dgram_cksum) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid UDP mask");
+ return -rte_errno;
+ }
+
+ if (udp_mask->hdr.src_port != UINT16_MAX ||
+ udp_mask->hdr.dst_port != UINT16_MAX) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid UDP mask");
+ return -rte_errno;
+ }
+
+ input_set |= I40E_INSET_SRC_PORT;
+ input_set |= I40E_INSET_DST_PORT;
+
+ /* Get filter info */
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+ flow_type =
+ RTE_ETH_FLOW_NONFRAG_IPV4_UDP;
+ else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+ flow_type =
+ RTE_ETH_FLOW_NONFRAG_IPV6_UDP;
+
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+ filter->input.flow.udp4_flow.src_port =
+ udp_spec->hdr.src_port;
+ filter->input.flow.udp4_flow.dst_port =
+ udp_spec->hdr.dst_port;
+ } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+ filter->input.flow.udp6_flow.src_port =
+ udp_spec->hdr.src_port;
+ filter->input.flow.udp6_flow.dst_port =
+ udp_spec->hdr.dst_port;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_SCTP:
+ sctp_spec =
+ (const struct rte_flow_item_sctp *)item->spec;
+ sctp_mask =
+ (const struct rte_flow_item_sctp *)item->mask;
+ if (!sctp_spec || !sctp_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL SCTP spec/mask");
+ return -rte_errno;
+ }
+
+ /* Check SCTP mask and update input set */
+ if (sctp_mask->hdr.cksum) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid UDP mask");
+ return -rte_errno;
+ }
+
+ if (sctp_mask->hdr.src_port != UINT16_MAX ||
+ sctp_mask->hdr.dst_port != UINT16_MAX ||
+ sctp_mask->hdr.tag != UINT32_MAX) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid UDP mask");
+ return -rte_errno;
+ }
+ input_set |= I40E_INSET_SRC_PORT;
+ input_set |= I40E_INSET_DST_PORT;
+ input_set |= I40E_INSET_SCTP_VT;
+
+ /* Get filter info */
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV4_SCTP;
+ else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6)
+ flow_type = RTE_ETH_FLOW_NONFRAG_IPV6_SCTP;
+
+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
+ filter->input.flow.sctp4_flow.src_port =
+ sctp_spec->hdr.src_port;
+ filter->input.flow.sctp4_flow.dst_port =
+ sctp_spec->hdr.dst_port;
+ filter->input.flow.sctp4_flow.verify_tag =
+ sctp_spec->hdr.tag;
+ } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
+ filter->input.flow.sctp6_flow.src_port =
+ sctp_spec->hdr.src_port;
+ filter->input.flow.sctp6_flow.dst_port =
+ sctp_spec->hdr.dst_port;
+ filter->input.flow.sctp6_flow.verify_tag =
+ sctp_spec->hdr.tag;
+ }
+ break;
+ case RTE_FLOW_ITEM_TYPE_VF:
+ vf_spec = (const struct rte_flow_item_vf *)item->spec;
+ filter->input.flow_ext.is_vf = 1;
+ filter->input.flow_ext.dst_id = vf_spec->id;
+ if (filter->input.flow_ext.is_vf &&
+ filter->input.flow_ext.dst_id >= pf->vf_num) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid VF ID for FDIR.");
+ return -rte_errno;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ pctype = i40e_flowtype_to_pctype(flow_type);
+ if (pctype == 0 || pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Unsupported flow type");
+ return -rte_errno;
+ }
+
+ if (input_set != i40e_get_default_input_set(pctype)) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Invalid input set.");
+ return -rte_errno;
+ }
+ filter->input.flow_type = flow_type;
+
+ return 0;
+}
+
+/* Parse to get the action info of a FDIR filter */
+static int
+i40e_parse_fdir_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_fdir_filter *filter)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ const struct rte_flow_action *act;
+ const struct rte_flow_action_queue *act_q;
+ const struct rte_flow_action_mark *mark_spec;
+ uint32_t index = 0;
+
+ /* Check if the first non-void action is QUEUE or DROP. */
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
+ act->type != RTE_FLOW_ACTION_TYPE_DROP) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid action.");
+ return -rte_errno;
+ }
+
+ act_q = (const struct rte_flow_action_queue *)act->conf;
+ filter->action.flex_off = 0;
+ if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE)
+ filter->action.behavior = RTE_ETH_FDIR_ACCEPT;
+ else
+ filter->action.behavior = RTE_ETH_FDIR_REJECT;
+
+ filter->action.report_status = RTE_ETH_FDIR_REPORT_ID;
+ filter->action.rx_queue = act_q->index;
+
+ if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "Invalid queue ID for FDIR.");
+ return -rte_errno;
+ }
+
+ /* Check if the next non-void item is MARK or END. */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_MARK &&
+ act->type != RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid action.");
+ return -rte_errno;
+ }
+
+ if (act->type == RTE_FLOW_ACTION_TYPE_MARK) {
+ mark_spec = (const struct rte_flow_action_mark *)act->conf;
+ filter->soft_id = mark_spec->id;
+
+ /* Check if the next non-void item is END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid action.");
+ return -rte_errno;
+ }
+ }
+
+ return 0;
+}
+
+static int
i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
--
2.5.5
^ permalink raw reply related
* [PATCH v5 07/17] net/i40e: add flow validate function
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
This patch adds i40e_flow_validation function to check if
a flow is valid according to the flow pattern.
i40e_parse_ethertype_filter is added first, it also gets
the ethertype info.
i40e_flow.c is added to handle all generic filter events.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/Makefile | 1 +
drivers/net/i40e/i40e_ethdev.c | 7 +
drivers/net/i40e/i40e_ethdev.h | 18 ++
drivers/net/i40e/i40e_flow.c | 447 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 473 insertions(+)
create mode 100644 drivers/net/i40e/i40e_flow.c
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 11175c4..89bd85a 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -105,6 +105,7 @@ endif
SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c
SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c
SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
# vector PMD driver needs SSE4.1 support
ifeq ($(findstring RTE_MACHINE_CPUFLAG_SSE4_1,$(CFLAGS)),)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 153322a..edfd52b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -8426,6 +8426,8 @@ i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
return ret;
}
+const struct rte_flow_ops i40e_flow_ops;
+
static int
i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
@@ -8457,6 +8459,11 @@ i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
case RTE_ETH_FILTER_FDIR:
ret = i40e_fdir_ctrl_func(dev, filter_op, arg);
break;
+ case RTE_ETH_FILTER_GENERIC:
+ if (filter_op != RTE_ETH_FILTER_GET)
+ return -EINVAL;
+ *(const void **)arg = &i40e_flow_ops;
+ break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
filter_type);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 92f6f55..23f360b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -38,6 +38,7 @@
#include <rte_time.h>
#include <rte_kvargs.h>
#include <rte_hash.h>
+#include <rte_flow_driver.h>
#define I40E_VLAN_TAG_SIZE 4
@@ -629,6 +630,23 @@ struct i40e_adapter {
struct rte_timecounter tx_tstamp_tc;
};
+union i40e_filter_t {
+ struct rte_eth_ethertype_filter ethertype_filter;
+ struct rte_eth_fdir_filter fdir_filter;
+ struct rte_eth_tunnel_filter_conf tunnel_filter;
+};
+
+typedef int (*parse_filter_t)(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error,
+ union i40e_filter_t *filter);
+struct i40e_valid_pattern {
+ enum rte_flow_item_type *items;
+ parse_filter_t parse_filter;
+};
+
int i40e_dev_switch_queues(struct i40e_pf *pf, bool on);
int i40e_vsi_release(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf,
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
new file mode 100644
index 0000000..a9ff73f
--- /dev/null
+++ b/drivers/net/i40e/i40e_flow.c
@@ -0,0 +1,447 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_eth_ctrl.h>
+#include <rte_tailq.h>
+#include <rte_flow_driver.h>
+
+#include "i40e_logs.h"
+#include "base/i40e_type.h"
+#include "i40e_ethdev.h"
+
+static int i40e_flow_validate(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
+static int i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_ethertype_filter *filter);
+static int i40e_parse_ethertype_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_ethertype_filter *filter);
+static int i40e_parse_attr(const struct rte_flow_attr *attr,
+ struct rte_flow_error *error);
+
+const struct rte_flow_ops i40e_flow_ops = {
+ .validate = i40e_flow_validate,
+};
+
+union i40e_filter_t cons_filter;
+
+/* Pattern matched ethertype filter */
+static enum rte_flow_item_type pattern_ethertype[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_END,
+};
+
+static int
+i40e_parse_ethertype_filter(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error,
+ union i40e_filter_t *filter)
+{
+ struct rte_eth_ethertype_filter *ethertype_filter =
+ &filter->ethertype_filter;
+ int ret;
+
+ ret = i40e_parse_ethertype_pattern(dev, pattern, error,
+ ethertype_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_ethertype_act(dev, actions, error,
+ ethertype_filter);
+ if (ret)
+ return ret;
+
+ ret = i40e_parse_attr(attr, error);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static struct i40e_valid_pattern i40e_supported_patterns[] = {
+ /* Ethertype */
+ { pattern_ethertype, i40e_parse_ethertype_filter },
+};
+
+#define NEXT_ITEM_OF_ACTION(act, actions, index) \
+ do { \
+ act = actions + index; \
+ while (act->type == RTE_FLOW_ACTION_TYPE_VOID) { \
+ index++; \
+ act = actions + index; \
+ } \
+ } while (0)
+
+/* Find the first VOID or non-VOID item pointer */
+static const struct rte_flow_item *
+i40e_find_first_item(const struct rte_flow_item *item, bool is_void)
+{
+ bool is_find;
+
+ while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+ if (is_void)
+ is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
+ else
+ is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
+ if (is_find)
+ break;
+ item++;
+ }
+ return item;
+}
+
+/* Skip all VOID items of the pattern */
+static void
+i40e_pattern_skip_void_item(struct rte_flow_item *items,
+ const struct rte_flow_item *pattern)
+{
+ uint32_t cpy_count = 0;
+ const struct rte_flow_item *pb = pattern, *pe = pattern;
+
+ for (;;) {
+ /* Find a non-void item first */
+ pb = i40e_find_first_item(pb, false);
+ if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
+ pe = pb;
+ break;
+ }
+
+ /* Find a void item */
+ pe = i40e_find_first_item(pb + 1, true);
+
+ cpy_count = pe - pb;
+ rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
+
+ items += cpy_count;
+
+ if (pe->type == RTE_FLOW_ITEM_TYPE_END) {
+ pb = pe;
+ break;
+ }
+
+ pb = pe + 1;
+ }
+ /* Copy the END item. */
+ rte_memcpy(items, pe, sizeof(struct rte_flow_item));
+}
+
+/* Check if the pattern matches a supported item type array */
+static bool
+i40e_match_pattern(enum rte_flow_item_type *item_array,
+ struct rte_flow_item *pattern)
+{
+ struct rte_flow_item *item = pattern;
+
+ while ((*item_array == item->type) &&
+ (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
+ item_array++;
+ item++;
+ }
+
+ return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
+ item->type == RTE_FLOW_ITEM_TYPE_END);
+}
+
+/* Find if there's parse filter function matched */
+static parse_filter_t
+i40e_find_parse_filter_func(struct rte_flow_item *pattern)
+{
+ parse_filter_t parse_filter = NULL;
+ uint8_t i = 0;
+
+ for (; i < RTE_DIM(i40e_supported_patterns); i++) {
+ if (i40e_match_pattern(i40e_supported_patterns[i].items,
+ pattern)) {
+ parse_filter = i40e_supported_patterns[i].parse_filter;
+ break;
+ }
+ }
+
+ return parse_filter;
+}
+
+/* Parse attributes */
+static int
+i40e_parse_attr(const struct rte_flow_attr *attr,
+ struct rte_flow_error *error)
+{
+ /* Must be input direction */
+ if (!attr->ingress) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+ attr, "Only support ingress.");
+ return -rte_errno;
+ }
+
+ /* Not supported */
+ if (attr->egress) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+ attr, "Not support egress.");
+ return -rte_errno;
+ }
+
+ /* Not supported */
+ if (attr->priority) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+ attr, "Not support priority.");
+ return -rte_errno;
+ }
+
+ /* Not supported */
+ if (attr->group) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+ attr, "Not support group.");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+i40e_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct rte_eth_ethertype_filter *filter)
+{
+ const struct rte_flow_item *item = pattern;
+ const struct rte_flow_item_eth *eth_spec;
+ const struct rte_flow_item_eth *eth_mask;
+ enum rte_flow_item_type item_type;
+
+ for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+ if (item->last) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Not support range");
+ return -rte_errno;
+ }
+ item_type = item->type;
+ switch (item_type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ eth_spec = (const struct rte_flow_item_eth *)item->spec;
+ eth_mask = (const struct rte_flow_item_eth *)item->mask;
+ /* Get the MAC info. */
+ if (!eth_spec || !eth_mask) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "NULL ETH spec/mask");
+ return -rte_errno;
+ }
+
+ /* Mask bits of source MAC address must be full of 0.
+ * Mask bits of destination MAC address must be full
+ * of 1 or full of 0.
+ */
+ if (!is_zero_ether_addr(ð_mask->src) ||
+ (!is_zero_ether_addr(ð_mask->dst) &&
+ !is_broadcast_ether_addr(ð_mask->dst))) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid MAC_addr mask");
+ return -rte_errno;
+ }
+
+ if ((eth_mask->type & UINT16_MAX) != UINT16_MAX) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Invalid ethertype mask");
+ return -rte_errno;
+ }
+
+ /* If mask bits of destination MAC address
+ * are full of 1, set RTE_ETHTYPE_FLAGS_MAC.
+ */
+ if (is_broadcast_ether_addr(ð_mask->dst)) {
+ filter->mac_addr = eth_spec->dst;
+ filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
+ } else {
+ filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
+ }
+ filter->ether_type = rte_be_to_cpu_16(eth_spec->type);
+
+ if (filter->ether_type == ETHER_TYPE_IPv4 ||
+ filter->ether_type == ETHER_TYPE_IPv6) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "Unsupported ether_type in"
+ " control packet filter.");
+ return -rte_errno;
+ }
+ if (filter->ether_type == ETHER_TYPE_VLAN)
+ PMD_DRV_LOG(WARNING, "filter vlan ether_type in"
+ " first tag is not supported.");
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+i40e_parse_ethertype_act(struct rte_eth_dev *dev,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error,
+ struct rte_eth_ethertype_filter *filter)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ const struct rte_flow_action *act;
+ const struct rte_flow_action_queue *act_q;
+ uint32_t index = 0;
+
+ /* Check if the first non-void action is QUEUE or DROP. */
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
+ act->type != RTE_FLOW_ACTION_TYPE_DROP) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+ act_q = (const struct rte_flow_action_queue *)act->conf;
+ filter->queue = act_q->index;
+ if (filter->queue >= pf->dev_data->nb_rx_queues) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid queue ID for"
+ " ethertype_filter.");
+ return -rte_errno;
+ }
+ } else {
+ filter->flags |= RTE_ETHTYPE_FLAGS_DROP;
+ }
+
+ /* Check if the next non-void item is END */
+ index++;
+ NEXT_ITEM_OF_ACTION(act, actions, index);
+ if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Not supported action.");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+i40e_flow_validate(struct rte_eth_dev *dev,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+{
+ struct rte_flow_item *items; /* internal pattern w/o VOID items */
+ parse_filter_t parse_filter;
+ uint32_t item_num = 0; /* non-void item number of pattern*/
+ uint32_t i = 0;
+ int ret;
+
+ if (!pattern) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+ NULL, "NULL pattern.");
+ return -rte_errno;
+ }
+
+ if (!actions) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+ NULL, "NULL action.");
+ return -rte_errno;
+ }
+
+ memset(&cons_filter, 0, sizeof(cons_filter));
+
+ /* Get the non-void item number of pattern */
+ while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
+ if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
+ item_num++;
+ i++;
+ }
+ item_num++;
+
+ items = rte_zmalloc("i40e_pattern",
+ item_num * sizeof(struct rte_flow_item), 0);
+ if (!items) {
+ rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+ NULL, "No memory for PMD internal items.");
+ return -ENOMEM;
+ }
+
+ i40e_pattern_skip_void_item(items, pattern);
+
+ /* Find if there's matched parse filter function */
+ parse_filter = i40e_find_parse_filter_func(items);
+ if (!parse_filter) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ pattern, "Unsupported pattern");
+ return -rte_errno;
+ }
+
+ ret = parse_filter(dev, attr, items, actions, error, &cons_filter);
+
+ rte_free(items);
+
+ return ret;
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 06/17] net/i40e: restore flow director filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Add support of restoring flow director filter.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 1 +
drivers/net/i40e/i40e_ethdev.h | 1 +
drivers/net/i40e/i40e_fdir.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67e1b37..153322a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10135,4 +10135,5 @@ i40e_filter_restore(struct i40e_pf *pf)
{
i40e_ethertype_filter_restore(pf);
i40e_tunnel_filter_restore(pf);
+ i40e_fdir_filter_restore(pf);
}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index b79fbd6..92f6f55 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -670,6 +670,7 @@ int i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
int i40e_select_filter_input_set(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf,
enum rte_filter_type filter);
+void i40e_fdir_filter_restore(struct i40e_pf *pf);
int i40e_hash_filter_inset_select(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf);
int i40e_fdir_filter_inset_select(struct i40e_pf *pf,
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 4a29b37..f89dbc9 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1586,3 +1586,34 @@ i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
}
return ret;
}
+
+/* Restore flow director filter */
+void
+i40e_fdir_filter_restore(struct i40e_pf *pf)
+{
+ struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi);
+ struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list;
+ struct i40e_fdir_filter *f;
+#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ uint32_t fdstat;
+ uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */
+ uint32_t best_cnt; /**< Number of filters in best effort spaces. */
+#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
+
+ TAILQ_FOREACH(f, fdir_list, rules)
+ i40e_add_del_fdir_filter(dev, &f->fdir, TRUE);
+
+#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
+ fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
+ guarant_cnt =
+ (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
+ I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
+ best_cnt =
+ (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
+ I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
+#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
+
+ PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d, Best count: %d\n",
+ guarant_cnt, best_cnt);
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 05/17] net/i40e: restore tunnel filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Add support of restoring tunnel filter.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 189d110..67e1b37 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -475,6 +475,7 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
struct i40e_tunnel_filter *tunnel_filter);
static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
+static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
static void i40e_filter_restore(struct i40e_pf *pf);
static const struct rte_pci_id pci_id_i40e_map[] = {
@@ -10110,8 +10111,28 @@ i40e_ethertype_filter_restore(struct i40e_pf *pf)
stats.mac_etype_free, stats.etype_free);
}
+/* Restore tunnel filter */
+static void
+i40e_tunnel_filter_restore(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_vsi *vsi = pf->main_vsi;
+ struct i40e_tunnel_filter_list
+ *tunnel_list = &pf->tunnel.tunnel_list;
+ struct i40e_tunnel_filter *f;
+ struct i40e_aqc_add_remove_cloud_filters_element_data cld_filter;
+
+ TAILQ_FOREACH(f, tunnel_list, rules) {
+ memset(&cld_filter, 0, sizeof(cld_filter));
+ rte_memcpy(&cld_filter, &f->input, sizeof(f->input));
+ cld_filter.queue_number = f->queue;
+ i40e_aq_add_cloud_filters(hw, vsi->seid, &cld_filter, 1);
+ }
+}
+
static void
i40e_filter_restore(struct i40e_pf *pf)
{
i40e_ethertype_filter_restore(pf);
+ i40e_tunnel_filter_restore(pf);
}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 04/17] net/i40e: restore ethertype filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Add support of restoring ethertype filter in case filter
dropped accidentally, as all filters need to be added and
removed by user obviously for generic filter API.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 44 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fb7d794..189d110 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -474,6 +474,9 @@ static int i40e_tunnel_filter_convert(
static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
struct i40e_tunnel_filter *tunnel_filter);
+static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
+static void i40e_filter_restore(struct i40e_pf *pf);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -1955,6 +1958,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
/* enable uio intr after callback register */
rte_intr_enable(intr_handle);
+ i40e_filter_restore(pf);
+
return I40E_SUCCESS;
err_up:
@@ -10071,3 +10076,42 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
return ret;
}
+
+/* Restore ethertype filter */
+static void
+i40e_ethertype_filter_restore(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_filter_list
+ *ethertype_list = &pf->ethertype.ethertype_list;
+ struct i40e_ethertype_filter *f;
+ struct i40e_control_filter_stats stats;
+ uint16_t flags;
+
+ TAILQ_FOREACH(f, ethertype_list, rules) {
+ flags = 0;
+ if (!(f->flags & RTE_ETHTYPE_FLAGS_MAC))
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
+ if (f->flags & RTE_ETHTYPE_FLAGS_DROP)
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
+ flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
+
+ memset(&stats, 0, sizeof(stats));
+ i40e_aq_add_rem_control_packet_filter(hw,
+ f->input.mac_addr.addr_bytes,
+ f->input.ether_type,
+ flags, pf->main_vsi->seid,
+ f->queue, 1, &stats, NULL);
+ }
+ PMD_DRV_LOG(INFO, "Ethertype filter:"
+ " mac_etype_used = %u, etype_used = %u,"
+ " mac_etype_free = %u, etype_free = %u\n",
+ stats.mac_etype_used, stats.etype_used,
+ stats.mac_etype_free, stats.etype_free);
+}
+
+static void
+i40e_filter_restore(struct i40e_pf *pf)
+{
+ i40e_ethertype_filter_restore(pf);
+}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 03/17] net/i40e: store flow director filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Currently there's no flow director filter stored in SW. This
patch stores flow director filters in SW with cuckoo hash,
also adds protection if a flow director filter has been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 48 +++++++++++++++++++
drivers/net/i40e/i40e_ethdev.h | 14 ++++++
drivers/net/i40e/i40e_fdir.c | 105 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 167 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2bdb4d6..fb7d794 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -953,6 +953,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
PMD_INIT_FUNC_TRACE();
@@ -972,6 +973,14 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
.hash_func = rte_hash_crc,
};
+ char fdir_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters fdir_hash_params = {
+ .name = fdir_hash_name,
+ .entries = I40E_MAX_FDIR_FILTER_NUM,
+ .key_len = sizeof(struct rte_eth_fdir_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1253,8 +1262,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_tunnel_hash_map_alloc;
}
+ /* Initialize flow director filter rule list and hash */
+ TAILQ_INIT(&fdir_info->fdir_list);
+ snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
+ "fdir_%s", dev->data->name);
+ fdir_info->hash_table = rte_hash_create(&fdir_hash_params);
+ if (!fdir_info->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
+ ret = -EINVAL;
+ goto err_fdir_hash_table_create;
+ }
+ fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
+ sizeof(struct i40e_fdir_filter *) *
+ I40E_MAX_FDIR_FILTER_NUM,
+ 0);
+ if (!fdir_info->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for fdir hash map!");
+ ret = -ENOMEM;
+ goto err_fdir_hash_map_alloc;
+ }
+
return 0;
+err_fdir_hash_map_alloc:
+ rte_hash_free(fdir_info->hash_table);
+err_fdir_hash_table_create:
+ rte_free(tunnel_rule->hash_map);
err_tunnel_hash_map_alloc:
rte_hash_free(tunnel_rule->hash_table);
err_tunnel_hash_table_create:
@@ -1291,10 +1325,12 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
struct i40e_filter_control_settings settings;
struct i40e_ethertype_filter *p_ethertype;
struct i40e_tunnel_filter *p_tunnel;
+ struct i40e_fdir_filter *p_fdir;
int ret;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule;
struct i40e_tunnel_rule *tunnel_rule;
+ struct i40e_fdir_info *fdir_info;
PMD_INIT_FUNC_TRACE();
@@ -1306,6 +1342,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
pci_dev = dev->pci_dev;
ethertype_rule = &pf->ethertype;
tunnel_rule = &pf->tunnel;
+ fdir_info = &pf->fdir;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
@@ -1333,6 +1370,17 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
rte_free(p_tunnel);
}
+ /* Remove all flow director rules and hash */
+ if (fdir_info->hash_map)
+ rte_free(fdir_info->hash_map);
+ if (fdir_info->hash_table)
+ rte_hash_free(fdir_info->hash_table);
+
+ while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))) {
+ TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+ rte_free(p_fdir);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 83f3594..b79fbd6 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -377,6 +377,14 @@ struct i40e_fdir_flex_mask {
};
#define I40E_FILTER_PCTYPE_MAX 64
+#define I40E_MAX_FDIR_FILTER_NUM (1024 * 8)
+
+struct i40e_fdir_filter {
+ TAILQ_ENTRY(i40e_fdir_filter) rules;
+ struct rte_eth_fdir_filter fdir;
+};
+
+TAILQ_HEAD(i40e_fdir_filter_list, i40e_fdir_filter);
/*
* A structure used to define fields of a FDIR related info.
*/
@@ -395,6 +403,10 @@ struct i40e_fdir_info {
*/
struct i40e_fdir_flex_pit flex_set[I40E_MAX_FLXPLD_LAYER * I40E_MAX_FLXPLD_FIED];
struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX];
+
+ struct i40e_fdir_filter_list fdir_list;
+ struct i40e_fdir_filter **hash_map;
+ struct rte_hash *hash_table;
};
/* Ethertype filter number HW supports */
@@ -674,6 +686,8 @@ i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
const struct i40e_ethertype_filter_input *input);
int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
struct i40e_ethertype_filter_input *input);
+int i40e_sw_fdir_filter_del(struct i40e_pf *pf,
+ struct rte_eth_fdir_input *input);
struct i40e_tunnel_filter *
i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
const struct i40e_tunnel_filter_input *input);
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 335bf15..4a29b37 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -121,6 +121,14 @@ static int i40e_fdir_filter_programming(struct i40e_pf *pf,
bool add);
static int i40e_fdir_flush(struct rte_eth_dev *dev);
+static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+ struct i40e_fdir_filter *filter);
+static struct i40e_fdir_filter *
+i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
+ const struct rte_eth_fdir_input *input);
+static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf,
+ struct i40e_fdir_filter *filter);
+
static int
i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
{
@@ -1017,6 +1025,74 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq)
return ret;
}
+static int
+i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+ struct i40e_fdir_filter *filter)
+{
+ rte_memcpy(&filter->fdir, input, sizeof(struct rte_eth_fdir_filter));
+ return 0;
+}
+
+/* Check if there exists the flow director filter */
+static struct i40e_fdir_filter *
+i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
+ const struct rte_eth_fdir_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(fdir_info->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return fdir_info->hash_map[ret];
+}
+
+/* Add a flow director filter into the SW list */
+static int
+i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)
+{
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ int ret;
+
+ ret = rte_hash_add_key(fdir_info->hash_table,
+ &filter->fdir.input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert fdir filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ fdir_info->hash_map[ret] = filter;
+
+ TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules);
+
+ return 0;
+}
+
+/* Delete a flow director filter from the SW list */
+int
+i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
+{
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *filter;
+ int ret;
+
+ ret = rte_hash_del_key(fdir_info->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete fdir filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ filter = fdir_info->hash_map[ret];
+ fdir_info->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules);
+ rte_free(filter);
+
+ return 0;
+}
+
/*
* i40e_add_del_fdir_filter - add or remove a flow director filter.
* @pf: board private structure
@@ -1032,6 +1108,9 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
enum i40e_filter_pctype pctype;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *fdir_filter, *node;
+ struct i40e_fdir_filter check_filter; /* Check if the filter exists */
int ret = 0;
if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
@@ -1054,6 +1133,22 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
return -EINVAL;
}
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_fdir_filter_convert(filter, &check_filter);
+ node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR,
+ "Conflict with existing flow director rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR,
+ "There's no corresponding flow firector filter!");
+ return -EINVAL;
+ }
+
memset(pkt, 0, I40E_FDIR_PKT_LEN);
ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
@@ -1077,6 +1172,16 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
pctype);
return ret;
}
+
+ if (add) {
+ fdir_filter = rte_zmalloc("fdir_filter",
+ sizeof(*fdir_filter), 0);
+ rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter));
+ ret = i40e_sw_fdir_filter_insert(pf, fdir_filter);
+ } else {
+ ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
+ }
+
return ret;
}
--
2.5.5
^ permalink raw reply related
* [PATCH v5 02/17] net/i40e: store tunnel filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Currently there's no tunnel filter stored in SW.
This patch stores tunnel filter in SW with cuckoo
hash, also adds protection if a tunnel filter has
been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 169 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 32 ++++++++
2 files changed, 198 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e43b4d9..2bdb4d6 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -468,6 +468,12 @@ static int i40e_ethertype_filter_convert(
static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
struct i40e_ethertype_filter *filter);
+static int i40e_tunnel_filter_convert(
+ struct i40e_aqc_add_remove_cloud_filters_element_data *cld_filter,
+ struct i40e_tunnel_filter *tunnel_filter);
+static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *tunnel_filter);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -946,6 +952,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
uint32_t len;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
PMD_INIT_FUNC_TRACE();
@@ -957,6 +964,14 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
.hash_func = rte_hash_crc,
};
+ char tunnel_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters tunnel_hash_params = {
+ .name = tunnel_hash_name,
+ .entries = I40E_MAX_TUNNEL_FILTER_NUM,
+ .key_len = sizeof(struct i40e_tunnel_filter_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1217,8 +1232,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
goto err_ethertype_hash_map_alloc;
}
+ /* Initialize tunnel filter rule list and hash */
+ TAILQ_INIT(&tunnel_rule->tunnel_list);
+ snprintf(tunnel_hash_name, RTE_HASH_NAMESIZE,
+ "tunnel_%s", dev->data->name);
+ tunnel_rule->hash_table = rte_hash_create(&tunnel_hash_params);
+ if (!tunnel_rule->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create tunnel hash table!");
+ ret = -EINVAL;
+ goto err_tunnel_hash_table_create;
+ }
+ tunnel_rule->hash_map = rte_zmalloc("i40e_tunnel_hash_map",
+ sizeof(struct i40e_tunnel_filter *) *
+ I40E_MAX_TUNNEL_FILTER_NUM,
+ 0);
+ if (!tunnel_rule->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for tunnel hash map!");
+ ret = -ENOMEM;
+ goto err_tunnel_hash_map_alloc;
+ }
+
return 0;
+err_tunnel_hash_map_alloc:
+ rte_hash_free(tunnel_rule->hash_table);
+err_tunnel_hash_table_create:
+ rte_free(ethertype_rule->hash_map);
err_ethertype_hash_map_alloc:
rte_hash_free(ethertype_rule->hash_table);
err_ethertype_hash_table_create:
@@ -1250,9 +1290,11 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
struct i40e_hw *hw;
struct i40e_filter_control_settings settings;
struct i40e_ethertype_filter *p_ethertype;
+ struct i40e_tunnel_filter *p_tunnel;
int ret;
uint8_t aq_fail = 0;
struct i40e_ethertype_rule *ethertype_rule;
+ struct i40e_tunnel_rule *tunnel_rule;
PMD_INIT_FUNC_TRACE();
@@ -1263,6 +1305,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
pci_dev = dev->pci_dev;
ethertype_rule = &pf->ethertype;
+ tunnel_rule = &pf->tunnel;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
@@ -1279,6 +1322,17 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
rte_free(p_ethertype);
}
+ /* Remove all tunnel director rules and hash */
+ if (tunnel_rule->hash_map)
+ rte_free(tunnel_rule->hash_map);
+ if (tunnel_rule->hash_table)
+ rte_hash_free(tunnel_rule->hash_table);
+
+ while ((p_tunnel = TAILQ_FIRST(&tunnel_rule->tunnel_list))) {
+ TAILQ_REMOVE(&tunnel_rule->tunnel_list, p_tunnel, rules);
+ rte_free(p_tunnel);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
@@ -6478,6 +6532,85 @@ i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag)
return 0;
}
+/* Convert tunnel filter structure */
+static int
+i40e_tunnel_filter_convert(struct i40e_aqc_add_remove_cloud_filters_element_data
+ *cld_filter,
+ struct i40e_tunnel_filter *tunnel_filter)
+{
+ ether_addr_copy((struct ether_addr *)&cld_filter->outer_mac,
+ (struct ether_addr *)&tunnel_filter->input.outer_mac);
+ ether_addr_copy((struct ether_addr *)&cld_filter->inner_mac,
+ (struct ether_addr *)&tunnel_filter->input.inner_mac);
+ tunnel_filter->input.inner_vlan = cld_filter->inner_vlan;
+ tunnel_filter->input.flags = cld_filter->flags;
+ tunnel_filter->input.tenant_id = cld_filter->tenant_id;
+ tunnel_filter->queue = cld_filter->queue_number;
+
+ return 0;
+}
+
+/* Check if there exists the tunnel filter */
+struct i40e_tunnel_filter *
+i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
+ const struct i40e_tunnel_filter_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(tunnel_rule->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return tunnel_rule->hash_map[ret];
+}
+
+/* Add a tunnel filter into the SW list */
+static int
+i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
+ struct i40e_tunnel_filter *tunnel_filter)
+{
+ struct i40e_tunnel_rule *rule = &pf->tunnel;
+ int ret;
+
+ ret = rte_hash_add_key(rule->hash_table, &tunnel_filter->input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert tunnel filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ rule->hash_map[ret] = tunnel_filter;
+
+ TAILQ_INSERT_TAIL(&rule->tunnel_list, tunnel_filter, rules);
+
+ return 0;
+}
+
+/* Delete a tunnel filter from the SW list */
+int
+i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
+ struct i40e_tunnel_filter_input *input)
+{
+ struct i40e_tunnel_rule *rule = &pf->tunnel;
+ struct i40e_tunnel_filter *tunnel_filter;
+ int ret;
+
+ ret = rte_hash_del_key(rule->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete tunnel filter to hash table %d!",
+ ret);
+ return ret;
+ }
+ tunnel_filter = rule->hash_map[ret];
+ rule->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&rule->tunnel_list, tunnel_filter, rules);
+ rte_free(tunnel_filter);
+
+ return 0;
+}
+
static int
i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct rte_eth_tunnel_filter_conf *tunnel_filter,
@@ -6493,6 +6626,9 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
struct i40e_vsi *vsi = pf->main_vsi;
struct i40e_aqc_add_remove_cloud_filters_element_data *cld_filter;
struct i40e_aqc_add_remove_cloud_filters_element_data *pfilter;
+ struct i40e_tunnel_rule *tunnel_rule = &pf->tunnel;
+ struct i40e_tunnel_filter *tunnel, *node;
+ struct i40e_tunnel_filter check_filter; /* Check if filter exists */
cld_filter = rte_zmalloc("tunnel_filter",
sizeof(struct i40e_aqc_add_remove_cloud_filters_element_data),
@@ -6555,11 +6691,38 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
pfilter->tenant_id = rte_cpu_to_le_32(tunnel_filter->tenant_id);
pfilter->queue_number = rte_cpu_to_le_16(tunnel_filter->queue_id);
- if (add)
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_tunnel_filter_convert(cld_filter, &check_filter);
+ node = i40e_sw_tunnel_filter_lookup(tunnel_rule, &check_filter.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR, "Conflict with existing tunnel rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR, "There's no corresponding tunnel filter!");
+ return -EINVAL;
+ }
+
+ if (add) {
ret = i40e_aq_add_cloud_filters(hw, vsi->seid, cld_filter, 1);
- else
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to add a tunnel filter.");
+ return ret;
+ }
+ tunnel = rte_zmalloc("tunnel_filter", sizeof(*tunnel), 0);
+ rte_memcpy(tunnel, &check_filter, sizeof(check_filter));
+ ret = i40e_sw_tunnel_filter_insert(pf, tunnel);
+ } else {
ret = i40e_aq_remove_cloud_filters(hw, vsi->seid,
- cld_filter, 1);
+ cld_filter, 1);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to delete a tunnel filter.");
+ return ret;
+ }
+ ret = i40e_sw_tunnel_filter_del(pf, &node->input);
+ }
rte_free(cld_filter);
return ret;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 3fb20ba..83f3594 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -421,6 +421,32 @@ struct i40e_ethertype_rule {
struct rte_hash *hash_table;
};
+/* Tunnel filter number HW supports */
+#define I40E_MAX_TUNNEL_FILTER_NUM 400
+
+/* Tunnel filter struct */
+struct i40e_tunnel_filter_input {
+ uint8_t outer_mac[6]; /* Outer mac address to match */
+ uint8_t inner_mac[6]; /* Inner mac address to match */
+ uint16_t inner_vlan; /* Inner vlan address to match */
+ uint16_t flags; /* Filter type flag */
+ uint32_t tenant_id; /* Tenant id to match */
+};
+
+struct i40e_tunnel_filter {
+ TAILQ_ENTRY(i40e_tunnel_filter) rules;
+ struct i40e_tunnel_filter_input input;
+ uint16_t queue; /* Queue assigned to when match */
+};
+
+TAILQ_HEAD(i40e_tunnel_filter_list, i40e_tunnel_filter);
+
+struct i40e_tunnel_rule {
+ struct i40e_tunnel_filter_list tunnel_list;
+ struct i40e_tunnel_filter **hash_map;
+ struct rte_hash *hash_table;
+};
+
#define I40E_MIRROR_MAX_ENTRIES_PER_RULE 64
#define I40E_MAX_MIRROR_RULES 64
/*
@@ -492,6 +518,7 @@ struct i40e_pf {
struct i40e_fdir_info fdir; /* flow director info */
struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
+ struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
struct i40e_fc_conf fc_conf; /* Flow control conf */
struct i40e_mirror_rule_list mirror_list;
uint16_t nb_mirror_rule; /* The number of mirror rules */
@@ -647,6 +674,11 @@ i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
const struct i40e_ethertype_filter_input *input);
int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
struct i40e_ethertype_filter_input *input);
+struct i40e_tunnel_filter *
+i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
+ const struct i40e_tunnel_filter_input *input);
+int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
+ struct i40e_tunnel_filter_input *input);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
--
2.5.5
^ permalink raw reply related
* [PATCH v5 01/17] net/i40e: store ethertype filter
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483500187-124740-1-git-send-email-beilei.xing@intel.com>
Currently there's no ethertype filter stored in SW.
This patch stores ethertype filter with cuckoo hash
in SW, also adds protection if an ethertype filter
has been added.
Signed-off-by: Beilei Xing <beilei.xing@intel.com>
---
drivers/net/i40e/Makefile | 1 +
drivers/net/i40e/i40e_ethdev.c | 166 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev.h | 31 ++++++++
3 files changed, 197 insertions(+), 1 deletion(-)
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 66997b6..11175c4 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -117,5 +117,6 @@ DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_net
DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_kvargs
+DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_hash
include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8033c35..e43b4d9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -51,6 +51,7 @@
#include <rte_dev.h>
#include <rte_eth_ctrl.h>
#include <rte_tailq.h>
+#include <rte_hash_crc.h>
#include "i40e_logs.h"
#include "base/i40e_prototype.h"
@@ -461,6 +462,12 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
+static int i40e_ethertype_filter_convert(
+ const struct rte_eth_ethertype_filter *input,
+ struct i40e_ethertype_filter *filter);
+static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter);
+
static const struct rte_pci_id pci_id_i40e_map[] = {
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
@@ -938,9 +945,18 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
int ret;
uint32_t len;
uint8_t aq_fail = 0;
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
PMD_INIT_FUNC_TRACE();
+ char ethertype_hash_name[RTE_HASH_NAMESIZE];
+ struct rte_hash_parameters ethertype_hash_params = {
+ .name = ethertype_hash_name,
+ .entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
+ .key_len = sizeof(struct i40e_ethertype_filter_input),
+ .hash_func = rte_hash_crc,
+ };
+
dev->dev_ops = &i40e_eth_dev_ops;
dev->rx_pkt_burst = i40e_recv_pkts;
dev->tx_pkt_burst = i40e_xmit_pkts;
@@ -1180,8 +1196,33 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
pf->flags &= ~I40E_FLAG_DCB;
}
+ /* Initialize ethertype filter rule list and hash */
+ TAILQ_INIT(ðertype_rule->ethertype_list);
+ snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
+ "ethertype_%s", dev->data->name);
+ ethertype_rule->hash_table = rte_hash_create(ðertype_hash_params);
+ if (!ethertype_rule->hash_table) {
+ PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
+ ret = -EINVAL;
+ goto err_ethertype_hash_table_create;
+ }
+ ethertype_rule->hash_map = rte_zmalloc("i40e_ethertype_hash_map",
+ sizeof(struct i40e_ethertype_filter *) *
+ I40E_MAX_ETHERTYPE_FILTER_NUM,
+ 0);
+ if (!ethertype_rule->hash_map) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate memory for ethertype hash map!");
+ ret = -ENOMEM;
+ goto err_ethertype_hash_map_alloc;
+ }
+
return 0;
+err_ethertype_hash_map_alloc:
+ rte_hash_free(ethertype_rule->hash_table);
+err_ethertype_hash_table_create:
+ rte_free(dev->data->mac_addrs);
err_mac_alloc:
i40e_vsi_release(pf->main_vsi);
err_setup_pf_switch:
@@ -1204,23 +1245,40 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
static int
eth_i40e_dev_uninit(struct rte_eth_dev *dev)
{
+ struct i40e_pf *pf;
struct rte_pci_device *pci_dev;
struct i40e_hw *hw;
struct i40e_filter_control_settings settings;
+ struct i40e_ethertype_filter *p_ethertype;
int ret;
uint8_t aq_fail = 0;
+ struct i40e_ethertype_rule *ethertype_rule;
PMD_INIT_FUNC_TRACE();
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
+ pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
pci_dev = dev->pci_dev;
+ ethertype_rule = &pf->ethertype;
if (hw->adapter_stopped == 0)
i40e_dev_close(dev);
+ /* Remove all ethertype director rules and hash */
+ if (ethertype_rule->hash_map)
+ rte_free(ethertype_rule->hash_map);
+ if (ethertype_rule->hash_table)
+ rte_hash_free(ethertype_rule->hash_table);
+
+ while ((p_ethertype = TAILQ_FIRST(ðertype_rule->ethertype_list))) {
+ TAILQ_REMOVE(ðertype_rule->ethertype_list,
+ p_ethertype, rules);
+ rte_free(p_ethertype);
+ }
+
dev->dev_ops = NULL;
dev->rx_pkt_burst = NULL;
dev->tx_pkt_burst = NULL;
@@ -7955,6 +8013,82 @@ i40e_hash_filter_ctrl(struct rte_eth_dev *dev,
return ret;
}
+/* Convert ethertype filter structure */
+static int
+i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
+ struct i40e_ethertype_filter *filter)
+{
+ rte_memcpy(&filter->input.mac_addr, &input->mac_addr, ETHER_ADDR_LEN);
+ filter->input.ether_type = input->ether_type;
+ filter->flags = input->flags;
+ filter->queue = input->queue;
+
+ return 0;
+}
+
+/* Check if there exists the ehtertype filter */
+struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
+ const struct i40e_ethertype_filter_input *input)
+{
+ int ret;
+
+ ret = rte_hash_lookup(ethertype_rule->hash_table, (const void *)input);
+ if (ret < 0)
+ return NULL;
+
+ return ethertype_rule->hash_map[ret];
+}
+
+/* Add ethertype filter in SW list */
+static int
+i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
+ struct i40e_ethertype_filter *filter)
+{
+ struct i40e_ethertype_rule *rule = &pf->ethertype;
+ int ret;
+
+ ret = rte_hash_add_key(rule->hash_table, &filter->input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to insert ethertype filter"
+ " to hash table %d!",
+ ret);
+ return ret;
+ }
+ rule->hash_map[ret] = filter;
+
+ TAILQ_INSERT_TAIL(&rule->ethertype_list, filter, rules);
+
+ return 0;
+}
+
+/* Delete ethertype filter in SW list */
+int
+i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+ struct i40e_ethertype_filter_input *input)
+{
+ struct i40e_ethertype_rule *rule = &pf->ethertype;
+ struct i40e_ethertype_filter *filter;
+ int ret;
+
+ ret = rte_hash_del_key(rule->hash_table, input);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR,
+ "Failed to delete ethertype filter"
+ " to hash table %d!",
+ ret);
+ return ret;
+ }
+ filter = rule->hash_map[ret];
+ rule->hash_map[ret] = NULL;
+
+ TAILQ_REMOVE(&rule->ethertype_list, filter, rules);
+ rte_free(filter);
+
+ return 0;
+}
+
/*
* Configure ethertype filter, which can director packet by filtering
* with mac address and ether_type or only ether_type
@@ -7965,6 +8099,9 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
bool add)
{
struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
+ struct i40e_ethertype_filter *ethertype_filter, *node;
+ struct i40e_ethertype_filter check_filter;
struct i40e_control_filter_stats stats;
uint16_t flags = 0;
int ret;
@@ -7983,6 +8120,21 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is"
" not supported.");
+ /* Check if there is the filter in SW list */
+ memset(&check_filter, 0, sizeof(check_filter));
+ i40e_ethertype_filter_convert(filter, &check_filter);
+ node = i40e_sw_ethertype_filter_lookup(ethertype_rule,
+ &check_filter.input);
+ if (add && node) {
+ PMD_DRV_LOG(ERR, "Conflict with existing ethertype rules!");
+ return -EINVAL;
+ }
+
+ if (!add && !node) {
+ PMD_DRV_LOG(ERR, "There's no corresponding ethertype filter!");
+ return -EINVAL;
+ }
+
if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
@@ -8003,7 +8155,19 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
stats.mac_etype_free, stats.etype_free);
if (ret < 0)
return -ENOSYS;
- return 0;
+
+ /* Add or delete a filter in SW list */
+ if (add) {
+ ethertype_filter = rte_zmalloc("ethertype_filter",
+ sizeof(*ethertype_filter), 0);
+ rte_memcpy(ethertype_filter, &check_filter,
+ sizeof(check_filter));
+ ret = i40e_sw_ethertype_filter_insert(pf, ethertype_filter);
+ } else {
+ ret = i40e_sw_ethertype_filter_del(pf, &node->input);
+ }
+
+ return ret;
}
/*
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 298cef4..3fb20ba 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -37,6 +37,7 @@
#include <rte_eth_ctrl.h>
#include <rte_time.h>
#include <rte_kvargs.h>
+#include <rte_hash.h>
#define I40E_VLAN_TAG_SIZE 4
@@ -396,6 +397,30 @@ struct i40e_fdir_info {
struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX];
};
+/* Ethertype filter number HW supports */
+#define I40E_MAX_ETHERTYPE_FILTER_NUM 768
+
+/* Ethertype filter struct */
+struct i40e_ethertype_filter_input {
+ struct ether_addr mac_addr; /* Mac address to match */
+ uint16_t ether_type; /* Ether type to match */
+};
+
+struct i40e_ethertype_filter {
+ TAILQ_ENTRY(i40e_ethertype_filter) rules;
+ struct i40e_ethertype_filter_input input;
+ uint16_t flags; /* Flags from RTE_ETHTYPE_FLAGS_* */
+ uint16_t queue; /* Queue assigned to when match */
+};
+
+TAILQ_HEAD(i40e_ethertype_filter_list, i40e_ethertype_filter);
+
+struct i40e_ethertype_rule {
+ struct i40e_ethertype_filter_list ethertype_list;
+ struct i40e_ethertype_filter **hash_map;
+ struct rte_hash *hash_table;
+};
+
#define I40E_MIRROR_MAX_ENTRIES_PER_RULE 64
#define I40E_MAX_MIRROR_RULES 64
/*
@@ -466,6 +491,7 @@ struct i40e_pf {
struct i40e_vmdq_info *vmdq;
struct i40e_fdir_info fdir; /* flow director info */
+ struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
struct i40e_fc_conf fc_conf; /* Flow control conf */
struct i40e_mirror_rule_list mirror_list;
uint16_t nb_mirror_rule; /* The number of mirror rules */
@@ -616,6 +642,11 @@ void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_rxq_info *qinfo);
void i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_txq_info *qinfo);
+struct i40e_ethertype_filter *
+i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
+ const struct i40e_ethertype_filter_input *input);
+int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
+ struct i40e_ethertype_filter_input *input);
/* I40E_DEV_PRIVATE_TO */
#define I40E_DEV_PRIVATE_TO_PF(adapter) \
--
2.5.5
^ permalink raw reply related
* [PATCH v5 00/17] net/i40e: consistent filter API
From: Beilei Xing @ 2017-01-04 3:22 UTC (permalink / raw)
To: jingjing.wu, helin.zhang; +Cc: dev
In-Reply-To: <1483068352-32272-1-git-send-email-beilei.xing@intel.com>
The patch set depends on Adrien's Generic flow API(rte_flow).
The patches mainly finish following functions:
1) Store and restore all kinds of filters.
2) Parse all kinds of filters.
3) Add flow validate function.
4) Add flow create function.
5) Add flow destroy function.
6) Add flow flush function.
v5 changes:
Change some local variable name.
Add removing i40e_flow_list during device unint.
Fix compile error when gcc compile option isn't '-O0'.
v4 changes:
Change I40E_TCI_MASK with 0xFFFF to align with testpmd.
Modidy the stats show when restoring filters.
v3 changes:
Set the related cause pointer to a non-NULL value when error happens.
Change return value when error happens.
Modify filter_del parameter with key.
Malloc filter after checking when delete a filter.
Delete meaningless initialization.
Add return value when there's error.
Change global variable definition.
Modify some function declaration.
v2 changes:
Add i40e_flow.c, all flow ops are implemented in the file.
Change the whole implementation of all parse flow functions.
Update error info for all flow ops.
Add flow_list to store flows created.
Beilei Xing (17):
net/i40e: store ethertype filter
net/i40e: store tunnel filter
net/i40e: store flow director filter
net/i40e: restore ethertype filter
net/i40e: restore tunnel filter
net/i40e: restore flow director filter
net/i40e: add flow validate function
net/i40e: parse flow director filter
net/i40e: parse tunnel filter
net/i40e: add flow create function
net/i40e: add flow destroy function
net/i40e: destroy ethertype filter
net/i40e: destroy tunnel filter
net/i40e: destroy flow directory filter
net/i40e: add flow flush function
net/i40e: flush ethertype filters
net/i40e: flush tunnel filters
drivers/net/i40e/Makefile | 2 +
drivers/net/i40e/i40e_ethdev.c | 526 ++++++++++--
drivers/net/i40e/i40e_ethdev.h | 173 ++++
drivers/net/i40e/i40e_fdir.c | 140 +++-
drivers/net/i40e/i40e_flow.c | 1772 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 2547 insertions(+), 66 deletions(-)
create mode 100644 drivers/net/i40e/i40e_flow.c
--
2.5.5
^ permalink raw reply
* Re: [PATCH v3 2/4] net/e1000: add firmware version get
From: Yang, Qiming @ 2017-01-04 3:14 UTC (permalink / raw)
To: Yigit, Ferruh, dev@dpdk.org, thomas.monjalon@6wind.com; +Cc: Horton, Remy
In-Reply-To: <c562f86a-33a5-ad3a-c8d3-12c6981e7050@intel.com>
See the reply below.
-----Original Message-----
From: Yigit, Ferruh
Sent: Tuesday, January 3, 2017 11:03 PM
To: Yang, Qiming <qiming.yang@intel.com>; dev@dpdk.org; thomas.monjalon@6wind.com
Cc: Horton, Remy <remy.horton@intel.com>
Subject: Re: [PATCH v3 2/4] net/e1000: add firmware version get
On 12/27/2016 12:30 PM, Qiming Yang wrote:
> This patch adds a new function eth_igb_fw_version_get.
>
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> ---
> v3 changes:
> * use eth_igb_fw_version_get(struct rte_eth_dev *dev, u32 *fw_major,
> u32 *fw_minor, u32 *fw_minor, u32 *fw_patch, u32 *etrack_id) instead
> of eth_igb_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
> int fw_length). Add statusment in /doc/guides/nics/features/igb.ini.
> ---
> ---
> doc/guides/nics/features/igb.ini | 1 +
> drivers/net/e1000/igb_ethdev.c | 43 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 44 insertions(+)
>
> diff --git a/doc/guides/nics/features/igb.ini
> b/doc/guides/nics/features/igb.ini
> index 9fafe72..ffd87ba 100644
> --- a/doc/guides/nics/features/igb.ini
> +++ b/doc/guides/nics/features/igb.ini
> @@ -39,6 +39,7 @@ EEPROM dump = Y
> Registers dump = Y
> BSD nic_uio = Y
> Linux UIO = Y
> +FW version = Y
Please keep same location with default.ini file. Why you are putting this just into middle of the uio and vfio?
Qiming: It's a clerical error, I want to add this line at the end of this file.
> Linux VFIO = Y
> x86-32 = Y
> x86-64 = Y
> diff --git a/drivers/net/e1000/igb_ethdev.c
> b/drivers/net/e1000/igb_ethdev.c index 4a15447..25344b7 100644
> --- a/drivers/net/e1000/igb_ethdev.c
> +++ b/drivers/net/e1000/igb_ethdev.c
> @@ -120,6 +120,8 @@ static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
> unsigned limit);
> static void eth_igb_stats_reset(struct rte_eth_dev *dev); static
> void eth_igb_xstats_reset(struct rte_eth_dev *dev);
> +static void eth_igb_fw_version_get(struct rte_eth_dev *dev, u32 *fw_major,
> + u32 *fw_minor, u32 *fw_patch, u32 *etrack_id);
I think you can use a struct as parameter here. But beware, that struct should NOT be a public struct.
Qiming: I think only add a private struct for igb is unnecessary. Keep the arguments consistent with rte_eth_dev_fw_info_get is better.
What do you think?
> static void eth_igb_infos_get(struct rte_eth_dev *dev,
> struct rte_eth_dev_info *dev_info); static const uint32_t
> *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev); @@ -389,6
> +391,7 @@ static const struct eth_dev_ops eth_igb_ops = {
> .xstats_get_names = eth_igb_xstats_get_names,
> .stats_reset = eth_igb_stats_reset,
> .xstats_reset = eth_igb_xstats_reset,
> + .fw_version_get = eth_igb_fw_version_get,
> .dev_infos_get = eth_igb_infos_get,
> .dev_supported_ptypes_get = eth_igb_supported_ptypes_get,
> .mtu_set = eth_igb_mtu_set,
> @@ -1981,6 +1984,46 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
> }
>
<...>
^ permalink raw reply
* [PATCH] lib/librte_vhost: fix memory leak
From: Yong Wang @ 2017-01-04 3:57 UTC (permalink / raw)
To: yuanhan.liu; +Cc: dev, Yong Wang
In function vhost_new_device(), current code dose not free 'dev'
in "i == MAX_VHOST_DEVICE" condition statements. It will lead to a
memory leak.
Signed-off-by: Yong Wang <wang.yong19@zte.com.cn>
---
lib/librte_vhost/vhost.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 31825b8..e415093 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -250,6 +250,7 @@ struct virtio_net *
if (i == MAX_VHOST_DEVICE) {
RTE_LOG(ERR, VHOST_CONFIG,
"Failed to find a free slot for new device.\n");
+ rte_free(dev);
return -1;
}
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v3 3/4] net/ixgbe: add firmware version get
From: Yang, Qiming @ 2017-01-04 2:44 UTC (permalink / raw)
To: Yigit, Ferruh, dev@dpdk.org, thomas.monjalon@6wind.com; +Cc: Horton, Remy
In-Reply-To: <9c401d90-0264-8fc8-3733-abb59bfd277e@intel.com>
You can see the kernel version ethtool, use command 'ethtool -i <ixgbe NIC name>'
driver: ixgbe
version: 4.2.1-k
firmware-version: 0x61bf0001
Ixgbe's FW version do not have the major and minor number, and the original purpose of this function is get FW version, so I think it's enough.
-----Original Message-----
From: Yigit, Ferruh
Sent: Tuesday, January 3, 2017 11:04 PM
To: Yang, Qiming <qiming.yang@intel.com>; dev@dpdk.org; thomas.monjalon@6wind.com
Cc: Horton, Remy <remy.horton@intel.com>
Subject: Re: [PATCH v3 3/4] net/ixgbe: add firmware version get
On 12/27/2016 12:30 PM, Qiming Yang wrote:
> This patch add a new function ixgbe_fw_version_get.
>
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
<...>
>
> static void
> +ixgbe_fw_version_get(struct rte_eth_dev *dev, __rte_unused u32 *fw_major,
> + __rte_unused u32 *fw_minor, __rte_unused u32 *fw_patch, u32
> +*etrack_id)
This API at least provide major and minor fw versions I think. Isn't there any kind of FW version information for ixgbe? Just providing etrack_id is not looking good.
> +{
> + struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> + u16 eeprom_verh, eeprom_verl;
> +
> + ixgbe_read_eeprom(hw, 0x2e, &eeprom_verh);
> + ixgbe_read_eeprom(hw, 0x2d, &eeprom_verl);
> +
> + *etrack_id = (eeprom_verh << 16) | eeprom_verl; }
> +
> +static void
> ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info
> *dev_info) {
> struct rte_pci_device *pci_dev = IXGBE_DEV_TO_PCI(dev);
>
^ permalink raw reply
* Re: [PATCH v2 02/18] net/ixgbe: store flow director filter
From: Zhao1, Wei @ 2017-01-04 2:03 UTC (permalink / raw)
To: Dai, Wei, dev@dpdk.org; +Cc: Lu, Wenzhuo
In-Reply-To: <49759EB36A64CF4892C1AFEC9231E8D63A322651@PGSMSX106.gar.corp.intel.com>
Hi, weid
> -----Original Message-----
> From: Dai, Wei
> Sent: Tuesday, January 3, 2017 10:28 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhao1, Wei
> <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 02/18] net/ixgbe: store flow director filter
>
> Hi, Wei Zhao
>
> Would you please do git rebase master for this patch set?
> When I do git pull and then git apply this patch, following errors are reported:
> [root@dpdk4 dpdk-org]# git am ../patches/bundle-488-zhaowei-ixgbe-filter-
> api-v2.mbox
>
This patch is based on dpdk_next_net lib.
> Applying: net/ixgbe: store SYN filter
> Applying: net/ixgbe: store flow director filter
> error: patch failed: drivers/net/ixgbe/ixgbe_ethdev.c:1284
> error: drivers/net/ixgbe/ixgbe_ethdev.c: patch does not apply Patch failed at
> 0002 net/ixgbe: store flow director filter The copy of the patch that failed is
> found in: .git/rebase-apply/patch When you have resolved this problem, run
> "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Friday, December 30, 2016 3:53 PM
> > To: dev@dpdk.org
> > Cc: Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhao1, Wei
> > <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v2 02/18] net/ixgbe: store flow director
> > filter
> >
> > Add support for storing flow director filter in SW.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >
> > v2:
> > --add a fdir initialization function in device start process
> > ---
> > drivers/net/ixgbe/ixgbe_ethdev.c | 55 ++++++++++++++++++++
> > drivers/net/ixgbe/ixgbe_ethdev.h | 19 ++++++-
> > drivers/net/ixgbe/ixgbe_fdir.c | 105
> > ++++++++++++++++++++++++++++++++++++++-
> > 3 files changed, 176 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index 316e560..de27a73 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -60,6 +60,7 @@
> > #include <rte_malloc.h>
> > #include <rte_random.h>
> > #include <rte_dev.h>
> > +#include <rte_hash_crc.h>
> >
> > #include "ixgbe_logs.h"
> > #include "base/ixgbe_api.h"
> > @@ -165,6 +166,7 @@ enum ixgbevf_xcast_modes {
> >
> > static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev); static
> > int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
> > +static int ixgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
> > static int ixgbe_dev_configure(struct rte_eth_dev *dev); static int
> > ixgbe_dev_start(struct rte_eth_dev *dev); static void
> > ixgbe_dev_stop(struct rte_eth_dev *dev); @@ -1276,6 +1278,9 @@
> > eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
> >
> > /* initialize SYN filter */
> > filter_info->syn_info = 0;
> > + /* initialize flow director filter list & hash */
> > + ixgbe_fdir_filter_init(eth_dev);
> > +
> > return 0;
> > }
> >
> > @@ -1284,6 +1289,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev
> > *eth_dev) {
> > struct rte_pci_device *pci_dev;
> > struct ixgbe_hw *hw;
> > + struct ixgbe_hw_fdir_info *fdir_info =
> > + IXGBE_DEV_PRIVATE_TO_FDIR_INFO(eth_dev->data-
> >dev_private);
> > + struct ixgbe_fdir_filter *fdir_filter;
> >
> > PMD_INIT_FUNC_TRACE();
> >
> > @@ -1317,9 +1325,56 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev
> > *eth_dev)
> > rte_free(eth_dev->data->hash_mac_addrs);
> > eth_dev->data->hash_mac_addrs = NULL;
> >
> > + /* remove all the fdir filters & hash */
> > + if (fdir_info->hash_map)
> > + rte_free(fdir_info->hash_map);
> > + if (fdir_info->hash_handle)
> > + rte_hash_free(fdir_info->hash_handle);
> > +
> > + while ((fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list))) {
> > + TAILQ_REMOVE(&fdir_info->fdir_list,
> > + fdir_filter,
> > + entries);
> > + rte_free(fdir_filter);
> > + }
> > +
> > return 0;
> > }
> >
> > +static int ixgbe_fdir_filter_init(struct rte_eth_dev *eth_dev) {
> > + struct ixgbe_hw_fdir_info *fdir_info =
> > + IXGBE_DEV_PRIVATE_TO_FDIR_INFO(eth_dev->data-
> >dev_private);
> > + char fdir_hash_name[RTE_HASH_NAMESIZE];
> > + struct rte_hash_parameters fdir_hash_params = {
> > + .name = fdir_hash_name,
> > + .entries = IXGBE_MAX_FDIR_FILTER_NUM,
> > + .key_len = sizeof(union ixgbe_atr_input),
> > + .hash_func = rte_hash_crc,
> > + .hash_func_init_val = 0,
> > + .socket_id = rte_socket_id(),
> > + };
> > +
> > + TAILQ_INIT(&fdir_info->fdir_list);
> > + snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
> > + "fdir_%s", eth_dev->data->name);
> > + fdir_info->hash_handle = rte_hash_create(&fdir_hash_params);
> > + if (!fdir_info->hash_handle) {
> > + PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
> > + return -EINVAL;
> > + }
> > + fdir_info->hash_map = rte_zmalloc("ixgbe",
> > + sizeof(struct ixgbe_fdir_filter *) *
> > + IXGBE_MAX_FDIR_FILTER_NUM,
> > + 0);
> > + if (!fdir_info->hash_map) {
> > + PMD_INIT_LOG(ERR,
> > + "Failed to allocate memory for fdir hash map!");
> > + return -ENOMEM;
> > + }
> > +
> > + return 0;
> > +}
> > /*
> > * Negotiate mailbox API version with the PF.
> > * After reset API version is always set to the basic one
> (ixgbe_mbox_api_10).
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h
> > b/drivers/net/ixgbe/ixgbe_ethdev.h
> > index 827026c..8310220 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.h
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.h
> > @@ -38,6 +38,7 @@
> > #include "base/ixgbe_dcb_82598.h"
> > #include "ixgbe_bypass.h"
> > #include <rte_time.h>
> > +#include <rte_hash.h>
> >
> > /* need update link, bit flag */
> > #define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) @@ -130,10
> > +131,11 @@
> > #define IXGBE_MISC_VEC_ID
> > RTE_INTR_VEC_ZERO_OFFSET
> > #define IXGBE_RX_VEC_START
> > RTE_INTR_VEC_RXTX_OFFSET
> >
> > +#define IXGBE_MAX_FDIR_FILTER_NUM (1024 * 32)
> > +
> > /*
> > * Information about the fdir mode.
> > */
> > -
> > struct ixgbe_hw_fdir_mask {
> > uint16_t vlan_tci_mask;
> > uint32_t src_ipv4_mask;
> > @@ -148,6 +150,17 @@ struct ixgbe_hw_fdir_mask {
> > uint8_t tunnel_type_mask;
> > };
> >
> > +struct ixgbe_fdir_filter {
> > + TAILQ_ENTRY(ixgbe_fdir_filter) entries;
> > + union ixgbe_atr_input ixgbe_fdir; /* key of fdir filter*/
> > + uint32_t fdirflags; /* drop or forward */
> > + uint32_t fdirhash; /* hash value for fdir */
> > + uint8_t queue; /* assigned rx queue */ };
> > +
> > +/* list of fdir filters */
> > +TAILQ_HEAD(ixgbe_fdir_filter_list, ixgbe_fdir_filter);
> > +
> > struct ixgbe_hw_fdir_info {
> > struct ixgbe_hw_fdir_mask mask;
> > uint8_t flex_bytes_offset;
> > @@ -159,6 +172,10 @@ struct ixgbe_hw_fdir_info {
> > uint64_t remove;
> > uint64_t f_add;
> > uint64_t f_remove;
> > + struct ixgbe_fdir_filter_list fdir_list; /* filter list*/
> > + /* store the pointers of the filters, index is the hash value. */
> > + struct ixgbe_fdir_filter **hash_map;
> > + struct rte_hash *hash_handle; /* cuckoo hash handler */
> > };
> >
> > /* structure for interrupt relative data */ diff --git
> > a/drivers/net/ixgbe/ixgbe_fdir.c b/drivers/net/ixgbe/ixgbe_fdir.c
> > index
> > 4b81ee3..bfcd294 100644
> > --- a/drivers/net/ixgbe/ixgbe_fdir.c
> > +++ b/drivers/net/ixgbe/ixgbe_fdir.c
> > @@ -43,6 +43,7 @@
> > #include <rte_pci.h>
> > #include <rte_ether.h>
> > #include <rte_ethdev.h>
> > +#include <rte_malloc.h>
> >
> > #include "ixgbe_logs.h"
> > #include "base/ixgbe_api.h"
> > @@ -1075,6 +1076,65 @@ fdir_erase_filter_82599(struct ixgbe_hw *hw,
> > uint32_t fdirhash)
> >
> > }
> >
> > +static inline struct ixgbe_fdir_filter *
> > +ixgbe_fdir_filter_lookup(struct ixgbe_hw_fdir_info *fdir_info,
> > + union ixgbe_atr_input *key)
> > +{
> > + int ret = 0;
> > +
> > + ret = rte_hash_lookup(fdir_info->hash_handle, (const void *)key);
> > + if (ret < 0)
> > + return NULL;
> > +
> > + return fdir_info->hash_map[ret];
> > +}
> > +
> > +static inline int
> > +ixgbe_insert_fdir_filter(struct ixgbe_hw_fdir_info *fdir_info,
> > + struct ixgbe_fdir_filter *fdir_filter) {
> > + int ret = 0;
> > +
> > + ret = rte_hash_add_key(fdir_info->hash_handle,
> > + &fdir_filter->ixgbe_fdir);
> > +
> > + if (ret < 0) {
> > + PMD_DRV_LOG(ERR,
> > + "Failed to insert fdir filter to hash table %d!",
> > + ret);
> > + return ret;
> > + }
> > +
> > + fdir_info->hash_map[ret] = fdir_filter;
> > +
> > + TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries);
> > +
> > + return 0;
> > +}
> > +
> > +static inline int
> > +ixgbe_remove_fdir_filter(struct ixgbe_hw_fdir_info *fdir_info,
> > + union ixgbe_atr_input *key)
> > +{
> > + int ret = 0;
> > + struct ixgbe_fdir_filter *fdir_filter;
> > +
> > + ret = rte_hash_del_key(fdir_info->hash_handle, key);
> > +
> > + if (ret < 0) {
> > + PMD_DRV_LOG(ERR, "No such fdir filter to delete %d!", ret);
> > + return ret;
> > + }
> > +
> > + fdir_filter = fdir_info->hash_map[ret];
> > + fdir_info->hash_map[ret] = NULL;
> > +
> > + TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);
> > + rte_free(fdir_filter);
> > +
> > + return 0;
> > +}
> > +
> > /*
> > * ixgbe_add_del_fdir_filter - add or remove a flow diretor filter.
> > * @dev: pointer to the structure rte_eth_dev @@ -1098,6 +1158,8 @@
> > ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
> > struct ixgbe_hw_fdir_info *info =
> > IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data-
> >dev_private);
> > enum rte_fdir_mode fdir_mode = dev->data-
> >dev_conf.fdir_conf.mode;
> > + struct ixgbe_fdir_filter *node;
> > + bool add_node = FALSE;
> >
> > if (fdir_mode == RTE_FDIR_MODE_NONE)
> > return -ENOTSUP;
> > @@ -1148,6 +1210,10 @@ ixgbe_add_del_fdir_filter(struct rte_eth_dev
> *dev,
> > dev->data-
> >dev_conf.fdir_conf.pballoc);
> >
> > if (del) {
> > + err = ixgbe_remove_fdir_filter(info, &input);
> > + if (err < 0)
> > + return err;
> > +
> > err = fdir_erase_filter_82599(hw, fdirhash);
> > if (err < 0)
> > PMD_DRV_LOG(ERR, "Fail to delete FDIR filter!");
> @@ -1172,6
> > +1238,37 @@ ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
> > else
> > return -EINVAL;
> >
> > + node = ixgbe_fdir_filter_lookup(info, &input);
> > + if (node) {
> > + if (update) {
> > + node->fdirflags = fdircmd_flags;
> > + node->fdirhash = fdirhash;
> > + node->queue = queue;
> > + } else {
> > + PMD_DRV_LOG(ERR, "Conflict with existing fdir
> filter!");
> > + return -EINVAL;
> > + }
> > + } else {
> > + add_node = TRUE;
> > + node = rte_zmalloc("ixgbe_fdir",
> > + sizeof(struct ixgbe_fdir_filter),
> > + 0);
> > + if (!node)
> > + return -ENOMEM;
> > + (void)rte_memcpy(&node->ixgbe_fdir,
> > + &input,
> > + sizeof(union ixgbe_atr_input));
> > + node->fdirflags = fdircmd_flags;
> > + node->fdirhash = fdirhash;
> > + node->queue = queue;
> > +
> > + err = ixgbe_insert_fdir_filter(info, node);
> > + if (err < 0) {
> > + rte_free(node);
> > + return err;
> > + }
> > + }
> > +
> > if (is_perfect) {
> > err = fdir_write_perfect_filter_82599(hw, &input, queue,
> > fdircmd_flags, fdirhash,
> > @@ -1180,10 +1277,14 @@ ixgbe_add_del_fdir_filter(struct rte_eth_dev
> > *dev,
> > err = fdir_add_signature_filter_82599(hw, &input, queue,
> > fdircmd_flags, fdirhash);
> > }
> > - if (err < 0)
> > + if (err < 0) {
> > PMD_DRV_LOG(ERR, "Fail to add FDIR filter!");
> > - else
> > +
> > + if (add_node)
> > + (void)ixgbe_remove_fdir_filter(info, &input);
> > + } else {
> > PMD_DRV_LOG(DEBUG, "Success to add FDIR filter");
> > + }
> >
> > return err;
> > }
> > --
> > 2.5.5
^ permalink raw reply
* Re: [PATCH v2 01/18] net/ixgbe: store SYN filter
From: Zhao1, Wei @ 2017-01-04 1:46 UTC (permalink / raw)
To: Dai, Wei, dev@dpdk.org; +Cc: Lu, Wenzhuo
In-Reply-To: <49759EB36A64CF4892C1AFEC9231E8D63A322663@PGSMSX106.gar.corp.intel.com>
Hi, Daiwei
> -----Original Message-----
> From: Dai, Wei
> Sent: Tuesday, January 3, 2017 10:33 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhao1, Wei
> <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 01/18] net/ixgbe: store SYN filter
>
> Hi, Wei Zhao
>
> I think that you had better give a cover letter for such a series of patches.
> You can give the changes between v2 and v1 in cover letter and maybe no
> need describe it in each one.
>
Ok, I will add cover letter in v3
> Thanks &Best Regards
> -Wei
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Friday, December 30, 2016 3:53 PM
> > To: dev@dpdk.org
> > Cc: Lu, Wenzhuo <wenzhuo.lu@intel.com>; Zhao1, Wei
> > <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v2 01/18] net/ixgbe: store SYN filter
> >
> > Add support for storing SYN filter in SW.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >
> > v2:
> > --synqf assignment location change
> > ---
> > drivers/net/ixgbe/ixgbe_ethdev.c | 14 +++++++++++---
> > drivers/net/ixgbe/ixgbe_ethdev.h | 2 ++
> > 2 files changed, 13 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> > b/drivers/net/ixgbe/ixgbe_ethdev.c
> > index a25bac8..316e560 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> > @@ -1274,6 +1274,8 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
> > memset(filter_info->fivetuple_mask, 0,
> > sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
> >
> > + /* initialize SYN filter */
> > + filter_info->syn_info = 0;
> > return 0;
> > }
> >
> > @@ -5580,15 +5582,18 @@ ixgbe_syn_filter_set(struct rte_eth_dev *dev,
> > bool add)
> > {
> > struct ixgbe_hw *hw =
> > IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> > + struct ixgbe_filter_info *filter_info =
> > + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data-
> >dev_private);
> > + uint32_t syn_info;
> > uint32_t synqf;
> >
> > if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM)
> > return -EINVAL;
> >
> > - synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
> > + syn_info = filter_info->syn_info;
> >
> > if (add) {
> > - if (synqf & IXGBE_SYN_FILTER_ENABLE)
> > + if (syn_info & IXGBE_SYN_FILTER_ENABLE)
> > return -EINVAL;
> > synqf = (uint32_t)(((filter->queue <<
> > IXGBE_SYN_FILTER_QUEUE_SHIFT) &
> > IXGBE_SYN_FILTER_QUEUE) |
> IXGBE_SYN_FILTER_ENABLE); @@ -5598,10
> > +5603,13 @@ ixgbe_syn_filter_set(struct rte_eth_dev *dev,
> > else
> > synqf &= ~IXGBE_SYN_FILTER_SYNQFP;
> > } else {
> > - if (!(synqf & IXGBE_SYN_FILTER_ENABLE))
> > + synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF);
> > + if (!(syn_info & IXGBE_SYN_FILTER_ENABLE))
> > return -ENOENT;
> > synqf &= ~(IXGBE_SYN_FILTER_QUEUE |
> IXGBE_SYN_FILTER_ENABLE);
> > }
> > +
> > + filter_info->syn_info = synqf;
> > IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf);
> > IXGBE_WRITE_FLUSH(hw);
> > return 0;
> > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h
> > b/drivers/net/ixgbe/ixgbe_ethdev.h
> > index 4ff6338..827026c 100644
> > --- a/drivers/net/ixgbe/ixgbe_ethdev.h
> > +++ b/drivers/net/ixgbe/ixgbe_ethdev.h
> > @@ -262,6 +262,8 @@ struct ixgbe_filter_info {
> > /* Bit mask for every used 5tuple filter */
> > uint32_t fivetuple_mask[IXGBE_5TUPLE_ARRAY_SIZE];
> > struct ixgbe_5tuple_filter_list fivetuple_list;
> > + /* store the SYN filter info */
> > + uint32_t syn_info;
> > };
> >
> > /*
> > --
> > 2.5.5
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox