DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v8 00/25] Support VFD on i40e
From: Lu, Wenzhuo @ 2017-01-12  3:21 UTC (permalink / raw)
  To: Vincent JARDIN, Yigit, Ferruh, Zhang, Helin, dev@dpdk.org
  Cc: 'JOSHI, KAUSTUBH', 'DANIELS, EDWARD',
	'ZELEZNIAK, ALEX', Chen, Jing D
In-Reply-To: <ea5d8fdb-2de3-3dbf-bbb5-5c2099c8c73a@6wind.com>

Hi Vincent,

> -----Original Message-----
> From: Vincent JARDIN [mailto:vincent.jardin@6wind.com]
> Sent: Wednesday, January 11, 2017 9:14 PM
> To: Yigit, Ferruh; Zhang, Helin; Lu, Wenzhuo; dev@dpdk.org
> Cc: 'JOSHI, KAUSTUBH'; 'DANIELS, EDWARD'; 'ZELEZNIAK, ALEX'
> Subject: Re: [dpdk-dev] [PATCH v8 00/25] Support VFD on i40e
> 
> Le 10/01/2017 à 22:32, Ferruh Yigit a écrit :
> > What do you think to continue high level DPDK PF discussion in mail
> > thread for other pathset? So that we can continue to work on this one.
> 
> First, we need to assess or not if it makes sense to go toward Linux kernel or
> DPDK based PF. If Linux kernel is used, then DPDK does not need VFD related
> modifications.
> 
> VFD demonstrates that there are some needs of features, but it pushes the
> new path of a fork of PF drivers.
We're not sure if we want to change and maintain a totally new DPDK PF either. 
So, we only change PMD code and not expose it to abstraction layer. It can only be used by some users who have the needs. 
It's experimental and comes from the users' requirement. If it's good enough and accepted by other NICs, we can expose it. 
If it's not good, it still can be a choice before Linux kernel provides.

^ permalink raw reply

* [PATCH v2] doc: add known uio_pci_generic issue for i40e
From: Jeff Guo @ 2017-01-12  3:27 UTC (permalink / raw)
  To: helin.zhang, jingjing.wu; +Cc: dev, jia.guo
In-Reply-To: <1482460523-74460-1-git-send-email-jia.guo@intel.com>

From: "Guo, Jia" <jia.guo@intel.com>

When bind with uio_pci_generic in X710/XL710/XXV710, the result
is failed. uio_pci_generic is not supported by X710/XL710/XXV710.

Signed-off-by: Guo, Jia <jia.guo@intel.com>
---
v2: add X710/XXV710 limitation case
---
 doc/guides/rel_notes/known_issues.rst | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/doc/guides/rel_notes/known_issues.rst b/doc/guides/rel_notes/known_issues.rst
index 3cd4237..1751451 100644
--- a/doc/guides/rel_notes/known_issues.rst
+++ b/doc/guides/rel_notes/known_issues.rst
@@ -640,3 +640,27 @@ I40e VF may not receive packets in the promiscuous mode
 
 **Driver/Module**:
    Poll Mode Driver (PMD).
+
+
+uio_pci_generic bind failed in X710/XL710/XXV710
+-------------------------------------------------------
+
+**Description**:
+   uio_pci_generic is not supported by XL710, since the errata of XL710 that the feature
+   about the Interrupt Status bit is not implemented.The errata is the item #71 from the
+   `xl710 controller spec  <http://www.intel.com/content/www/us/en/embedded/products/networking/xl710-10-40-controller-spec-update.html>`_.
+   The hw limitation is the same as other X710/XXV710 NICs.
+
+**Implication**:
+   When bind uio_pci_generic, the uio_pci_generic probe device and check the Interrupt
+   Status bit related feature of NICs , since it is not supported by X710/XL710/XXV710,
+   so it return failed.
+
+**Resolution/Workaround**:
+   Do not bind to use uio_pci_generic in X710/XL710/XXV710 NICs.
+
+**Affected Environment/Platform**:
+   All.
+
+**Driver/Module**:
+   Poll Mode Driver (PMD).
-- 
2.7.4

^ permalink raw reply related

* [PATCH v5] app/testpmd: supported offload capabilities query
From: Qiming Yang @ 2017-01-12  3:26 UTC (permalink / raw)
  To: dev; +Cc: Qiming Yang
In-Reply-To: <1482485513-7087-1-git-send-email-qiming.yang@intel.com>

Add two new commands "show port cap <port>" and "show
port cap all"to diaplay what offload capabilities supported
in ports. It will not only display all the capabilities of
the port, but also the enabling condition for each capability
in the running time.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
---
v2 changes:
* fixed the output style as Ferruh's patch show and add some
  description in docs for new functions.
v3 changes:
* add new command in cmd_help_long_parsed.
v4 changes:
* use 'cap' instead of 'capa'.
v5 changes:
* rebased, fixed the inappropriate expression and adjusted the
  output order.
---
---
 app/test-pmd/cmdline.c                      |  17 ++-
 app/test-pmd/config.c                       | 175 ++++++++++++++++++++++++++++
 app/test-pmd/testpmd.h                      |   1 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  12 +-
 4 files changed, 195 insertions(+), 10 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4e8b0d8..6fa1783 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -183,7 +183,7 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"Display:\n"
 			"--------\n\n"
 
-			"show port (info|stats|xstats|fdir|stat_qmap|dcb_tc) (port_id|all)\n"
+			"show port (info|stats|xstats|fdir|stat_qmap|dcb_tc|cap) (port_id|all)\n"
 			"    Display information for port_id, or all.\n\n"
 
 			"show port X rss reta (size) (mask0,mask1,...)\n"
@@ -5812,6 +5812,9 @@ static void cmd_showportall_parsed(void *parsed_result,
 	else if (!strcmp(res->what, "dcb_tc"))
 		FOREACH_PORT(i, ports)
 			port_dcb_info_display(i);
+	else if (!strcmp(res->what, "cap"))
+		FOREACH_PORT(i, ports)
+			port_offload_cap_display(i);
 }
 
 cmdline_parse_token_string_t cmd_showportall_show =
@@ -5821,13 +5824,14 @@ cmdline_parse_token_string_t cmd_showportall_port =
 	TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, port, "port");
 cmdline_parse_token_string_t cmd_showportall_what =
 	TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, what,
-				 "info#stats#xstats#fdir#stat_qmap#dcb_tc");
+				 "info#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
 cmdline_parse_token_string_t cmd_showportall_all =
 	TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, all, "all");
 cmdline_parse_inst_t cmd_showportall = {
 	.f = cmd_showportall_parsed,
 	.data = NULL,
-	.help_str = "show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc all",
+	.help_str = "show|clear port"
+	"info|stats|xstats|fdir|stat_qmap|dcb_tc|cap all",
 	.tokens = {
 		(void *)&cmd_showportall_show,
 		(void *)&cmd_showportall_port,
@@ -5867,6 +5871,8 @@ static void cmd_showport_parsed(void *parsed_result,
 		nic_stats_mapping_display(res->portnum);
 	else if (!strcmp(res->what, "dcb_tc"))
 		port_dcb_info_display(res->portnum);
+	else if (!strcmp(res->what, "cap"))
+		port_offload_cap_display(res->portnum);
 }
 
 cmdline_parse_token_string_t cmd_showport_show =
@@ -5876,14 +5882,15 @@ cmdline_parse_token_string_t cmd_showport_port =
 	TOKEN_STRING_INITIALIZER(struct cmd_showport_result, port, "port");
 cmdline_parse_token_string_t cmd_showport_what =
 	TOKEN_STRING_INITIALIZER(struct cmd_showport_result, what,
-				 "info#stats#xstats#fdir#stat_qmap#dcb_tc");
+				 "info#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
 cmdline_parse_token_num_t cmd_showport_portnum =
 	TOKEN_NUM_INITIALIZER(struct cmd_showport_result, portnum, UINT8);
 
 cmdline_parse_inst_t cmd_showport = {
 	.f = cmd_showport_parsed,
 	.data = NULL,
-	.help_str = "show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc "
+	.help_str = "show|clear port"
+		"info|stats|xstats|fdir|stat_qmap|dcb_tc|cap "
 		"<port_id>",
 	.tokens = {
 		(void *)&cmd_showport_show,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 617e6d4..8a2ef56 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -542,6 +542,181 @@ port_infos_display(portid_t port_id)
 		dev_info.tx_desc_lim.nb_min);
 	printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
 }
+void
+port_offload_cap_display(portid_t port_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	static const char *info_border = "************";
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	dev = &rte_eth_devices[port_id];
+	rte_eth_dev_info_get(port_id, &dev_info);
+
+	printf("\n%s Port %d supported offload features: %s\n",
+		info_border, port_id, info_border);
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
+		printf("VLAN stripped:                 ");
+		if (dev->data->dev_conf.rxmode.hw_vlan_strip)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) {
+		printf("Double VLANs stripped:         ");
+		if (dev->data->dev_conf.rxmode.hw_vlan_extend)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) {
+		printf("RX IPv4 checksum:              ");
+		if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) {
+		printf("RX UDP checksum:               ");
+		if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) {
+		printf("RX TCP checksum:               ");
+		if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
+		printf("RX Outer IPv4 checksum:        ");
+
+	if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
+		printf("Large receive offload:         ");
+		if (dev->data->dev_conf.rxmode.enable_lro)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) {
+		printf("VLAN insert:                   ");
+		if (ports[port_id].tx_ol_flags &
+		    TESTPMD_TX_OFFLOAD_INSERT_VLAN)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
+		printf("Double VLANs insert:           ");
+		if (ports[port_id].tx_ol_flags &
+		    TESTPMD_TX_OFFLOAD_INSERT_QINQ)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) {
+		printf("TX IPv4 checksum:              ");
+		if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) {
+		printf("TX UDP checksum:               ");
+		if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) {
+		printf("TX TCP checksum:               ");
+		if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
+		printf("TX SCTP checksum:              ");
+		if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) {
+		printf("TX Outer IPv4 checksum:        ");
+		if (ports[port_id].tx_ol_flags &
+		    TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
+		printf("TX TCP segmentation:           ");
+		if (ports[port_id].tso_segsz != 0)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO) {
+		printf("TX UDP segmentation:           ");
+		if (ports[port_id].tso_segsz != 0)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO) {
+		printf("TSO for VXLAN tunnel packet:   ");
+		if (ports[port_id].tunnel_tso_segsz)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO) {
+		printf("TSO for GRE tunnel packet:     ");
+		if (ports[port_id].tunnel_tso_segsz)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO) {
+		printf("TSO for IPIP tunnel packet:    ");
+		if (ports[port_id].tunnel_tso_segsz)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO) {
+		printf("TSO for GENEVE tunnel packet:  ");
+		if (ports[port_id].tunnel_tso_segsz)
+			printf("on\n");
+		else
+			printf("off\n");
+	}
+
+}
 
 int
 port_id_is_invalid(portid_t port_id, enum print_warning warning)
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 22ce2d6..8b2374a 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -498,6 +498,7 @@ void nic_xstats_display(portid_t port_id);
 void nic_xstats_clear(portid_t port_id);
 void nic_stats_mapping_display(portid_t port_id);
 void port_infos_display(portid_t port_id);
+void port_offload_cap_display(portid_t port_id);
 void rx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
 void tx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
 void fwd_lcores_config_display(void);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index c611dc5..0e49d98 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -51,10 +51,10 @@ If you type a partial command and hit ``<TAB>`` you get a list of the available
 
    testpmd> show port <TAB>
 
-       info [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc X
-       info [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc all
-       stats [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc X
-       stats [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc all
+       info [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc|cap X
+       info [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc|cap all
+       stats [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc|cap X
+       stats [Mul-choice STRING]: show|clear port info|stats|xstats|fdir|stat_qmap|dcb_tc|cap all
        ...
 
 
@@ -131,7 +131,7 @@ show port
 
 Display information for a given port or all ports::
 
-   testpmd> show port (info|stats|xstats|fdir|stat_qmap|dcb_tc) (port_id|all)
+   testpmd> show port (info|stats|xstats|fdir|stat_qmap|dcb_tc|cap) (port_id|all)
 
 The available information categories are:
 
@@ -147,6 +147,8 @@ The available information categories are:
 
 * ``dcb_tc``: DCB information such as TC mapping.
 
+* ``cap``: Supported offload capabilities.
+
 For example:
 
 .. code-block:: console
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v5 00/29] Support VFD and DPDK PF + kernel VF on i40e
From: Chen, Jing D @ 2017-01-12  3:47 UTC (permalink / raw)
  To: Vincent JARDIN, Scott Daniels, dev@dpdk.org
  Cc: kaustubh@research.att.com, az5157@att.com
In-Reply-To: <ac872854-11c0-ba37-8261-c265d1dc80db@6wind.com>

Hi, Vincent,

> -----Original Message-----
> From: Vincent JARDIN [mailto:vincent.jardin@6wind.com]
> Sent: Tuesday, January 10, 2017 9:30 PM
> To: Scott Daniels <daniels@research.att.com>; dev@dpdk.org
> Cc: kaustubh@research.att.com; az5157@att.com; Chen, Jing D
> <jing.d.chen@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v5 00/29] Support VFD and DPDK PF + kernel VF on
> i40e
> 
> Hi Scott,
> 
> Le 04/01/2017 à 22:09, Scott Daniels a écrit :
> >  With holidays we are a bit late with our thoughts, but would like to
> >  toss them into the mix.
> 
> Same, I hope I am not missing emails. I do appreciate your arguments, it
> provides lot of light. See below,
> 
> >  The original NAK is understandable, however having the ability to
> >  configure the PF via DPDK is advantageous for several reasons:
> >
> >  1) While some functions may be duplicated and/or available from the kernel
> >  driver, it is often not possible to introduce new kernel drivers into
> >  production without a large amount of additional testing of the entire
> >  platform which can cause a significant delay when introducing a DPDK based
> >  product.  If the PF control is a part of the DPDK environment, then only
> >  the application needs to pass the operational testing before deployment; a
> >  much more simple task.
> 
> So we agree: you confirm that your foresee the benefits of using DPDK to
> *bypass the role of the Kernel being the PF* of reference for the
> hypervisor.
> 
> >  2) If the driver changes are upstreamed into the kernel proper, the
> >  difficulty of operational readiness testing increases as a new kernel is
> >  introduced, and further undermines the ability to quickly and easily
> >  release a DPDK based application into production.  While the application
> >  may eventually fall back on driver and/or kernel support, this could be
> >  years away.
> 
> I do agree with the benefits of the agilities and the upsides it brings.
> But they are other options to get the same agility without creating a
> fragmentation of PFs.
> 
> For example, you do not have to update the whole kernel, you can just
> update the PF kernel module that can be upgraded with the latest needed
> features.
> 
> >  3) As DPDK is being used to configure the NIC, it just seems to make
> >  sense, for consistency, that the configuration capabilities should include
> >  the ability to configure the PF as is proposed.
> 
>  From this perspective, the kernel modules are fine for the PF: most
> kernels of hypervisors support it without the need to upgrade their kernels.
> 
> To summarize, I understand that you need a flexible way to upgrade PF
> features without touching/changing the kernel. So let's check the kernel
> module option? VFD brings some interesting capabilities, could it be a
> way to push and stimulate the i40e features instead of using DPDK?
> 
>    https://sourceforge.net/projects/e1000/files/i40e%20stable/
> for instance could be better stimulated.

May I ask what if DPDK VF need a new extension function from PF?
Then, we'll have to build kernel community expertise and submit
patch to Linux PF and wait for merge.
Your proposal indicates DPDK community submitters will have to
ask Linux community to authorize if we'll have any requirements
in DPDK VF.
Comparing fragmentation, the extra dependency worry me most.
Can you imagine how long it will be for any VF features gets
ready?  



^ permalink raw reply

* Re: [PATCH] vhost: Introduce vhost-user's REPLY_ACK feature
From: Yuanhan Liu @ 2017-01-12  4:03 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev
In-Reply-To: <20161212175400.7978-1-maxime.coquelin@redhat.com>

On Mon, Dec 12, 2016 at 06:54:00PM +0100, Maxime Coquelin wrote:
> REPLY_ACK features provide a generic way for QEMU to ensure both
> completion and success of a request.
> 
> As described in vhost-user spec in QEMU repository, QEMU sets
> VHOST_USER_NEED_REPLY flag (bit 3) when expecting a reply_ack from
> the backend. Backend must reply with 0 for success or non-zero
> otherwise when flag is set.
> 
> Currently, only VHOST_USER_SET_MEM_TABLE request implements reply_ack,
> in order to synchronize mapping updates.
> 
> This patch enables REPLY_ACK feature generally, but only checks error
> code for VHOST_USER_SET_MEM_TABLE.
> 
> Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Applied to dpdk-next-virtio.

Thanks.

	--yliu

^ permalink raw reply

* Re: [PATCH v6] vhost: allow for many vhost user ports
From: Yuanhan Liu @ 2017-01-12  4:05 UTC (permalink / raw)
  To: dev; +Cc: Patrik Andersson, Jan Wickbom
In-Reply-To: <1482313513-1709-1-git-send-email-yuanhan.liu@linux.intel.com>

On Wed, Dec 21, 2016 at 05:45:13PM +0800, Yuanhan Liu wrote:
> From: Jan Wickbom <jan.wickbom@ericsson.com>
> 
> Currently select() is used to monitor file descriptors for vhostuser
> ports. This limits the number of ports possible to create since the
> fd number is used as index in the fd_set and we have seen fds > 1023.
> This patch changes select() to poll(). This way we can keep an
> packed (pollfd) array for the fds, e.g. as many fds as the size of
> the array.
> 
> Also see:
> http://dpdk.org/ml/archives/dev/2016-April/037024.html
> 
> Reported-by: Patrik Andersson <patrik.r.andersson@ericsson.com>
> Signed-off-by: Jan Wickbom <jan.wickbom@ericsson.com>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>

Applied to dpdk-next-virtio.

	--yliu

^ permalink raw reply

* Re: [PATCH 1/2] add rte_bus->probe
From: Shreyansh Jain @ 2017-01-12  5:28 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev@dpdk.org
In-Reply-To: <af4540a3-1b9f-dc40-fab4-c0a67a82562d@intel.com>

> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Wednesday, January 11, 2017 8:34 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>; dev@dpdk.org
> Cc: Stephen Hemminger <sthemmin@microsoft.com>; Jan Blunck
> <jblunck@infradead.org>
> Subject: Re: [PATCH 1/2] add rte_bus->probe
> 
> On 1/11/2017 4:53 AM, Shreyansh Jain wrote:
> > On Tuesday 10 January 2017 11:32 PM, Ferruh Yigit wrote:
> >> Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
> >> ---
> >>  lib/librte_eal/common/eal_common_bus.c  | 7 ++++---
> >>  lib/librte_eal/common/include/rte_bus.h | 3 +++
> >>  lib/librte_eal/linuxapp/eal/eal_pci.c   | 1 +
> >>  3 files changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/lib/librte_eal/common/eal_common_bus.c
> b/lib/librte_eal/common/eal_common_bus.c
> >> index f8c2e03..e8d1143 100644
> >> --- a/lib/librte_eal/common/eal_common_bus.c
> >> +++ b/lib/librte_eal/common/eal_common_bus.c
> >> @@ -145,6 +145,7 @@ rte_eal_bus_register(struct rte_bus *bus)
> >>  	/* A bus should mandatorily have the scan and match implemented */
> >>  	RTE_VERIFY(bus->scan);
> >>  	RTE_VERIFY(bus->match);
> >> +	RTE_VERIFY(bus->probe);
> >
> > v6 of my patches would include the above.
> 
> Since I am aware of you are working on something similar, I added this
> (in a dirty way) just to able to test next patch.

:) I understood this after sending my mail. I understand your point.

> 
> Thanks,
> ferruh
> 
> <...>

^ permalink raw reply

* Re: [PATCH v3 6/6] net/virtio: remove dead structure field
From: Yuanhan Liu @ 2017-01-12  6:02 UTC (permalink / raw)
  To: dev
In-Reply-To: <1483697780-12088-7-git-send-email-yuanhan.liu@linux.intel.com>

On Fri, Jan 06, 2017 at 06:16:20PM +0800, Yuanhan Liu wrote:
> Actually, virtio_hw->dev is not used since the beginning when it's
> introduced. Remove it.

It's not true after the refactoring of decoupling from PCI device.
This patch is dropped. Instead, two more patches will be sent soon.

	--yliu

^ permalink raw reply

* [PATCH 1/2] net/virtio: access interrupt handler directly
From: Yuanhan Liu @ 2017-01-12  6:03 UTC (permalink / raw)
  To: dev; +Cc: Yuanhan Liu

Since commit 0e1b45a284b4 ("ethdev: decouple interrupt handling from
PCI device"), intr_handle is stored at eth_dev struct, that we could
use it directly. Thus there is no need to get it from hw.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 9 ++++-----
 drivers/net/virtio/virtio_pci.h    | 6 ------
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 495de11..edef2a2 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1397,7 +1397,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 
 	/* Setup interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
-		rte_intr_callback_register(vtpci_intr_handle(hw),
+		rte_intr_callback_register(eth_dev->intr_handle,
 			virtio_interrupt_handler, eth_dev);
 
 	return 0;
@@ -1425,7 +1425,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 
 	/* reset interrupt callback  */
 	if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
-		rte_intr_callback_unregister(vtpci_intr_handle(hw),
+		rte_intr_callback_unregister(eth_dev->intr_handle,
 						virtio_interrupt_handler,
 						eth_dev);
 	if (hw->dev)
@@ -1544,7 +1544,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 			return -ENOTSUP;
 		}
 
-		if (rte_intr_enable(vtpci_intr_handle(hw)) < 0) {
+		if (rte_intr_enable(dev->intr_handle) < 0) {
 			PMD_DRV_LOG(ERR, "interrupt enable failed");
 			return -EIO;
 		}
@@ -1636,13 +1636,12 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 static void
 virtio_dev_stop(struct rte_eth_dev *dev)
 {
-	struct virtio_hw *hw = dev->data->dev_private;
 	struct rte_eth_link link;
 
 	PMD_INIT_LOG(DEBUG, "stop");
 
 	if (dev->data->dev_conf.intr_conf.lsc)
-		rte_intr_disable(vtpci_intr_handle(hw));
+		rte_intr_disable(dev->intr_handle);
 
 	memset(&link, 0, sizeof(link));
 	virtio_dev_atomic_write_link_status(dev, &link);
diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h
index 38a71a4..511a1c8 100644
--- a/drivers/net/virtio/virtio_pci.h
+++ b/drivers/net/virtio/virtio_pci.h
@@ -333,12 +333,6 @@ int vtpci_init(struct rte_pci_device *, struct virtio_hw *,
 
 uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t);
 
-static inline struct rte_intr_handle *
-vtpci_intr_handle(struct virtio_hw *hw)
-{
-	return hw->dev ? &hw->dev->intr_handle : NULL;
-}
-
 extern const struct virtio_pci_ops legacy_ops;
 extern const struct virtio_pci_ops modern_ops;
 extern const struct virtio_pci_ops virtio_user_ops;
-- 
1.9.0

^ permalink raw reply related

* [PATCH 2/2] net/virtio: do not store PCI device pointer at shared memory
From: Yuanhan Liu @ 2017-01-12  6:03 UTC (permalink / raw)
  To: dev; +Cc: Yuanhan Liu
In-Reply-To: <1484201000-31071-1-git-send-email-yuanhan.liu@linux.intel.com>

hw->dev, a pointer to pci_dev, was actually not used, until the
refactor of decouping from PCI device. This would somehow break
the multiple process again, since "hw" is stored at shared memory,
while "pci_dev" is not: the primary and secondary process could
have different address for it, while just one value is allowed.

Thus we should not store it to "hw", instead, we could retrieve
it from the "eth_dev->device" field.

Fixes: ae34410a8a8a ("ethdev: move info filling of PCI into drivers")
Fixes: eac901ce29be ("ethdev: decouple from PCI device")

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 16 ++++++++--------
 drivers/net/virtio/virtio_pci.c    |  2 --
 drivers/net/virtio/virtio_pci.h    |  1 -
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index edef2a2..f596f4d 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -489,7 +489,7 @@ struct rte_virtio_xstats_name_off {
 	 * virtual address. And we need properly set _offset_, please see
 	 * VIRTIO_MBUF_DATA_DMA_ADDR in virtqueue.h for more information.
 	 */
-	if (hw->dev)
+	if (!hw->virtio_user_dev)
 		vq->offset = offsetof(struct rte_mbuf, buf_physaddr);
 	else {
 		vq->vq_ring_mem = (uintptr_t)mz->addr;
@@ -1194,7 +1194,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 	struct virtio_hw *hw = eth_dev->data->dev_private;
 	struct virtio_net_config *config;
 	struct virtio_net_config local_config;
-	struct rte_pci_device *pci_dev = hw->dev;
+	struct rte_pci_device *pci_dev = NULL;
 	int ret;
 
 	/* Reset the device although not necessary at startup */
@@ -1214,8 +1214,10 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 	else
 		eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
 
-	if (pci_dev)
+	if (eth_dev->device) {
+		pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
 		rte_eth_copy_pci_info(eth_dev, pci_dev);
+	}
 
 	rx_func_get(eth_dev);
 
@@ -1406,8 +1408,6 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 static int
 eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 {
-	struct virtio_hw *hw = eth_dev->data->dev_private;
-
 	PMD_INIT_FUNC_TRACE();
 
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
@@ -1428,8 +1428,8 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 		rte_intr_callback_unregister(eth_dev->intr_handle,
 						virtio_interrupt_handler,
 						eth_dev);
-	if (hw->dev)
-		rte_eal_pci_unmap_device(hw->dev);
+	if (eth_dev->device)
+		rte_eal_pci_unmap_device(RTE_DEV_TO_PCI(eth_dev->device));
 
 	PMD_INIT_LOG(DEBUG, "dev_uninit completed");
 
@@ -1687,7 +1687,7 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev)
 	uint64_t tso_mask;
 	struct virtio_hw *hw = dev->data->dev_private;
 
-	dev_info->pci_dev = hw->dev;
+	dev_info->pci_dev = dev->device ? RTE_DEV_TO_PCI(dev->device) : NULL;
 	dev_info->max_rx_queues =
 		RTE_MIN(hw->max_queue_pairs, VIRTIO_MAX_RX_QUEUES);
 	dev_info->max_tx_queues =
diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c
index f5754e5..fbdb5b7 100644
--- a/drivers/net/virtio/virtio_pci.c
+++ b/drivers/net/virtio/virtio_pci.c
@@ -730,8 +730,6 @@
 vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw,
 	   uint32_t *dev_flags)
 {
-	hw->dev = dev;
-
 	/*
 	 * Try if we can succeed reading virtio pci caps, which exists
 	 * only on modern pci device. If failed, we fallback to legacy
diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h
index 511a1c8..4235bef 100644
--- a/drivers/net/virtio/virtio_pci.h
+++ b/drivers/net/virtio/virtio_pci.h
@@ -258,7 +258,6 @@ struct virtio_hw {
 	uint32_t    notify_off_multiplier;
 	uint8_t     *isr;
 	uint16_t    *notify_base;
-	struct rte_pci_device *dev;
 	struct virtio_pci_common_cfg *common_cfg;
 	struct virtio_net_config *dev_cfg;
 	void	    *virtio_user_dev;
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 0/2] maintainers: minor updates to virtio/vhost
From: Yuanhan Liu @ 2017-01-12  6:24 UTC (permalink / raw)
  To: dev; +Cc: Yuanhan Liu
In-Reply-To: <1480575999-14453-1-git-send-email-yuanhan.liu@linux.intel.com>

v2: split virtio and vhost

---
Yuanhan Liu (2):
  maintainers: update virtio maintainer
  maintainers: split virtio and vhost

 MAINTAINERS | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

-- 
1.9.0

^ permalink raw reply

* [PATCH v2 1/2] maintainers: update virtio maintainer
From: Yuanhan Liu @ 2017-01-12  6:24 UTC (permalink / raw)
  To: dev; +Cc: Yuanhan Liu, Huawei Xie
In-Reply-To: <1484202298-17680-1-git-send-email-yuanhan.liu@linux.intel.com>

Huawei has left DPDK team for months, and he hasn't showed up since
then. Remove him.

Cc: Huawei Xie <huawei.xie@intel.com>
Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 MAINTAINERS | 1 -
 1 file changed, 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9645c9b..ca0c276 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -367,7 +367,6 @@ F: drivers/net/qede/
 F: doc/guides/nics/qede.rst
 
 RedHat virtio
-M: Huawei Xie <huawei.xie@intel.com>
 M: Yuanhan Liu <yuanhan.liu@linux.intel.com>
 T: git://dpdk.org/next/dpdk-next-virtio
 F: drivers/net/virtio/
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 2/2] maintainers: split virtio and vhost
From: Yuanhan Liu @ 2017-01-12  6:24 UTC (permalink / raw)
  To: dev; +Cc: Yuanhan Liu
In-Reply-To: <1484202298-17680-1-git-send-email-yuanhan.liu@linux.intel.com>

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---

v2: split virtio and vhost

---
 MAINTAINERS | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ca0c276..f9b3f5e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -366,16 +366,21 @@ M: Harish Patil <harish.patil@cavium.com>
 F: drivers/net/qede/
 F: doc/guides/nics/qede.rst
 
-RedHat virtio
+Vhost-user
 M: Yuanhan Liu <yuanhan.liu@linux.intel.com>
 T: git://dpdk.org/next/dpdk-next-virtio
-F: drivers/net/virtio/
-F: doc/guides/nics/virtio.rst
 F: lib/librte_vhost/
 F: doc/guides/prog_guide/vhost_lib.rst
 F: examples/vhost/
 F: doc/guides/sample_app_ug/vhost.rst
 
+
+Virtio PMD
+M: Yuanhan Liu <yuanhan.liu@linux.intel.com>
+T: git://dpdk.org/next/dpdk-next-virtio
+F: drivers/net/virtio/
+F: doc/guides/nics/virtio.rst
+
 VMware vmxnet3
 M: Yong Wang <yongwang@vmware.com>
 F: drivers/net/vmxnet3/
-- 
1.9.0

^ permalink raw reply related

* [PATCH v8 0/5] new API 'rte_eth_dev_fw_version_get'
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484116905-57438-1-git-send-email-qiming.yang@intel.com>

v8: - defined the minimum fw version size as a macro.

v7: - rebased

v6: - renamed fw_length -> fw_size
    - added return value for insufficient fw_size
    - fixed the indentation problem in e1000
    - added ver.build.patch in i40e, keep the same with Linux kernel driver

v5: - modified the API rte_eth_dev_fw_version_get(uint8_t port_id,
      char *fw_version, int fw_length).

v4: - removed deprecation notice
    - renamed API as rte_eth_dev_fw_version_get
    - splited bus info print from this patch set

v3: - changed API, use 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)
    - added statusment in /doc/guides/nics/features/default.ini and
      release_17_02.rst

v2: - fixed commit log

Now, the example ethtool can only show the driver information. From
customers' point of view, it should be better if we can have the same
way that the Linux kernel ethtool does to show firmware version.

These five patches added a new function ``rte_eth_dev_fw_version_get()``
to fetch firmware version related information and implement the
display in example ethtool.

Qiming Yang (5):
  ethdev: add firmware version get
  net/e1000: add firmware version get
  net/ixgbe: add firmware version get
  net/i40e: add firmware version get
  ethtool: display firmware version

 doc/guides/nics/features/default.ini   |  1 +
 doc/guides/nics/features/i40e.ini      |  1 +
 doc/guides/nics/features/igb.ini       |  1 +
 doc/guides/nics/features/ixgbe.ini     |  1 +
 doc/guides/rel_notes/deprecation.rst   |  4 ---
 doc/guides/rel_notes/release_17_02.rst |  5 +++
 drivers/net/e1000/igb_ethdev.c         | 56 ++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.c         | 33 ++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 26 ++++++++++++++++
 examples/ethtool/ethtool-app/ethapp.c  |  1 +
 examples/ethtool/lib/rte_ethtool.c     |  6 ++++
 lib/librte_ether/rte_ethdev.c          | 12 ++++++++
 lib/librte_ether/rte_ethdev.h          | 25 +++++++++++++++
 lib/librte_ether/rte_ether_version.map |  1 +
 14 files changed, 169 insertions(+), 4 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v8 1/5] ethdev: add firmware version get
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484202716-41669-1-git-send-email-qiming.yang@intel.com>

This patch adds a new API 'rte_eth_dev_fw_version_get' for
fetching firmware version by a given device.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/nics/features/default.ini   |  1 +
 doc/guides/rel_notes/deprecation.rst   |  4 ----
 doc/guides/rel_notes/release_17_02.rst |  5 +++++
 lib/librte_ether/rte_ethdev.c          | 12 ++++++++++++
 lib/librte_ether/rte_ethdev.h          | 25 +++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  1 +
 6 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index f1bf9bf..ae40d57 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -50,6 +50,7 @@ Timesync             =
 Basic stats          =
 Extended stats       =
 Stats per queue      =
+FW version           =
 EEPROM dump          =
 Registers dump       =
 Multiprocess aware   =
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 054e2e7..755dc65 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -30,10 +30,6 @@ Deprecation Notices
   ``nb_seg_max`` and ``nb_mtu_seg_max`` providing information about number of
   segments limit to be transmitted by device for TSO/non-TSO packets.
 
-* In 17.02 ABI change is planned: the ``rte_eth_dev_info`` structure
-  will be extended with a new member ``fw_version`` in order to store
-  the NIC firmware version.
-
 * ethdev: an API change is planned for 17.02 for the function
   ``_rte_eth_dev_callback_process``. In 17.02 the function will return an ``int``
   instead of ``void`` and a fourth parameter ``void *ret_param`` will be added.
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 5762d3f..f9134bb 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -66,6 +66,11 @@ New Features
   Support for Mellanox ConnectX-5 family of 10/25/40/50/100 Gbps adapters
   has been added to the existing mlx5 PMD.
 
+* **Added firmware version get API.**
+
+  Added a new function ``rte_eth_dev_fw_version_get()`` to fetch firmware
+  version by a given device.
+
 Resolved Issues
 ---------------
 
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 917557a..89cffcf 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1588,6 +1588,18 @@ rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id,
 			STAT_QMAP_RX);
 }
 
+int
+rte_eth_dev_fw_version_get(uint8_t port_id, char *fw_version, size_t fw_size)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fw_version_get, -ENOTSUP);
+	return (*dev->dev_ops->fw_version_get)(dev, fw_version, fw_size);
+}
+
 void
 rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index ded43d7..a9b3686 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1177,6 +1177,10 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
 typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
 /**< @internal Check DD bit of specific RX descriptor */
 
+typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
+				     char *fw_version, size_t fw_size);
+/**< @internal Get firmware information of an Ethernet device. */
+
 typedef void (*eth_rxq_info_get_t)(struct rte_eth_dev *dev,
 	uint16_t rx_queue_id, struct rte_eth_rxq_info *qinfo);
 
@@ -1459,6 +1463,7 @@ struct eth_dev_ops {
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
 	eth_rxq_info_get_t         rxq_info_get; /**< retrieve RX queue information. */
 	eth_txq_info_get_t         txq_info_get; /**< retrieve TX queue information. */
+	eth_fw_version_get_t       fw_version_get; /**< Get firmware version. */
 	eth_dev_supported_ptypes_get_t dev_supported_ptypes_get;
 	/**< Get packet types supported and identified by device. */
 
@@ -2396,6 +2401,26 @@ void rte_eth_macaddr_get(uint8_t port_id, struct ether_addr *mac_addr);
 void rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info);
 
 /**
+ * Retrieve the firmware version of a device.
+ *
+ * @param port_id
+ *   The port identifier of the device.
+ * @param fw_version
+ *   A array pointer to store the firmware version of a device,
+ *   allocated by caller.
+ * @param fw_size
+ *   The size of the array pointed by fw_version, which should be
+ *   large enough to store firmware version of the device.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if operation is not supported.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-EINVAL) if *fw_size* is not enough to store firmware version.
+ */
+int rte_eth_dev_fw_version_get(uint8_t port_id,
+			       char *fw_version, size_t fw_size);
+
+/**
  * Retrieve the supported packet types of an Ethernet device.
  *
  * When a packet type is announced as supported, it *must* be recognized by
diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map
index 0c2859e..c6c9d0d 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -146,6 +146,7 @@ DPDK_17.02 {
 	global:
 
 	_rte_eth_dev_reset;
+	rte_eth_dev_fw_version_get;
 	rte_flow_create;
 	rte_flow_destroy;
 	rte_flow_flush;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 2/5] net/e1000: add firmware version get
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484202716-41669-1-git-send-email-qiming.yang@intel.com>

This patch adds a new function eth_igb_fw_version_get.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/nics/features/igb.ini |  1 +
 drivers/net/e1000/igb_ethdev.c   | 56 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/doc/guides/nics/features/igb.ini b/doc/guides/nics/features/igb.ini
index 9fafe72..26ae008 100644
--- a/doc/guides/nics/features/igb.ini
+++ b/doc/guides/nics/features/igb.ini
@@ -35,6 +35,7 @@ Packet type parsing  = Y
 Timesync             = Y
 Basic stats          = Y
 Extended stats       = Y
+FW version           = Y
 EEPROM dump          = Y
 Registers dump       = Y
 BSD nic_uio          = Y
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2bb57f5..931992d 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -99,6 +99,8 @@
 #define E1000_VET_VET_EXT            0xFFFF0000
 #define E1000_VET_VET_EXT_SHIFT      16
 
+#define E1000_MIN_FW_VERSION_SIZE    16
+
 static int  eth_igb_configure(struct rte_eth_dev *dev);
 static int  eth_igb_start(struct rte_eth_dev *dev);
 static void eth_igb_stop(struct rte_eth_dev *dev);
@@ -120,6 +122,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 int eth_igb_fw_version_get(struct rte_eth_dev *dev,
+				   char *fw_version, size_t fw_size);
 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);
@@ -391,6 +395,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,
@@ -1984,6 +1989,57 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
 	       offsetof(struct e1000_vf_stats, gprc));
 }
 
+static int
+eth_igb_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
+		       size_t fw_size)
+{
+	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct e1000_fw_version fw;
+
+	if (fw_size < E1000_MIN_FW_VERSION_SIZE) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return -EINVAL;
+	}
+
+	e1000_get_fw_version(hw, &fw);
+
+	switch (hw->mac.type) {
+	case e1000_i210:
+	case e1000_i211:
+		if (!(e1000_get_flash_presence_i210(hw))) {
+			snprintf(fw_version, fw_size,
+				 "%2d.%2d-%d",
+				 fw.invm_major, fw.invm_minor,
+				 fw.invm_img_type);
+			break;
+		}
+		/* fall through */
+	default:
+		/* if option rom is valid, display its version too*/
+		if (fw.or_valid) {
+			snprintf(fw_version, fw_size,
+				 "%d.%d, 0x%08x, %d.%d.%d",
+				 fw.eep_major, fw.eep_minor, fw.etrack_id,
+				 fw.or_major, fw.or_build, fw.or_patch);
+		/* no option rom */
+		} else {
+			if (fw.etrack_id != 0X0000) {
+				snprintf(fw_version, fw_size,
+					 "%d.%d, 0x%08x",
+					 fw.eep_major, fw.eep_minor,
+					 fw.etrack_id);
+			} else {
+				snprintf(fw_version, fw_size,
+					 "%d.%d.%d",
+					 fw.eep_major, fw.eep_minor,
+					 fw.eep_build);
+			}
+		}
+		break;
+	}
+	return 0;
+}
+
 static void
 eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 3/5] net/ixgbe: add firmware version get
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484202716-41669-1-git-send-email-qiming.yang@intel.com>

This patch adds a new function ixgbe_fw_version_get.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/nics/features/ixgbe.ini |  1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/doc/guides/nics/features/ixgbe.ini b/doc/guides/nics/features/ixgbe.ini
index 4a5667f..e7104c2 100644
--- a/doc/guides/nics/features/ixgbe.ini
+++ b/doc/guides/nics/features/ixgbe.ini
@@ -43,6 +43,7 @@ Timesync             = Y
 Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
+FW version           = Y
 EEPROM dump          = Y
 Registers dump       = Y
 Multiprocess aware   = Y
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b7ddd4f..2363eb4 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -163,6 +163,7 @@ enum ixgbevf_xcast_modes {
 #define IXGBE_EXVET_VET_EXT_SHIFT              16
 #define IXGBE_DMATXCTL_VT_MASK                 0xFFFF0000
 
+#define IXGBE_MIN_FW_VERSION_SIZE              11
 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_dev_configure(struct rte_eth_dev *dev);
@@ -193,6 +194,8 @@ static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
 					     uint8_t is_rx);
+static int ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
+				 size_t fw_size);
 static void ixgbe_dev_info_get(struct rte_eth_dev *dev,
 			       struct rte_eth_dev_info *dev_info);
 static const uint32_t *ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
@@ -532,6 +535,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_reset         = ixgbe_dev_xstats_reset,
 	.xstats_get_names     = ixgbe_dev_xstats_get_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
+	.fw_version_get       = ixgbe_fw_version_get,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
 	.mtu_set              = ixgbe_dev_mtu_set,
@@ -3022,6 +3026,28 @@ ixgbevf_dev_stats_reset(struct rte_eth_dev *dev)
 	hw_stats->vfgotc = 0;
 }
 
+static int
+ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u16 eeprom_verh, eeprom_verl;
+	u32 etrack_id;
+
+	if (fw_size < IXGBE_MIN_FW_VERSION_SIZE) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return -EINVAL;
+	}
+
+	ixgbe_read_eeprom(hw, 0x2e, &eeprom_verh);
+	ixgbe_read_eeprom(hw, 0x2d, &eeprom_verl);
+
+	etrack_id = (eeprom_verh << 16) | eeprom_verl;
+	snprintf(fw_version, fw_size,
+		 "0x%08x", etrack_id);
+
+	return 0;
+}
+
 static void
 ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 4/5] net/i40e: add firmware version get
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484202716-41669-1-git-send-email-qiming.yang@intel.com>

This patch add a new function i40e_fw_version_get.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/nics/features/i40e.ini |  1 +
 drivers/net/i40e/i40e_ethdev.c    | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/doc/guides/nics/features/i40e.ini b/doc/guides/nics/features/i40e.ini
index 0d143bc..0dbc3c3 100644
--- a/doc/guides/nics/features/i40e.ini
+++ b/doc/guides/nics/features/i40e.ini
@@ -39,6 +39,7 @@ Packet type parsing  = Y
 Timesync             = Y
 Basic stats          = Y
 Extended stats       = Y
+FW version           = Y
 Multiprocess aware   = Y
 BSD nic_uio          = Y
 Linux UIO            = Y
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 46def56..81a9f1d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -231,6 +231,8 @@
 #define I40E_INSET_IPV6_HOP_LIMIT_MASK  0x000CFF00UL
 #define I40E_INSET_IPV6_NEXT_HDR_MASK   0x000C00FFUL
 
+#define I40E_MIN_FW_VERSION_SIZE        16
+
 /* PCI offset for querying capability */
 #define PCI_DEV_CAP_REG            0xA4
 /* PCI offset for enabling/disabling Extended Tag */
@@ -266,6 +268,8 @@ static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
 					    uint16_t queue_id,
 					    uint8_t stat_idx,
 					    uint8_t is_rx);
+static int i40e_fw_version_get(struct rte_eth_dev *dev,
+				char *fw_version, size_t fw_size);
 static void i40e_dev_info_get(struct rte_eth_dev *dev,
 			      struct rte_eth_dev_info *dev_info);
 static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
@@ -458,6 +462,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.stats_reset                  = i40e_dev_stats_reset,
 	.xstats_reset                 = i40e_dev_stats_reset,
 	.queue_stats_mapping_set      = i40e_dev_queue_stats_mapping_set,
+	.fw_version_get               = i40e_fw_version_get,
 	.dev_infos_get                = i40e_dev_info_get,
 	.dev_supported_ptypes_get     = i40e_dev_supported_ptypes_get,
 	.vlan_filter_set              = i40e_vlan_filter_set,
@@ -2770,6 +2775,34 @@ i40e_dev_queue_stats_mapping_set(__rte_unused struct rte_eth_dev *dev,
 	return -ENOSYS;
 }
 
+static int
+i40e_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	u32 full_ver;
+	u8 ver, patch;
+	u16 build;
+
+	if (fw_size < I40E_MIN_FW_VERSION_SIZE) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return -EINVAL;
+	}
+
+	full_ver = hw->nvm.oem_ver;
+	ver = (u8)(full_ver >> 24);
+	build = (u16)((full_ver >> 8) & 0xffff);
+	patch = (u8)(full_ver & 0xff);
+
+	snprintf(fw_version, fw_size,
+		 "%d.%d%d 0x%08x %d.%d.%d",
+		 ((hw->nvm.version >> 12) & 0xf),
+		 ((hw->nvm.version >> 4) & 0xff),
+		 (hw->nvm.version & 0xf), hw->nvm.eetrack,
+		 ver, build, patch);
+
+	return 0;
+}
+
 static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 5/5] ethtool: display firmware version
From: Qiming Yang @ 2017-01-12  6:31 UTC (permalink / raw)
  To: dev, ferruh.yigit; +Cc: remy.horton, Qiming Yang
In-Reply-To: <1484202716-41669-1-git-send-email-qiming.yang@intel.com>

This patch enhances the ethtool example to support to show
firmware version, in the same way that the Linux kernel
ethtool does.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Remy Horton <remy.horton@intel.com>
---
 examples/ethtool/ethtool-app/ethapp.c | 1 +
 examples/ethtool/lib/rte_ethtool.c    | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/examples/ethtool/ethtool-app/ethapp.c b/examples/ethtool/ethtool-app/ethapp.c
index 6aeaa06..85c31ac 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -185,6 +185,7 @@ pcmd_drvinfo_callback(__rte_unused void *ptr_params,
 		printf("Port %i driver: %s (ver: %s)\n",
 			id_port, info.driver, info.version
 		      );
+		printf("firmware-version: %s\n", info.fw_version);
 	}
 }
 
diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c
index b1f159e..33d38a7 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -51,12 +51,18 @@ rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo)
 	struct rte_eth_dev_info dev_info;
 	struct rte_dev_reg_info reg_info;
 	int n;
+	int ret;
 
 	if (drvinfo == NULL)
 		return -EINVAL;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 
+	ret = rte_eth_dev_fw_version_get(port_id, drvinfo->fw_version,
+			      sizeof(drvinfo->fw_version));
+	if (ret != 0)
+		printf("firmware version get error: (%s)\n", strerror(-ret));
+
 	memset(&dev_info, 0, sizeof(dev_info));
 	rte_eth_dev_info_get(port_id, &dev_info);
 
-- 
2.7.4

^ permalink raw reply related

* Re: Port stats zero when using MLX5 DPDK driver
From: Shahaf Shuler @ 2017-01-12  7:34 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev@dpdk.org, george.dit@gmail.com
In-Reply-To: <1660469.qnTIcQ9A6p@xps13>



--Shahaf


-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] 
Sent: Wednesday, January 11, 2017 3:47 PM
To: Shahaf Shuler <shahafs@mellanox.com>
Cc: dev@dpdk.org; george.dit@gmail.com
Subject: Re: [dpdk-dev] Port stats zero when using MLX5 DPDK driver

> > On Mon, Jan 9, 2017 at 2:32 PM, Shahaf Shuler wrote:
> > It is not support on Mellanox PMD to read the primary process 
> > counters from a secondary process.

It is a pity that such a basic feature is not supported.
We should try to have this kind of feature better supported across every drivers.
[Shahaf Shuler] there is a patch we are pushing which will enable to read the xstats from a secondary process:
[PATCH] net/mlx5: support extended statistics


2017-01-10 08:43, Shahaf Shuler:
> supporting this functionality is not on the plans.

Please could you re-consider the plans? It should not be so difficult to give access to the stats from a secondary process.
[Shahaf Shuler] DPDK secondary process much conflict with Mellanox Arch. we will put this task on our plans.



Thanks


> If you wish to read statistics of a running process you can use ethtool –S <device_name>.
> It will provide you the statistics of the port.
> Note that those statistics count the number of bytes/packet which were 
> received/sent by the port. This number may not be equal to the number 
> of packet/bytes which were send/received on the PMD.


^ permalink raw reply

* [PATCH] app/testpmd: fix static build link ordering
From: Jerin Jacob @ 2017-01-12  7:46 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Jerin Jacob, stable

By introducing explicit -lrte_pmd_ixgbe link request in
testpmd Makefile,"-Wl,-lrte_pmd_ixgbe" provided twice, and linker
removes the duplication by keeping only first occurrence.
This moves "-Wl,-lrte_pmd_ixgbe" out of "-Wl,--whole-archive" flag
and makes symbol generation totally different than previous version
in case of static build.
This patch fixes the static build linking order by introducing
-lrte_pmd_ixgbe under the shared library config
(CONFIG_RTE_BUILD_SHARED_LIB).

Fixes: 425781ff5afe ("app/testpmd: add ixgbe VF management")

CC: stable@dpdk.org
Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
---
 app/test-pmd/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile
index 5988c3e..050663a 100644
--- a/app/test-pmd/Makefile
+++ b/app/test-pmd/Makefile
@@ -59,7 +59,9 @@ SRCS-y += csumonly.c
 SRCS-y += icmpecho.c
 SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c
 
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe
+endif
 
 CFLAGS_cmdline.o := -D_GNU_SOURCE
 
-- 
2.5.5

^ permalink raw reply related

* [PATCH v2] net/mlx5: support extended statistics
From: Shahaf Shuler @ 2017-01-12  8:08 UTC (permalink / raw)
  To: adrien.mazarguil; +Cc: dev, Elad Persiko, Hanoch Haim

Implement xstats_*() DPDK callbacks

Signed-off-by: Shahaf Shuler <shahafs@mellanox.com>
Signed-off-by: Elad Persiko <eladpe@mellanox.com>
Signed-off-by: Hanoch Haim <hhaim@cisco.com>
---
 drivers/net/mlx5/mlx5.c         |   3 +
 drivers/net/mlx5/mlx5.h         |  15 ++
 drivers/net/mlx5/mlx5_defs.h    |   3 +
 drivers/net/mlx5/mlx5_stats.c   | 324 ++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_trigger.c |   1 +
 5 files changed, 346 insertions(+)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 55c5b87..11ef301 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -202,6 +202,9 @@
 	.link_update = mlx5_link_update,
 	.stats_get = mlx5_stats_get,
 	.stats_reset = mlx5_stats_reset,
+	.xstats_get = mlx5_xstats_get,
+	.xstats_reset = mlx5_xstats_reset,
+	.xstats_get_names = mlx5_xstats_get_names,
 	.dev_infos_get = mlx5_dev_infos_get,
 	.dev_supported_ptypes_get = mlx5_dev_supported_ptypes_get,
 	.vlan_filter_set = mlx5_vlan_filter_set,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index a163983..27bb01c 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -89,6 +89,14 @@ enum {
 	PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF = 0x101a,
 };
 
+struct mlx5_xstats_ctrl {
+	/* Number of device stats. */
+	uint16_t stats_n;
+	/* Index in the device counters table. */
+	uint16_t dev_table_idx[MLX5_MAX_XSTATS];
+	uint64_t base[MLX5_MAX_XSTATS];
+};
+
 struct priv {
 	struct rte_eth_dev *dev; /* Ethernet device. */
 	struct ibv_context *ctx; /* Verbs context. */
@@ -143,6 +151,7 @@ struct priv {
 	struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */
 	LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */
 	uint32_t link_speed_capa; /* Link speed capabilities. */
+	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
 	rte_spinlock_t lock; /* Lock for control functions. */
 };
 
@@ -251,8 +260,14 @@ int mlx5_dev_rss_reta_update(struct rte_eth_dev *,
 
 /* mlx5_stats.c */
 
+void priv_xstats_init(struct priv *);
 void mlx5_stats_get(struct rte_eth_dev *, struct rte_eth_stats *);
 void mlx5_stats_reset(struct rte_eth_dev *);
+int mlx5_xstats_get(struct rte_eth_dev *,
+		    struct rte_eth_xstat *, unsigned int);
+void mlx5_xstats_reset(struct rte_eth_dev *);
+int mlx5_xstats_get_names(struct rte_eth_dev *,
+			  struct rte_eth_xstat_name *, unsigned int);
 
 /* mlx5_vlan.c */
 
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index b32816e..beabb70 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -79,4 +79,7 @@
 /* Alarm timeout. */
 #define MLX5_ALARM_TIMEOUT_US 100000
 
+/* Maximum number of extended statistics counters. */
+#define MLX5_MAX_XSTATS 32
+
 #endif /* RTE_PMD_MLX5_DEFS_H_ */
diff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c
index f2b5781..30c5fea 100644
--- a/drivers/net/mlx5/mlx5_stats.c
+++ b/drivers/net/mlx5/mlx5_stats.c
@@ -31,11 +31,16 @@
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+
 /* DPDK headers don't like -pedantic. */
 #ifdef PEDANTIC
 #pragma GCC diagnostic ignored "-Wpedantic"
 #endif
 #include <rte_ethdev.h>
+#include <rte_common.h>
+#include <rte_malloc.h>
 #ifdef PEDANTIC
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
@@ -44,6 +49,251 @@
 #include "mlx5_rxtx.h"
 #include "mlx5_defs.h"
 
+struct mlx5_counter_ctrl {
+	/* Name of the counter. */
+	char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
+	/* Name of the counter on the device table. */
+	char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
+};
+
+static struct mlx5_counter_ctrl mlx5_counters_init[] = {
+	{
+		.dpdk_name = "rx_port_unicast_bytes",
+		.ctr_name = "rx_vport_unicast_bytes",
+	},
+	{
+		.dpdk_name = "rx_port_multicast_bytes",
+		.ctr_name = "rx_vport_multicast_bytes",
+	},
+	{
+		.dpdk_name = "rx_port_broadcast_bytes",
+		.ctr_name = "rx_vport_broadcast_bytes",
+	},
+	{
+		.dpdk_name = "rx_port_unicast_packets",
+		.ctr_name = "rx_vport_unicast_packets",
+	},
+	{
+		.dpdk_name = "rx_port_multicast_packets",
+		.ctr_name = "rx_vport_multicast_packets",
+	},
+	{
+		.dpdk_name = "rx_port_broadcast_packets",
+		.ctr_name = "rx_vport_broadcast_packets",
+	},
+	{
+		.dpdk_name = "tx_port_unicast_bytes",
+		.ctr_name = "tx_vport_unicast_bytes",
+	},
+	{
+		.dpdk_name = "tx_port_multicast_bytes",
+		.ctr_name = "tx_vport_multicast_bytes",
+	},
+	{
+		.dpdk_name = "tx_port_broadcast_bytes",
+		.ctr_name = "tx_vport_broadcast_bytes",
+	},
+	{
+		.dpdk_name = "tx_port_unicast_packets",
+		.ctr_name = "tx_vport_unicast_packets",
+	},
+	{
+		.dpdk_name = "tx_port_multicast_packets",
+		.ctr_name = "tx_vport_multicast_packets",
+	},
+	{
+		.dpdk_name = "tx_port_broadcast_packets",
+		.ctr_name = "tx_vport_broadcast_packets",
+	},
+	{
+		.dpdk_name = "rx_wqe_err",
+		.ctr_name = "rx_wqe_err",
+	},
+	{
+		.dpdk_name = "rx_crc_errors_phy",
+		.ctr_name = "rx_crc_errors_phy",
+	},
+	{
+		.dpdk_name = "rx_in_range_len_errors_phy",
+		.ctr_name = "rx_in_range_len_errors_phy",
+	},
+	{
+		.dpdk_name = "rx_symbol_err_phy",
+		.ctr_name = "rx_symbol_err_phy",
+	},
+	{
+		.dpdk_name = "tx_errors_phy",
+		.ctr_name = "tx_errors_phy",
+	},
+};
+
+static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
+
+/**
+ * Read device counters table.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param[out] stats
+ *   Counters table output buffer.
+ *
+ * @return
+ *   0 on success and stats is filled, negative on error.
+ */
+static int
+priv_read_dev_counters(struct priv *priv, uint64_t *stats)
+{
+	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+	unsigned int i;
+	struct ifreq ifr;
+	unsigned int stats_sz = (xstats_ctrl->stats_n * sizeof(uint64_t)) +
+				 sizeof(struct ethtool_stats);
+	struct ethtool_stats et_stats[(stats_sz + (
+				      sizeof(struct ethtool_stats) - 1)) /
+				      sizeof(struct ethtool_stats)];
+
+	et_stats->cmd = ETHTOOL_GSTATS;
+	et_stats->n_stats = xstats_ctrl->stats_n;
+	ifr.ifr_data = (caddr_t)et_stats;
+	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
+		WARN("unable to read statistic values from device");
+		return -1;
+	}
+	for (i = 0; (i != xstats_n) ; ++i)
+		stats[i] = (uint64_t)
+			   et_stats->data[xstats_ctrl->dev_table_idx[i]];
+	return 0;
+}
+
+/**
+ * Init the structures to read device counters.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ */
+void
+priv_xstats_init(struct priv *priv)
+{
+	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+	unsigned int i;
+	unsigned int j;
+	char ifname[IF_NAMESIZE];
+	struct ifreq ifr;
+	struct ethtool_drvinfo drvinfo;
+	struct ethtool_gstrings *strings = NULL;
+	unsigned int dev_stats_n;
+	unsigned int str_sz;
+
+	if (priv_get_ifname(priv, &ifname)) {
+		WARN("unable to get interface name");
+		return;
+	}
+	/* How many statistics are available. */
+	drvinfo.cmd = ETHTOOL_GDRVINFO;
+	ifr.ifr_data = (caddr_t)&drvinfo;
+	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
+		WARN("unable to get driver info");
+		return;
+	}
+	dev_stats_n = drvinfo.n_stats;
+	if (dev_stats_n < 1) {
+		WARN("no extended statistics available");
+		return;
+	}
+	xstats_ctrl->stats_n = dev_stats_n;
+	/* Allocate memory to grab stat names and values. */
+	str_sz = dev_stats_n * ETH_GSTRING_LEN;
+	strings = (struct ethtool_gstrings *)
+		  rte_malloc("xstats_strings",
+			     str_sz + sizeof(struct ethtool_gstrings), 0);
+	if (!strings) {
+		WARN("unable to allocate memory for xstats");
+		return;
+	}
+	strings->cmd = ETHTOOL_GSTRINGS;
+	strings->string_set = ETH_SS_STATS;
+	strings->len = dev_stats_n;
+	ifr.ifr_data = (caddr_t)strings;
+	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
+		WARN("unable to get statistic names");
+		goto free;
+	}
+	for (j = 0; (j != xstats_n); ++j)
+		xstats_ctrl->dev_table_idx[j] = dev_stats_n;
+	for (i = 0; (i != dev_stats_n); ++i) {
+		const char *curr_string = (const char *)
+			&strings->data[i * ETH_GSTRING_LEN];
+
+		for (j = 0; (j != xstats_n); ++j) {
+			if (!strcmp(mlx5_counters_init[j].ctr_name,
+				    curr_string)) {
+				xstats_ctrl->dev_table_idx[j] = i;
+				break;
+			}
+		}
+	}
+	for (j = 0; (j != xstats_n); ++j) {
+		if (xstats_ctrl->dev_table_idx[j] >= dev_stats_n) {
+			WARN("Counters %s is not recognized",
+			     mlx5_counters_init[j].dpdk_name);
+			goto free;
+		}
+	}
+	/* Copy to base at first time. */
+	assert(xstats_n <= MLX5_MAX_XSTATS);
+	priv_read_dev_counters(priv, xstats_ctrl->base);
+free:
+	rte_free(strings);
+}
+
+/**
+ * Get device extended statistics.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param[out] stats
+ *   Pointer to rte extended stats table.
+ *
+ * @return
+ *   Number of extended stats on success and stats is filled,
+ *   negative on error.
+ */
+static int
+priv_xstats_get(struct priv *priv, struct rte_eth_xstat *stats)
+{
+	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+	unsigned int i;
+	uint64_t counters[xstats_n];
+
+	if (priv_read_dev_counters(priv, counters) < 0)
+		return -1;
+	for (i = 0; (i != xstats_n) ; ++i) {
+		stats[i].id = i;
+		stats[i].value = (uint64_t)
+				 (counters[i] - xstats_ctrl->base[i]);
+	}
+	return xstats_n;
+}
+
+/**
+ * Reset device extended statistics.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ */
+static void
+priv_xstats_reset(struct priv *priv)
+{
+	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+	unsigned int i;
+	uint64_t counters[xstats_n];
+
+	if (priv_read_dev_counters(priv, counters) < 0)
+		return;
+	for (i = 0; (i != xstats_n) ; ++i)
+		xstats_ctrl->base[i] = counters[i];
+}
+
 /**
  * DPDK callback to get device statistics.
  *
@@ -142,3 +392,77 @@
 #endif
 	priv_unlock(priv);
 }
+
+/**
+ * DPDK callback to get extended device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param[out] stats
+ *   Stats table output buffer.
+ * @param n
+ *   The size of the stats table.
+ *
+ * @return
+ *   Number of xstats on success, negative on failure.
+ */
+int
+mlx5_xstats_get(struct rte_eth_dev *dev,
+		struct rte_eth_xstat *stats, unsigned int n)
+{
+	struct priv *priv = mlx5_get_priv(dev);
+	int ret = xstats_n;
+
+	if (n >= xstats_n && stats) {
+		priv_lock(priv);
+		ret = priv_xstats_get(priv, stats);
+		priv_unlock(priv);
+	}
+	return ret;
+}
+
+/**
+ * DPDK callback to clear device extended statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+void
+mlx5_xstats_reset(struct rte_eth_dev *dev)
+{
+	struct priv *priv = mlx5_get_priv(dev);
+
+	priv_lock(priv);
+	priv_xstats_reset(priv);
+	priv_unlock(priv);
+}
+
+/**
+ * DPDK callback to retrieve names of extended device statistics
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param[out] xstats_names
+ *   Buffer to insert names into.
+ * @param n
+ *   Number of names.
+ *
+ * @return
+ *   Number of xstats names.
+ */
+int
+mlx5_xstats_get_names(struct rte_eth_dev *dev,
+		struct rte_eth_xstat_name *xstats_names, unsigned int n)
+{
+	struct priv *priv = mlx5_get_priv(dev);
+	unsigned int i;
+
+	if (n >= xstats_n && xstats_names) {
+		priv_lock(priv);
+		for (i = 0; (i != xstats_n) ; ++i)
+			strcpy(xstats_names[i].name,
+			       mlx5_counters_init[i].dpdk_name);
+		priv_unlock(priv);
+	}
+	return xstats_n;
+}
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index 2399243..30addd2 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -91,6 +91,7 @@
 		priv_fdir_enable(priv);
 	priv_dev_interrupt_handler_install(priv, dev);
 	err = priv_flow_start(priv);
+	priv_xstats_init(priv);
 	priv_unlock(priv);
 	return -err;
 }
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v3 00/18] net/ixgbe: Consistent filter API
From: Wei Zhao @ 2017-01-12  8:12 UTC (permalink / raw)
  To: dev
In-Reply-To: <1483084390-53159-2-git-send-email-wei.zhao1@intel.com>

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.

v2 changes:
 fix git log error
 Modify some function call relationship
 Change return value type of all parse flow functions
 Update error info for all flow ops
 Add ixgbe_filterlist_flush to flush flows and rules created

v3 change:
 add new file ixgbe_flow.c to store generic API parser related functions
 add more comment about pattern and action rules
 add attr check in parser functions
 change struct name ixgbe_flow to rte_flow
 change SYN to TCP SYN
 change to use memset initizlize struct ixgbe_filter_info
 break down filter uninit process to 3 indepedent functions in eth_ixgbe_dev_uninit()
 change struct rte_flow_item_nvgre definition
 change struct rte_flow_item_e_tag definition
 fix one bug in function ixgbe_dev_filter_ctrl
 add goto in function ixgbe_flow_create
 delete some useless initialization 
 eliminate some git log check warning

zhao wei (18):
  net/ixgbe: store TCP SYN filter
  net/ixgbe: store flow director filter
  net/ixgbe: store L2 tunnel filter
  net/ixgbe: restore n-tuple filter Add support for restoring n-tuple
    filter in SW.
  net/ixgbe: restore ether type filter
  net/ixgbe: restore TCP SYN filter
  net/ixgbe: restore flow director filter
  net/ixgbe: restore L2 tunnel filter
  net/ixgbe: store and restore L2 tunnel configuration
  net/ixgbe: flush all the filters
  net/ixgbe: parse n-tuple filter
  net/ixgbe: parse ethertype filter
  net/ixgbe: parse TCP SYN filter     check if the rule is a TCP SYN
    rule, and get the SYN info.
  net/ixgbe: parse L2 tunnel filter     check if the rule is a L2 tunnel
    rule, and get the L2 tunnel info.
  net/ixgbe: parse flow director filter
  net/ixgbe: create consistent filter
  net/ixgbe: destroy consistent filter
  net/ixgbe: flush all the filter list

 drivers/net/ixgbe/Makefile       |    2 +
 drivers/net/ixgbe/ixgbe_ethdev.c |  667 +++++++--
 drivers/net/ixgbe/ixgbe_ethdev.h |  203 ++-
 drivers/net/ixgbe/ixgbe_fdir.c   |  407 ++++--
 drivers/net/ixgbe/ixgbe_flow.c   | 2811 ++++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_pf.c     |   26 +-
 lib/librte_ether/rte_flow.h      |   48 +
 7 files changed, 3953 insertions(+), 211 deletions(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_flow.c

-- 
2.5.5

^ permalink raw reply

* [PATCH v3 01/18] net/ixgbe: store TCP SYN filter
From: Wei Zhao @ 2017-01-12  8:13 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Wei Zhao
In-Reply-To: <1483084390-53159-2-git-send-email-wei.zhao1@intel.com>

Add support for storing TCP SYN filter in SW.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 18 +++++++++++++-----
 drivers/net/ixgbe/ixgbe_ethdev.h |  2 ++
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index b7ddd4f..719eddd 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1272,10 +1272,12 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
+	/* initialize filter info */
+	memset(filter_info, 0,
+	       sizeof(struct ixgbe_filter_info));
+
 	/* initialize 5tuple filter list */
 	TAILQ_INIT(&filter_info->fivetuple_list);
-	memset(filter_info->fivetuple_mask, 0,
-	       sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE);
 
 	return 0;
 }
@@ -5603,15 +5605,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);
@@ -5621,10 +5626,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 69b276f..90a89ec 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 related

* [PATCH v3 02/18] net/ixgbe: store flow director filter
From: Wei Zhao @ 2017-01-12  8:13 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Wei Zhao
In-Reply-To: <1484208838-58734-1-git-send-email-wei.zhao1@intel.com>

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>
---
 drivers/net/ixgbe/ixgbe_ethdev.c |  64 ++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_ethdev.h |  19 ++++++-
 drivers/net/ixgbe/ixgbe_fdir.c   | 105 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 719eddd..9796c4f 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,8 @@ 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_fdir_filter_uninit(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);
@@ -1279,6 +1282,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	/* initialize 5tuple filter list */
 	TAILQ_INIT(&filter_info->fivetuple_list);
 
+	/* initialize flow director filter list & hash */
+	ixgbe_fdir_filter_init(eth_dev);
+
 	return 0;
 }
 
@@ -1320,9 +1326,67 @@ 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 */
+	ixgbe_fdir_filter_uninit(eth_dev);
+
 	return 0;
 }
 
+static int ixgbe_fdir_filter_uninit(struct rte_eth_dev *eth_dev)
+{
+	struct ixgbe_hw_fdir_info *fdir_info =
+		IXGBE_DEV_PRIVATE_TO_FDIR_INFO(eth_dev->data->dev_private);
+	struct ixgbe_fdir_filter *fdir_filter;
+
+		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 90a89ec..300542e 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..8bf5705 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;
+
+	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;
+
+	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;
+	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 related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox