DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v9 01/26] net/i40e: support link status notification
From: Vincent JARDIN @ 2017-01-15 23:35 UTC (permalink / raw)
  To: Wenzhuo Lu; +Cc: dev
In-Reply-To: <1484290401-1404-2-git-send-email-wenzhuo.lu@intel.com>

Le 13/01/2017 à 07:52, Wenzhuo Lu a écrit :
> + * @b EXPERIMENTAL: this API may change without prior notice

a minor comment here:
   + including be removed.

^ permalink raw reply

* Re: [PATCH v9 00/26] Support VFD on i40e - EXPERIMENTAL
From: Vincent JARDIN @ 2017-01-15 23:52 UTC (permalink / raw)
  To: Ferruh Yigit, Wenzhuo Lu, dev; +Cc: Zhang, Helin, John Fastabend
In-Reply-To: <58027303-afeb-e21b-3820-cc7422e28d74@intel.com>

Le 13/01/2017 à 19:32, Ferruh Yigit a écrit :
>> Please aware VFD is an EXPERIMENTAL feature, it can be changed or even
>> removed without prior notice.
>>
> So new version sent with a experimental tag, this can provide some
> flexibility to the feature until proper DPDK PF discussion concluded.
>
> Is there any objection to the patchset with experimental tag?
>
> Hi Vincent,
>
> Can this be interim solution until your concerns addressed?
>
> If so, I will proceed working on getting patch into next-net.
>

I agree that the experimental status is a better option. It shall remain 
experimental till both:
   a- we agree that DPDK could be used as a PF, which I do not believe 
is a good option, it has been argued within previous email, but let's 
keep thinking about it ;
   b- assuming a-, the kernel includes exactly the same definition of 
messages+features for its PF.

The VF messages and PF messages shall remain with the experimental 
status for any x message that is not supported by the kernel's PF.

The PF side of the DPDK implementation may be removed some days.

Series-Acked-By: Vincent Jardin <vincent.jardin@6wind.com>

^ permalink raw reply

* Re: [PATCH v9 01/26] net/i40e: support link status notification
From: Lu, Wenzhuo @ 2017-01-16  0:42 UTC (permalink / raw)
  To: Vincent JARDIN; +Cc: dev@dpdk.org
In-Reply-To: <f89eb32a-0ab2-ee11-16d0-88fe89c89311@6wind.com>

Hi Vincent,

> -----Original Message-----
> From: Vincent JARDIN [mailto:vincent.jardin@6wind.com]
> Sent: Monday, January 16, 2017 7:35 AM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v9 01/26] net/i40e: support link status
> notification
> 
> Le 13/01/2017 à 07:52, Wenzhuo Lu a écrit :
> > + * @b EXPERIMENTAL: this API may change without prior notice
> 
> a minor comment here:
>    + including be removed.
Sure, will add it.

^ permalink raw reply

* Re: [PATCH v2 0/4] enhancement to i40e PF host driver
From: Zhang, Helin @ 2017-01-16  0:55 UTC (permalink / raw)
  To: Chen, Jing D, dev@dpdk.org
In-Reply-To: <1484277201-5930-1-git-send-email-jing.d.chen@intel.com>

Acked-by: Helin Zhang <helin.zhang@intel.com>

-----Original Message-----
From: Chen, Jing D 
Sent: Friday, January 13, 2017 11:13 AM
To: dev@dpdk.org
Cc: daniels@research.att.com; Zhang, Helin <helin.zhang@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>; vincent.jardin@6wind.com; Wu, Jingjing <jingjing.wu@intel.com>; Chen, Jing D <jing.d.chen@intel.com>
Subject: [PATCH v2 0/4] enhancement to i40e PF host driver

v2:
- add macro to replace numeric
- rework comments

Current PF host driver can serve DPDK VF well, but the implementation is not complete to support Linux VF, even both DPDK VF and Linux VF use same API set.

Note that the patch are experimental for use and might be removed without prior notice.

This patch set made below changes:
1. Make an enhancement on interface to serve VF, so
   both Linux and DPDK VF can be well served.
2. Change API version number so both DPDK and Linux
   VF can recognize and select proper command and
   data structure to request service. But the
   sacrifice is DPDK VF can't identify host driver
   (Linux or DPDK) and extended function provided
   in DPDK PF host driver can't be used.
   This situation will change after negotiate with
   Linux maintainer to provide a better mechanism
   to identify both PF and VF function.

Chen Jing D(Mark) (4):
  net/i40e: change version number to support Linux VF
  net/i40e: return correct VSI id
  net/i40e: parse more VF parameter and configure
  net/i40e: support Linux VF to configure IRQ link list

 drivers/net/i40e/i40e_pf.c |  171 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 153 insertions(+), 18 deletions(-)

--
1.7.7.6

^ permalink raw reply

* Re: [PATCH v5] app/testpmd: supported offload capabilities query
From: Yang, Qiming @ 2017-01-16  2:00 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev@dpdk.org; +Cc: Lu, Wenzhuo
In-Reply-To: <F5DF4F0E3AFEF648ADC1C3C33AD4DBF16EDCC328@SHSMSX101.ccr.corp.intel.com>

Hi, Pablo
I have checked with Wenzhuo, this capability has no way to disable and is always enable if NIC have this capability.
So I'll change the print to " RX Outer IPv4 checksum:        on".

-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Yang, Qiming
Sent: Saturday, January 14, 2017 11:06 AM
To: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; dev@dpdk.org
Cc: Lu, Wenzhuo <wenzhuo.lu@intel.com>
Subject: Re: [dpdk-dev] [PATCH v5] app/testpmd: supported offload capabilities query

HI, Pablo

> ...
> 
> > +
> > +	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:        ");
> 
> Missing on/off?
> Qiming: I didn't find any switch for this feature in DPDK now. I'll 
> fix the format problem. Thank you.

I just saw your v6. So, what does this mean? If the device is capable of doing this, but there is no way to enable/disable it, it would mean that it will be enabled or disabled by default, right?

I see that X550 NIC is the only one capable of this. Maybe Wenzhuo can help on clarifying this.

I would say that, if it is enabled when it is capable, then you should print "on", But printing only "RX Outer IPv4 checksum" does not give any information (when all the rest of the capabilities show on/off).

Qiming: Ok, I'll check with Wenzhuo, Thank you for your advice for the unsuitable print in this place .

Thanks,
Pablo
 

^ permalink raw reply

* Re: [PATCH v7 2/6] ethdev: add event type for MACsec
From: Ananyev, Konstantin @ 2017-01-16  2:31 UTC (permalink / raw)
  To: Bie, Tiwei, dev@dpdk.org
  Cc: adrien.mazarguil@6wind.com, Lu, Wenzhuo, Mcnamara, John,
	olivier.matz@6wind.com, thomas.monjalon@6wind.com, Zhang, Helin,
	Dai, Wei, Wang, Xiao W
In-Reply-To: <1484306501-164565-3-git-send-email-tiwei.bie@intel.com>



> 
> This commit adds a below event type:
> 
> - RTE_ETH_EVENT_MACSEC
> 
> This event will occur when the PN counter in a MACsec connection
> reaches the exhaustion threshold.
> 
> Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 1c356c1..d5d2956 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -3188,6 +3188,7 @@ enum rte_eth_event_type {
>  	RTE_ETH_EVENT_INTR_RESET,
>  			/**< reset interrupt event, sent to VF on PF reset */
>  	RTE_ETH_EVENT_VF_MBOX,  /**< message from the VF received by PF */
> +	RTE_ETH_EVENT_MACSEC,   /**< MACsec offload related event */
>  	RTE_ETH_EVENT_MAX       /**< max value of this enum */
>  };
> 
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.7.4

^ permalink raw reply

* Re: [PATCH v7 3/6] ethdev: add MACsec offload capability flags
From: Ananyev, Konstantin @ 2017-01-16  2:33 UTC (permalink / raw)
  To: Bie, Tiwei, dev@dpdk.org
  Cc: adrien.mazarguil@6wind.com, Lu, Wenzhuo, Mcnamara, John,
	olivier.matz@6wind.com, thomas.monjalon@6wind.com, Zhang, Helin,
	Dai, Wei, Wang, Xiao W
In-Reply-To: <1484306501-164565-4-git-send-email-tiwei.bie@intel.com>



> 
> If these flags are advertised by a PMD, the NIC supports the MACsec
> offload. The incoming MACsec traffics can be offloaded transparently
> after the MACsec offload is configured correctly by the application.
> And the application can set the PKT_TX_MACSEC flag in mbufs to enable
> the MACsec offload for the packets to be transmitted.
> 
> Signed-off-by: Tiwei Bie <tiwei.bie@intel.com>
> ---

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

^ permalink raw reply

* [PATCH v7] app/testpmd: supported offload capabilities query
From: Qiming Yang @ 2017-01-16  2:31 UTC (permalink / raw)
  To: dev; +Cc: Qiming Yang
In-Reply-To: <1484309859-57852-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.
v6 changes:
* fixed format problems.
v7  changes:
* show the default status of 'RX Outer IPV4 checksum'.
---
 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..5938daa 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..b7ab635 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:        on");
+
+	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 v3 11/29] eal: generic implementation for I/O device read/write access
From: Jerin Jacob @ 2017-01-16  3:26 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, konstantin.ananyev, bruce.richardson, jianbo.liu, viktorin,
	santosh.shukla
In-Reply-To: <2622450.7mMCSCBjjk@xps13>

On Sun, Jan 15, 2017 at 10:29:42PM +0100, Thomas Monjalon wrote:
> 2017-01-12 14:47, Jerin Jacob:
> > +#define rte_read8_relaxed(addr) \
> > +	({ uint8_t __v = *(const volatile uint8_t *)addr; __v; })
> 
> Why do you prefer a macro over an inline function?

In this case, I thought of avoiding any compiler behavior changes when
adding the new EAL APIs. Earlier, drivers were using direct pointer
dereference in code, I thought of using the macro to just substitute that to avoid
any performance regression due to this change for easy patchset acceptance.

IMO, One line macros are OK and for this specific case Linux also uses
readl/writel as macros.

Having said that, If you think it needs to be changed to "static inline", I
am fine with that. Let me know.

> It won't provide the same "debuggability".

^ permalink raw reply

* Re: [PATCH v4 4/5] doc: add EFD library section in Programmers guide
From: Jerin Jacob @ 2017-01-16  4:15 UTC (permalink / raw)
  To: Pablo de Lara; +Cc: dev, Sameh Gobriel
In-Reply-To: <1484481875-126335-5-git-send-email-pablo.de.lara.guarch@intel.com>

On Sun, Jan 15, 2017 at 12:04:34PM +0000, Pablo de Lara wrote:
> Signed-off-by: Sameh Gobriel <sameh.gobriel@intel.com>
> Acked-by: Christian Maciocco <christian.maciocco@intel.com>

Looks like trailing white space error on git am. Please check it

➜ [dpdk] $ pwclient git-am 19363
Applying patch #19363 using 'git am'
Description: [dpdk-dev,v4,4/5] doc: add EFD library section in
Programmers guide
Applying: doc: add EFD library section in Programmers guide
/export/upstream/dpdk/.git/rebase-apply/patch:342: trailing whitespace.
``rte_efd_delete()`` can be used. The function returns zero upon success 
warning: 1 line adds whitespace errors.

^ permalink raw reply

* Re: [PATCH v4 1/5] efd: new Elastic Flow Distributor library
From: Jerin Jacob @ 2017-01-16  4:25 UTC (permalink / raw)
  To: Pablo de Lara; +Cc: dev, Byron Marohn, Saikrishna Edupuganti
In-Reply-To: <1484481875-126335-2-git-send-email-pablo.de.lara.guarch@intel.com>

On Sun, Jan 15, 2017 at 12:04:31PM +0000, Pablo de Lara wrote:
> Elastic Flow Distributor (EFD) is a distributor library that uses
> perfect hashing to determine a target/value for a given incoming flow key.
> It has the following advantages:
> 
> - First, because it uses perfect hashing, it does not store
>   the key itself and hence lookup performance is not dependent
>   on the key size.
> 
> - Second, the target/value can be any arbitrary value hence
>   the system designer and/or operator can better optimize service rates
>   and inter-cluster network traffic locating.
> 
> - Third, since the storage requirement is much smaller than a hash-based
>   flow table (i.e. better fit for CPU cache), EFD can scale to
>   millions of flow keys.
>   Finally, with current optimized library implementation performance
>   is fully scalable with number of CPU cores.
> 
> Signed-off-by: Byron Marohn <byron.marohn@intel.com>
> Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> Signed-off-by: Saikrishna Edupuganti <saikrishna.edupuganti@intel.com>
> Acked-by: Christian Maciocco <christian.maciocco@intel.com>
> ---
> +#if (RTE_EFD_VALUE_NUM_BITS == 8 || RTE_EFD_VALUE_NUM_BITS == 16 || \
> +	RTE_EFD_VALUE_NUM_BITS == 24 || RTE_EFD_VALUE_NUM_BITS == 32)
> +#define EFD_LOAD_SI128(val) _mm_load_si128(val)
> +#else
> +#define EFD_LOAD_SI128(val) _mm_lddqu_si128(val)
> +#endif
> +
> +static inline efd_value_t
> +efd_lookup_internal(const struct efd_online_group_entry * const group,
> +		const uint32_t hash_val_a, const uint32_t hash_val_b,
> +		enum rte_efd_compare_function cmp_fn)
> +{
> +	efd_value_t value = 0;
> +	uint32_t i;
> +
> +	switch (cmp_fn) {
> +#ifdef RTE_MACHINE_CPUFLAG_AVX2
> +	case RTE_HASH_COMPARE_AVX2:
> +
> +		i = 0;
> +		__m256i vhash_val_a = _mm256_set1_epi32(hash_val_a);
> +		__m256i vhash_val_b = _mm256_set1_epi32(hash_val_b);
> +

Could you please abstract and move SIMD specific code to another file like other
libraries(example: lib_acl) to enable smooth integration with neon and altivec
SIMD implementations in future.

> +		for (; i < RTE_EFD_VALUE_NUM_BITS; i += 8) {
> +			__m256i vhash_idx =
> +					_mm256_cvtepu16_epi32(EFD_LOAD_SI128(
> +					(__m128i const *) &group->hash_idx[i]));
> +			__m256i vlookup_table = _mm256_cvtepu16_epi32(
> +					EFD_LOAD_SI128((__m128i const *)
> +					&group->lookup_table[i]));
> +			__m256i vhash = _mm256_add_epi32(vhash_val_a,
> +					_mm256_mullo_epi32(vhash_idx, vhash_val_b));
> +			__m256i vbucket_idx = _mm256_srli_epi32(vhash,
> +					EFD_LOOKUPTBL_SHIFT);
> +			__m256i vresult = _mm256_srlv_epi32(vlookup_table,
> +					vbucket_idx);
> +
> +			value |= (_mm256_movemask_ps(
> +				(__m256) _mm256_slli_epi32(vresult, 31))
> +				& ((1 << (RTE_EFD_VALUE_NUM_BITS - i)) - 1)) << i;
> +		}
> +		break;
> +#endif

^ permalink raw reply

* [PATCH v9 0/5] new API 'rte_eth_dev_fw_version_get'
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484202716-41669-2-git-send-email-qiming.yang@intel.com>

v9: - when fw_size is insufficient, return the size of the non truncated
      string as snprintf does.

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         | 32 +++++++++++++++++++
 drivers/net/ixgbe/ixgbe_ethdev.c       | 25 +++++++++++++++
 examples/ethtool/ethtool-app/ethapp.c  |  1 +
 examples/ethtool/lib/rte_ethtool.c     |  9 ++++++
 lib/librte_ether/rte_ethdev.c          | 12 ++++++++
 lib/librte_ether/rte_ethdev.h          | 26 ++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  1 +
 14 files changed, 171 insertions(+), 4 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v9 1/5] ethdev: add firmware version get
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484545498-33882-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          | 26 ++++++++++++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  1 +
 6 files changed, 45 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..37a55ef 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,27 @@ 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.
+ *   - (>0) if *fw_size* is not enough to store firmware version, return
+ *          the size of the non truncated string.
+ */
+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 v9 2/5] net/e1000: add firmware version get
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484545498-33882-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..a96d562 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 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 +393,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 +1987,59 @@ 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;
+	int ret;
+
+	e1000_get_fw_version(hw, &fw);
+
+	switch (hw->mac.type) {
+	case e1000_i210:
+	case e1000_i211:
+		if (!(e1000_get_flash_presence_i210(hw))) {
+			ret = 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) {
+			ret = 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) {
+				ret = snprintf(fw_version, fw_size,
+					 "%d.%d, 0x%08x",
+					 fw.eep_major, fw.eep_minor,
+					 fw.etrack_id);
+			} else {
+				ret = snprintf(fw_version, fw_size,
+					 "%d.%d.%d",
+					 fw.eep_major, fw.eep_minor,
+					 fw.eep_build);
+			}
+		}
+		break;
+	}
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (u32)ret) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return ret;
+	} else
+		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 v9 3/5] net/ixgbe: add firmware version get
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484545498-33882-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   | 25 +++++++++++++++++++++++++
 2 files changed, 26 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..fa8ae68 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -193,6 +193,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 +534,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 +3025,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;
+	int ret;
+
+	ixgbe_read_eeprom(hw, 0x2e, &eeprom_verh);
+	ixgbe_read_eeprom(hw, 0x2d, &eeprom_verl);
+
+	etrack_id = (eeprom_verh << 16) | eeprom_verl;
+	ret = snprintf(fw_version, fw_size, "0x%08x", etrack_id);
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (u32)ret) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return ret;
+	} else
+		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 v9 4/5] net/i40e: add firmware version get
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484545498-33882-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    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 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..d55d9d0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -266,6 +266,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 +460,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 +2773,35 @@ 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;
+	int ret;
+
+	full_ver = hw->nvm.oem_ver;
+	ver = (u8)(full_ver >> 24);
+	build = (u16)((full_ver >> 8) & 0xffff);
+	patch = (u8)(full_ver & 0xff);
+
+	ret = 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);
+
+	ret += 1; /* add the size of '\0' */
+	if (fw_size < (u32)ret) {
+		PMD_DRV_LOG(WARNING, "Insufficient fw version buffer size");
+		return ret;
+	} else
+		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 v9 5/5] ethtool: display firmware version
From: Qiming Yang @ 2017-01-16  5:44 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, ferruh.yigit, Qiming Yang
In-Reply-To: <1484545498-33882-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    | 9 +++++++++
 2 files changed, 10 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..cd2f277 100644
--- a/examples/ethtool/lib/rte_ethtool.c
+++ b/examples/ethtool/lib/rte_ethtool.c
@@ -51,12 +51,21 @@ 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));
+	else if (ret > 0)
+		printf("Insufficient fw version buffer size, the minimun size"
+		       "should be %d\n", ret);
+
 	memset(&dev_info, 0, sizeof(dev_info));
 	rte_eth_dev_info_get(port_id, &dev_info);
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v10 09/26] net/i40e: fix VF reset flow
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Qi Zhang, stable
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

From: Qi Zhang <qi.z.zhang@intel.com>

Add missing step during VF reset: PF should
set I40E_VFGEN_RSTAT to ACTIVE at end of the
VF reset operation or VF driver may not able
to detect that reset is already completed.
This patch also remove the unnecessary enum
for vfr state.

Fixes: 4861cde46116 ("i40e: new poll mode driver")

CC: stable@dpdk.org
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 drivers/net/i40e/i40e_pf.c | 6 ++++--
 drivers/net/i40e/i40e_pf.h | 5 -----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index 5c58424..8a6733c 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -139,7 +139,7 @@
 	abs_vf_id = vf_id + hw->func_caps.vf_base_id;
 
 	/* Notify VF that we are in VFR progress */
-	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_INPROGRESS);
+	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_INPROGRESS);
 
 	/*
 	 * If require a SW VF reset, a VFLR interrupt will be generated,
@@ -220,7 +220,7 @@
 	}
 
 	/* Reset done, Set COMPLETE flag and clear reset bit */
-	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_COMPLETED);
+	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_COMPLETED);
 	val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
 	val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
 	I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
@@ -248,6 +248,8 @@
 		return -EFAULT;
 	}
 
+	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_VFACTIVE);
+
 	return ret;
 }
 
diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index 47a9c34..b4c2287 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -48,11 +48,6 @@
 
 #define I40E_DPDK_OFFSET  0x100
 
-enum i40e_pf_vfr_state {
-	I40E_PF_VFR_INPROGRESS = 0,
-	I40E_PF_VFR_COMPLETED = 1,
-};
-
 /* DPDK pf driver specific command to VF */
 enum i40e_virtchnl_ops_dpdk {
 	/*
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 12/26] net/i40e: fix VF MAC address assignment
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Ferruh Yigit, stable
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

From: Ferruh Yigit <ferruh.yigit@intel.com>

If PF sets vf->mac_addr, in VF initialization hw->mac.addr will be set
to that same value. It is possible to check if PF set a MAC address or
not through the hw->mac.addr variable.

hw->mac.addr set by i40e_vf_parse_hw_config(), call stack is:

In PF side
i40e_pf_host_process_cmd_get_vf_resources()
    eth_addr_copy(vf->mac_addr, vf_res->vsi_res[0].default_mac_address)

In VF sise
i40evf_init_vf()
    i40evf_get_vf_resources()
            i40e_vf_parse_hw_config()
                    memcpy(hw->mac.addr, vsi_res->default_mac_addr)

Updated code is after i40evf_get_vf_resources() and can benefit from
hw->mac.addr variable.

Fixes: 89e6b86384bb ("i40evf: rework MAC address validation")

CC: stable@dpdk.org
Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 drivers/net/i40e/i40e_ethdev_vf.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index a9a8bb4..17a035c 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1195,7 +1195,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 	int i, err, bufsz;
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	struct ether_addr *p_mac_addr;
 	uint16_t interval =
 		i40e_calc_itr_interval(I40E_QUEUE_ITR_INTERVAL_MAX);
 
@@ -1272,13 +1271,10 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 	vf->vsi.adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 
 	/* Store the MAC address configured by host, or generate random one */
-	p_mac_addr = (struct ether_addr *)(vf->vsi_res->default_mac_addr);
-	if (is_valid_assigned_ether_addr(p_mac_addr)) { /* Configured by host */
-		ether_addr_copy(p_mac_addr, (struct ether_addr *)hw->mac.addr);
+	if (is_valid_assigned_ether_addr((struct ether_addr *)hw->mac.addr))
 		vf->flags |= I40E_FLAG_VF_MAC_BY_PF;
-	} else {
+	else
 		eth_random_addr(hw->mac.addr); /* Generate a random one */
-	}
 
 	/* If the PF host is not DPDK, set the interval of ITR0 to max*/
 	if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 00/26] Support VFD on i40e - EXPERIMENTAL
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1480637533-37425-1-git-send-email-wenzhuo.lu@intel.com>

1, VF Daemon (VFD)
VFD is an idea to control all the VFs from PF.
As we need to support the scenario kernel PF + DPDK VF, DPDK follows
the interface between kernel PF + kernel VF.
We don't want to introduce too many new messages between PF and VF.
So this patch set adds some new APIs to control VFs directly from PF.
The new APIs include,
1) set VF MAC anti-spoofing
2) set VF VLAN anti-spoofing
3) set TX loopback
4) set VF unicast promiscuous mode
5) set VF multicast promiscuous mode
6) set VF MTU
7) get/reset VF stats
8) set VF MAC address
9) set VF VLAN stripping
10) VF VLAN insertion
12) set VF broadcast mode
13) set VF VLAN tag
14) set VF VLAN filter
VFD also includes VF to PF mailbox message management by APP.
When PF receives mailbox messages from VF, PF should call the
callback provided by APP to know if they're permitted to be
processed.

Please aware VFD is an EXPERIMENTAL feature, it can be changed,
or even removed, without prior notice.

2, Implement VF MAC address setting on VF.

v10:
- some minor change of the doc and comments.
- add the NIC check in the private APIs.

v9:
- upadte the doc and announce VFD is an experimental feature.

v8:
- remove unnecessary VF check.
- add more debug logs.
- split VMDq related code to a separate patch set.
- some minor change.

v7:
- fix 32 bit compile error in patch 23.
- add new patches to configure VMDq.

v6:
- remove the support of DPDK PF + kernel VF. Will create a new patch set for it.
- reword the tittles of some patches.
- add sanity check for vsi, and other minor change.

v5:
- fix testpmd build error(s)
- fix i40e vf_rx_vlan
- remove redundant memset on dev_info
- add functions to .map file sorted

v4:
- rebase on latest next-net
- move patch 10/29 testpmd part to patch 18/29

v3:
- fix issue that VF does not work for i40e
- remove patch for VDMq receive mode init
- move get/reset VF stats API into rte_pmd_i40

v2:
- fix the compile issues.
- fix the checkpatch warning and typo.
- update the commit log of some patches.
- fix the invalid port ID issue of testpmd.


Bernard Iremonger (7):
  net/i40e: set VF VLAN insertion from PF
  net/i40e: set VF broadcast mode from PF
  net/i40e: set VF VLAN tag from PF
  net/i40e: set VF VLAN filter from PF
  app/testpmd: add command to test VF broadcast mode on i40e
  app/testpmd: add command to test VF VLAN tag on i40e
  app/testpmd: handle i40e in VF VLAN filter command

Chen Jing D(Mark) (2):
  net/i40e: set VF VLAN strip from PF
  net/i40e: enhance in sanity check of MAC

Ferruh Yigit (3):
  net/i40e: set VF MAC from PF support
  net/i40e: set VF MAC from VF support
  net/i40e: fix VF MAC address assignment

Qi Zhang (3):
  net/i40e: enable VF MTU change
  net/i40e: fix VF reset flow
  net/i40e: set/clear VF stats from PF

Wenzhuo Lu (11):
  net/i40e: support link status notification
  net/i40e: add callback to user on VF to PF mbox msg
  net/i40e: set VF MAC anti-spoofing from PF
  net/i40e: set VF VLAN anti-spoofing from PF
  net/i40e: set Tx loopback from PF
  net/i40e: set VF unicast promisc mode from PF
  net/i40e: set VF multicast promisc mode from PF
  app/testpmd: use VFD APIs on i40e
  app/testpmd: use unicast promiscuous mode on i40e
  app/testpmd: use multicast promiscuous mode on i40e
  doc: update doc for VFD

 MAINTAINERS                                 |   1 +
 app/test-pmd/Makefile                       |   1 +
 app/test-pmd/cmdline.c                      | 550 ++++++++++++++--
 app/test-pmd/config.c                       |  13 -
 app/test-pmd/testpmd.h                      |   2 -
 doc/guides/nics/i40e.rst                    |   1 +
 doc/guides/rel_notes/release_17_02.rst      |  29 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  32 +
 drivers/net/i40e/Makefile                   |   4 +-
 drivers/net/i40e/i40e_ethdev.c              | 976 +++++++++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h              |   5 +-
 drivers/net/i40e/i40e_ethdev_vf.c           |  82 ++-
 drivers/net/i40e/i40e_pf.c                  | 244 +++++--
 drivers/net/i40e/i40e_pf.h                  |   9 +-
 drivers/net/i40e/rte_pmd_i40e.h             | 335 ++++++++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |  20 +
 16 files changed, 2189 insertions(+), 115 deletions(-)
 create mode 100644 drivers/net/i40e/rte_pmd_i40e.h

Series-Acked-by: Helin Zhang <helin.zhang@intel.com>
Series-Acked-By: Vincent Jardin <vincent.jardin@6wind.com>
-- 
1.9.3

^ permalink raw reply

* [PATCH v10 01/26] net/i40e: support link status notification
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

Add an API to expose the ability, that PF can notify VF
when link status changes, to APP.
So if PF APP doesn't want to enable interruption but check
link status by itself, PF APP can let VF know link status
changed.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 MAINTAINERS                               |  1 +
 drivers/net/i40e/Makefile                 |  4 +-
 drivers/net/i40e/i40e_ethdev.c            | 38 +++++++++++++++++++
 drivers/net/i40e/i40e_pf.c                |  4 +-
 drivers/net/i40e/i40e_pf.h                |  4 +-
 drivers/net/i40e/rte_pmd_i40e.h           | 61 +++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e_version.map |  7 ++++
 7 files changed, 115 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/i40e/rte_pmd_i40e.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f3639f..aa1f261 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -332,6 +332,7 @@ Intel i40e
 M: Helin Zhang <helin.zhang@intel.com>
 M: Jingjing Wu <jingjing.wu@intel.com>
 F: drivers/net/i40e/
+F: drivers/net/i40e/rte_pmd_i40e.h - EXPERIMENTAL
 F: doc/guides/nics/i40e.rst
 F: doc/guides/nics/intel_vf.rst
 
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 89bd85a..94482cf 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -1,6 +1,6 @@
 #   BSD LICENSE
 #
-#   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+#   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
 #   All rights reserved.
 #
 #   Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,8 @@ ifeq ($(findstring RTE_MACHINE_CPUFLAG_SSE4_1,$(CFLAGS)),)
 CFLAGS_i40e_rxtx_vec_sse.o += -msse4.1
 endif
 
+# install this header file
+SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
 
 # this lib depends upon:
 DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 4b148bf..58f9dfa 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -63,6 +63,7 @@
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
 #include "i40e_regs.h"
+#include "rte_pmd_i40e.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -10188,3 +10189,40 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 	i40e_tunnel_filter_restore(pf);
 	i40e_fdir_filter_restore(pf);
 }
+
+static int
+is_i40e_pmd(const char *driver_name)
+{
+	if (!strstr(driver_name, "i40e"))
+		return -ENOTSUP;
+
+	if (strstr(driver_name, "i40e_vf"))
+		return -ENOTSUP;
+
+	return 0;
+}
+
+int
+rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (is_i40e_pmd(dev->data->drv_name))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid argument.");
+		return -EINVAL;
+	}
+
+	i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index ddfc140..f606c2a 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -897,7 +897,7 @@
 	return ret;
 }
 
-static void
+void
 i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
 {
 	struct i40e_virtchnl_pf_event event;
diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
index cddc45c..47a9c34 100644
--- a/drivers/net/i40e/i40e_pf.h
+++ b/drivers/net/i40e/i40e_pf.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -123,5 +123,7 @@ void i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
 				uint8_t *msg, uint16_t msglen);
 int i40e_pf_host_init(struct rte_eth_dev *dev);
 int i40e_pf_host_uninit(struct rte_eth_dev *dev);
+void i40e_notify_vf_link_status(struct rte_eth_dev *dev,
+				struct i40e_pf_vf *vf);
 
 #endif /* _I40E_PF_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
new file mode 100644
index 0000000..46ba60c
--- /dev/null
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -0,0 +1,61 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright (c) 2017 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.
+ */
+
+#ifndef _PMD_I40E_H_
+#define _PMD_I40E_H_
+
+/**
+ * @file rte_pmd_i40e.h
+ *
+ * i40e PMD specific functions.
+ *
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ */
+
+#include <rte_ethdev.h>
+
+/**
+ * Notify VF when PF link status changes.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf
+ *   VF id.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* invalid.
+ */
+int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);
+
+#endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef35398..3c6a192 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -2,3 +2,10 @@ DPDK_2.0 {
 
 	local: *;
 };
+
+DPDK_17.02 {
+	global:
+
+	rte_pmd_i40e_ping_vfs;
+
+} DPDK_2.0;
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 02/26] net/i40e: add callback to user on VF to PF mbox msg
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

The callback asks the user application if it is allowed to
perform the mailbox messages.

If the return value from user is RTE_PMD_I40E_MB_EVENT_PROCEED
then continue. If ACK or NACK, do nothing and send
not_supported to VF.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_pf.c      | 230 ++++++++++++++++++++++++++++++++++------
 drivers/net/i40e/rte_pmd_i40e.h |  21 ++++
 2 files changed, 216 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index f606c2a..5c58424 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -55,6 +55,7 @@
 #include "i40e_ethdev.h"
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
+#include "rte_pmd_i40e.h"
 
 #define I40E_CFG_CRCSTRIP_DEFAULT 1
 
@@ -272,14 +273,23 @@
 }
 
 static void
-i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf, bool b_op)
 {
 	struct i40e_virtchnl_version_info info;
 
 	info.major = I40E_DPDK_VERSION_MAJOR;
 	info.minor = I40E_DPDK_VERSION_MINOR;
-	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
-		I40E_SUCCESS, (uint8_t *)&info, sizeof(info));
+
+	if (b_op)
+		i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+					    I40E_SUCCESS,
+					    (uint8_t *)&info,
+					    sizeof(info));
+	else
+		i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION,
+					    I40E_NOT_SUPPORTED,
+					    (uint8_t *)&info,
+					    sizeof(info));
 }
 
 static int
@@ -292,13 +302,20 @@
 }
 
 static int
-i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
 {
 	struct i40e_virtchnl_vf_resource *vf_res = NULL;
 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
 	uint32_t len = 0;
 	int ret = I40E_SUCCESS;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(vf,
+					    I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
+					    I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	/* only have 1 VSI by default */
 	len =  sizeof(struct i40e_virtchnl_vf_resource) +
 				I40E_DEFAULT_VF_VSI_NUM *
@@ -423,7 +440,8 @@
 static int
 i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
 					   uint8_t *msg,
-					   uint16_t msglen)
+					   uint16_t msglen,
+					   bool b_op)
 {
 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
 	struct i40e_vsi *vsi = vf->vsi;
@@ -432,6 +450,13 @@
 	struct i40e_virtchnl_queue_pair_info *vc_qpi;
 	int i, ret = I40E_SUCCESS;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(vf,
+					    I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+					    I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
 		vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
 		msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
@@ -482,7 +507,8 @@
 static int
 i40e_pf_host_process_cmd_config_vsi_queues_ext(struct i40e_pf_vf *vf,
 					       uint8_t *msg,
-					       uint16_t msglen)
+					       uint16_t msglen,
+					       bool b_op)
 {
 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
 	struct i40e_vsi *vsi = vf->vsi;
@@ -491,6 +517,14 @@
 	struct i40e_virtchnl_queue_pair_ext_info *vc_qpei;
 	int i, ret = I40E_SUCCESS;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps ||
 		vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP ||
 		msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei,
@@ -539,12 +573,21 @@
 
 static int
 i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
-					uint8_t *msg, uint16_t msglen)
+					uint8_t *msg, uint16_t msglen,
+					bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_irq_map_info *irqmap =
 	    (struct i40e_virtchnl_irq_map_info *)msg;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) {
 		PMD_DRV_LOG(ERR, "buffer too short");
 		ret = I40E_ERR_PARAM;
@@ -646,12 +689,21 @@
 static int
 i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf,
 					uint8_t *msg,
-					uint16_t msglen)
+					uint16_t msglen,
+					bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_queue_select *q_sel =
 		(struct i40e_virtchnl_queue_select *)msg;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen != sizeof(*q_sel)) {
 		ret = I40E_ERR_PARAM;
 		goto send_msg;
@@ -669,7 +721,8 @@
 static int
 i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,
 					   uint8_t *msg,
-					   uint16_t msglen)
+					   uint16_t msglen,
+					   bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -678,6 +731,14 @@
 	int i;
 	struct ether_addr *mac;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));
 
 	if (msg == NULL || msglen <= sizeof(*addr_list)) {
@@ -707,7 +768,8 @@
 static int
 i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf,
 					   uint8_t *msg,
-					   uint16_t msglen)
+					   uint16_t msglen,
+					   bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_ether_addr_list *addr_list =
@@ -715,6 +777,14 @@
 	int i;
 	struct ether_addr *mac;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen <= sizeof(*addr_list)) {
 		PMD_DRV_LOG(ERR, "delete_ether_address argument too short");
 		ret = I40E_ERR_PARAM;
@@ -739,7 +809,8 @@
 
 static int
 i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf,
-				uint8_t *msg, uint16_t msglen)
+				uint8_t *msg, uint16_t msglen,
+				bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -747,6 +818,14 @@
 	int i;
 	uint16_t *vid;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_ADD_VLAN,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
 		PMD_DRV_LOG(ERR, "add_vlan argument too short");
 		ret = I40E_ERR_PARAM;
@@ -771,7 +850,8 @@
 static int
 i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf,
 				  uint8_t *msg,
-				  uint16_t msglen)
+				  uint16_t msglen,
+				  bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_vlan_filter_list *vlan_filter_list =
@@ -779,6 +859,14 @@
 	int i;
 	uint16_t *vid;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_DEL_VLAN,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
 		PMD_DRV_LOG(ERR, "delete_vlan argument too short");
 		ret = I40E_ERR_PARAM;
@@ -803,7 +891,8 @@
 i40e_pf_host_process_cmd_config_promisc_mode(
 					struct i40e_pf_vf *vf,
 					uint8_t *msg,
-					uint16_t msglen)
+					uint16_t msglen,
+					bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_promisc_info *promisc =
@@ -811,6 +900,14 @@
 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
 	bool unicast = FALSE, multicast = FALSE;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen != sizeof(*promisc)) {
 		ret = I40E_ERR_PARAM;
 		goto send_msg;
@@ -836,13 +933,20 @@
 }
 
 static int
-i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
+i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf, bool b_op)
 {
 	i40e_update_vsi_stats(vf->vsi);
 
-	i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
-		I40E_SUCCESS, (uint8_t *)&vf->vsi->eth_stats,
-				sizeof(vf->vsi->eth_stats));
+	if (b_op)
+		i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+					    I40E_SUCCESS,
+					    (uint8_t *)&vf->vsi->eth_stats,
+					    sizeof(vf->vsi->eth_stats));
+	else
+		i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS,
+					    I40E_NOT_SUPPORTED,
+					    (uint8_t *)&vf->vsi->eth_stats,
+					    sizeof(vf->vsi->eth_stats));
 
 	return I40E_SUCCESS;
 }
@@ -851,12 +955,21 @@
 i40e_pf_host_process_cmd_cfg_vlan_offload(
 					struct i40e_pf_vf *vf,
 					uint8_t *msg,
-					uint16_t msglen)
+					uint16_t msglen,
+					bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_vlan_offload_info *offload =
 			(struct i40e_virtchnl_vlan_offload_info *)msg;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen != sizeof(*offload)) {
 		ret = I40E_ERR_PARAM;
 		goto send_msg;
@@ -877,12 +990,21 @@
 static int
 i40e_pf_host_process_cmd_cfg_pvid(struct i40e_pf_vf *vf,
 					uint8_t *msg,
-					uint16_t msglen)
+					uint16_t msglen,
+					bool b_op)
 {
 	int ret = I40E_SUCCESS;
 	struct i40e_virtchnl_pvid_info  *tpid_info =
 			(struct i40e_virtchnl_pvid_info *)msg;
 
+	if (!b_op) {
+		i40e_pf_host_send_msg_to_vf(
+			vf,
+			I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
+			I40E_NOT_SUPPORTED, NULL, 0);
+		return ret;
+	}
+
 	if (msg == NULL || msglen != sizeof(*tpid_info)) {
 		ret = I40E_ERR_PARAM;
 		goto send_msg;
@@ -923,6 +1045,8 @@
 	struct i40e_pf_vf *vf;
 	/* AdminQ will pass absolute VF id, transfer to internal vf id */
 	uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;
+	struct rte_pmd_i40e_mb_event_param cb_param;
+	bool b_op = TRUE;
 
 	if (vf_id > pf->vf_num - 1 || !pf->vfs) {
 		PMD_DRV_LOG(ERR, "invalid argument");
@@ -937,10 +1061,35 @@
 		return;
 	}
 
+	/**
+	 * initialise structure to send to user application
+	 * will return response from user in retval field
+	 */
+	cb_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
+	cb_param.vfid = vf_id;
+	cb_param.msg_type = opcode;
+	cb_param.msg = (void *)msg;
+	cb_param.msglen = msglen;
+
+	/**
+	 * Ask user application if we're allowed to perform those functions.
+	 * If we get cb_param.retval == RTE_PMD_I40E_MB_EVENT_PROCEED,
+	 * then business as usual.
+	 * If RTE_PMD_I40E_MB_EVENT_NOOP_ACK or RTE_PMD_I40E_MB_EVENT_NOOP_NACK,
+	 * do nothing and send not_supported to VF. As PF must send a response
+	 * to VF and ACK/NACK is not defined.
+	 */
+	_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX, &cb_param);
+	if (cb_param.retval != RTE_PMD_I40E_MB_EVENT_PROCEED) {
+		PMD_DRV_LOG(WARNING, "VF to PF message(%d) is not permitted!",
+			    opcode);
+		b_op = FALSE;
+	}
+
 	switch (opcode) {
 	case I40E_VIRTCHNL_OP_VERSION :
 		PMD_DRV_LOG(INFO, "OP_VERSION received");
-		i40e_pf_host_process_cmd_version(vf);
+		i40e_pf_host_process_cmd_version(vf, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_RESET_VF :
 		PMD_DRV_LOG(INFO, "OP_RESET_VF received");
@@ -948,61 +1097,72 @@
 		break;
 	case I40E_VIRTCHNL_OP_GET_VF_RESOURCES:
 		PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
-		i40e_pf_host_process_cmd_get_vf_resource(vf);
+		i40e_pf_host_process_cmd_get_vf_resource(vf, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
-		i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen);
+		i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
+							   msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received");
 		i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg,
-								msglen);
+							       msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
-		i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen);
+		i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
-		i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
-		i40e_notify_vf_link_status(dev, vf);
+		if (b_op) {
+			i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+			i40e_notify_vf_link_status(dev, vf);
+		} else {
+			i40e_pf_host_send_msg_to_vf(
+				vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+				I40E_NOT_SUPPORTED, NULL, 0);
+		}
 		break;
 	case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
-		i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen);
+		i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS:
 		PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
-		i40e_pf_host_process_cmd_add_ether_address(vf, msg, msglen);
+		i40e_pf_host_process_cmd_add_ether_address(vf, msg,
+							   msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS:
 		PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
-		i40e_pf_host_process_cmd_del_ether_address(vf, msg, msglen);
+		i40e_pf_host_process_cmd_del_ether_address(vf, msg,
+							   msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_ADD_VLAN:
 		PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
-		i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen);
+		i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_DEL_VLAN:
 		PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
-		i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen);
+		i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
-		i40e_pf_host_process_cmd_config_promisc_mode(vf, msg, msglen);
+		i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
+							     msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_GET_STATS:
 		PMD_DRV_LOG(INFO, "OP_GET_STATS received");
-		i40e_pf_host_process_cmd_get_stats(vf);
+		i40e_pf_host_process_cmd_get_stats(vf, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD:
 		PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
-		i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
+		i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg,
+							  msglen, b_op);
 		break;
 	case I40E_VIRTCHNL_OP_CFG_VLAN_PVID:
 		PMD_DRV_LOG(INFO, "OP_CFG_VLAN_PVID received");
-		i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen);
+		i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen, b_op);
 		break;
 	/* Don't add command supported below, which will
 	 * return an error code.
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 46ba60c..afa3761 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -45,6 +45,27 @@
 #include <rte_ethdev.h>
 
 /**
+ * Response sent back to i40e driver from user app after callback
+ */
+enum rte_pmd_i40e_mb_event_rsp {
+	RTE_PMD_I40E_MB_EVENT_NOOP_ACK,  /**< skip mbox request and ACK */
+	RTE_PMD_I40E_MB_EVENT_NOOP_NACK, /**< skip mbox request and NACK */
+	RTE_PMD_I40E_MB_EVENT_PROCEED,  /**< proceed with mbox request  */
+	RTE_PMD_I40E_MB_EVENT_MAX       /**< max value of this enum */
+};
+
+/**
+ * Data sent to the user application when the callback is executed.
+ */
+struct rte_pmd_i40e_mb_event_param {
+	uint16_t vfid;     /**< Virtual Function number */
+	uint16_t msg_type; /**< VF to PF message type, see i40e_virtchnl_ops */
+	uint16_t retval;   /**< return value */
+	void *msg;         /**< pointer to message */
+	uint16_t msglen;   /**< length of the message */
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 03/26] net/i40e: set VF MAC anti-spoofing from PF
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

Support enabling/disabling VF MAC anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's MAC anti-spoofing.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            | 65 +++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           | 19 +++++++++
 drivers/net/i40e/rte_pmd_i40e_version.map |  1 +
 3 files changed, 85 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 58f9dfa..fb45c42 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10226,3 +10226,68 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 
 	return 0;
 }
+
+int
+rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+	struct i40e_vsi *vsi;
+	struct i40e_hw *hw;
+	struct i40e_vsi_context ctxt;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (is_i40e_pmd(dev->data->drv_name))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid argument.");
+		return -EINVAL;
+	}
+
+	vsi = pf->vfs[vf_id].vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Check if it has been already on or off */
+	if (vsi->info.valid_sections &
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
+		if (on) {
+			if ((vsi->info.sec_flags &
+			     I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
+			    I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
+				return 0; /* already on */
+		} else {
+			if ((vsi->info.sec_flags &
+			     I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
+				return 0; /* already off */
+		}
+	}
+
+	vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+	if (on)
+		vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+	else
+		vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+	(void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+	ctxt.seid = vsi->seid;
+
+	hw = I40E_VSI_TO_HW(vsi);
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret != I40E_SUCCESS) {
+		ret = -ENOTSUP;
+		PMD_DRV_LOG(ERR, "Failed to update VSI params");
+	}
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index afa3761..11d1c2b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -79,4 +79,23 @@ struct rte_pmd_i40e_mb_event_param {
  */
 int rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf);
 
+/**
+ * Enable/Disable VF MAC anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set MAC anti spoofing.
+ * @param on
+ *    1 - Enable VFs MAC anti spoofing.
+ *    0 - Disable VFs MAC anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port,
+				       uint16_t vf_id,
+				       uint8_t on);
+
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 3c6a192..0581209 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -7,5 +7,6 @@ DPDK_17.02 {
 	global:
 
 	rte_pmd_i40e_ping_vfs;
+	rte_pmd_i40e_set_vf_mac_anti_spoof;
 
 } DPDK_2.0;
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 04/26] net/i40e: set VF VLAN anti-spoofing from PF
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

Support enabling/disabling VF VLAN anti-spoofing from
PF.
User can call the API on PF to enable/disable a specific
VF's VLAN anti-spoofing.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            | 140 ++++++++++++++++++++++++++++--
 drivers/net/i40e/i40e_ethdev.h            |   1 +
 drivers/net/i40e/rte_pmd_i40e.h           |  19 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 4 files changed, 156 insertions(+), 5 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index fb45c42..97217f9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -4625,6 +4625,7 @@ struct i40e_vsi *
 	vsi->max_macaddrs = I40E_NUM_MACADDR_MAX;
 	vsi->parent_vsi = uplink_vsi ? uplink_vsi : pf->main_vsi;
 	vsi->user_param = user_param;
+	vsi->vlan_anti_spoof_on = 0;
 	/* Allocate queues */
 	switch (vsi->type) {
 	case I40E_VSI_MAIN  :
@@ -5966,14 +5967,11 @@ struct i40e_vsi *
 }
 
 static void
-i40e_set_vlan_filter(struct i40e_vsi *vsi,
-			 uint16_t vlan_id, bool on)
+i40e_store_vlan_filter(struct i40e_vsi *vsi,
+		       uint16_t vlan_id, bool on)
 {
 	uint32_t vid_idx, vid_bit;
 
-	if (vlan_id > ETH_VLAN_ID_MAX)
-		return;
-
 	vid_idx = I40E_VFTA_IDX(vlan_id);
 	vid_bit = I40E_VFTA_BIT(vlan_id);
 
@@ -5983,6 +5981,38 @@ struct i40e_vsi *
 		vsi->vfta[vid_idx] &= ~vid_bit;
 }
 
+static void
+i40e_set_vlan_filter(struct i40e_vsi *vsi,
+		     uint16_t vlan_id, bool on)
+{
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+	int ret;
+
+	if (vlan_id > ETH_VLAN_ID_MAX)
+		return;
+
+	i40e_store_vlan_filter(vsi, vlan_id, on);
+
+	if (!vsi->vlan_anti_spoof_on || !vlan_id)
+		return;
+
+	vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+
+	if (on) {
+		ret = i40e_aq_add_vlan(hw, vsi->seid,
+				       &vlan_data, 1, NULL);
+		if (ret != I40E_SUCCESS)
+			PMD_DRV_LOG(ERR, "Failed to add vlan filter");
+	} else {
+		ret = i40e_aq_remove_vlan(hw, vsi->seid,
+					  &vlan_data, 1, NULL);
+		if (ret != I40E_SUCCESS)
+			PMD_DRV_LOG(ERR,
+				    "Failed to remove vlan filter");
+	}
+}
+
 /**
  * Find all vlan options for specific mac addr,
  * return with actual vlan found.
@@ -10291,3 +10321,103 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 
 	return ret;
 }
+
+static int
+i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
+{
+	uint32_t j, k;
+	uint16_t vlan_id;
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
+	int ret;
+
+	for (j = 0; j < I40E_VFTA_SIZE; j++) {
+		if (!vsi->vfta[j])
+			continue;
+
+		for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
+			if (!(vsi->vfta[j] & (1 << k)))
+				continue;
+
+			vlan_id = j * I40E_UINT32_BIT_SIZE + k;
+			if (!vlan_id)
+				continue;
+
+			vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
+			if (add)
+				ret = i40e_aq_add_vlan(hw, vsi->seid,
+						       &vlan_data, 1, NULL);
+			else
+				ret = i40e_aq_remove_vlan(hw, vsi->seid,
+							  &vlan_data, 1, NULL);
+			if (ret != I40E_SUCCESS) {
+				PMD_DRV_LOG(ERR,
+					    "Failed to add/rm vlan filter");
+				return ret;
+			}
+		}
+	}
+
+	return I40E_SUCCESS;
+}
+
+int
+rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+	struct i40e_vsi *vsi;
+	struct i40e_hw *hw;
+	struct i40e_vsi_context ctxt;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (is_i40e_pmd(dev->data->drv_name))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid argument.");
+		return -EINVAL;
+	}
+
+	vsi = pf->vfs[vf_id].vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Check if it has been already on or off */
+	if (vsi->vlan_anti_spoof_on == on)
+		return 0; /* already on or off */
+
+	vsi->vlan_anti_spoof_on = on;
+	ret = i40e_add_rm_all_vlan_filter(vsi, on);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to remove VLAN filters.");
+		return -ENOTSUP;
+	}
+
+	vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
+	if (on)
+		vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+	else
+		vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+	(void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+	ctxt.seid = vsi->seid;
+
+	hw = I40E_VSI_TO_HW(vsi);
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret != I40E_SUCCESS) {
+		ret = -ENOTSUP;
+		PMD_DRV_LOG(ERR, "Failed to update VSI params");
+	}
+
+	return ret;
+}
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index c9fda15..797e892 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -361,6 +361,7 @@ struct i40e_vsi {
 	uint16_t msix_intr; /* The MSIX interrupt binds to VSI */
 	uint16_t nb_msix;   /* The max number of msix vector */
 	uint8_t enabled_tc; /* The traffic class enabled */
+	uint8_t vlan_anti_spoof_on; /* The VLAN anti-spoofing enabled */
 	struct i40e_bw_info bw_info; /* VSI bandwidth information */
 };
 
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 11d1c2b..be6e704 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -98,4 +98,23 @@ int rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port,
 				       uint16_t vf_id,
 				       uint8_t on);
 
+/**
+ * Enable/Disable VF VLAN anti spoofing.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param vf
+ *    VF on which to set VLAN anti spoofing.
+ * @param on
+ *    1 - Enable VFs VLAN anti spoofing.
+ *    0 - Disable VFs VLAN anti spoofing.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
+					uint16_t vf_id,
+					uint8_t on);
+
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 0581209..028f0ef 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -8,5 +8,6 @@ DPDK_17.02 {
 
 	rte_pmd_i40e_ping_vfs;
 	rte_pmd_i40e_set_vf_mac_anti_spoof;
+	rte_pmd_i40e_set_vf_vlan_anti_spoof;
 
 } DPDK_2.0;
-- 
1.9.3

^ permalink raw reply related

* [PATCH v10 05/26] net/i40e: set Tx loopback from PF
From: Wenzhuo Lu @ 2017-01-16  5:51 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu
In-Reply-To: <1484545911-40432-1-git-send-email-wenzhuo.lu@intel.com>

Support enabling/disabling TX loopback from PF.
User can call the API on PF to enable/disable TX loopback
for all the PF and VFs.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            | 241 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  16 ++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 3 files changed, 258 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 97217f9..4576ca2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -10421,3 +10421,244 @@ static void i40e_set_default_mac_addr(struct rte_eth_dev *dev,
 
 	return ret;
 }
+
+static int
+i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
+{
+	struct i40e_mac_filter *f;
+	struct i40e_macvlan_filter *mv_f;
+	int i, vlan_num;
+	enum rte_mac_filter_type filter_type;
+	int ret = I40E_SUCCESS;
+	void *temp;
+
+	/* remove all the MACs */
+	TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
+		vlan_num = vsi->vlan_num;
+		filter_type = f->mac_info.filter_type;
+		if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+		    filter_type == RTE_MACVLAN_HASH_MATCH) {
+			if (vlan_num == 0) {
+				PMD_DRV_LOG(ERR,
+					    "VLAN number shouldn't be 0\n");
+				return I40E_ERR_PARAM;
+			}
+		} else if (filter_type == RTE_MAC_PERFECT_MATCH ||
+			   filter_type == RTE_MAC_HASH_MATCH)
+			vlan_num = 1;
+
+		mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+		if (!mv_f) {
+			PMD_DRV_LOG(ERR, "failed to allocate memory");
+			return I40E_ERR_NO_MEMORY;
+		}
+
+		for (i = 0; i < vlan_num; i++) {
+			mv_f[i].filter_type = filter_type;
+			(void)rte_memcpy(&mv_f[i].macaddr,
+					 &f->mac_info.mac_addr,
+					 ETH_ADDR_LEN);
+		}
+		if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+		    filter_type == RTE_MACVLAN_HASH_MATCH) {
+			ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+							 &f->mac_info.mac_addr);
+			if (ret != I40E_SUCCESS) {
+				rte_free(mv_f);
+				return ret;
+			}
+		}
+
+		ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
+		if (ret != I40E_SUCCESS) {
+			rte_free(mv_f);
+			return ret;
+		}
+
+		rte_free(mv_f);
+		ret = I40E_SUCCESS;
+	}
+
+	return ret;
+}
+
+static int
+i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
+{
+	struct i40e_mac_filter *f;
+	struct i40e_macvlan_filter *mv_f;
+	int i, vlan_num = 0;
+	int ret = I40E_SUCCESS;
+	void *temp;
+
+	/* restore all the MACs */
+	TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
+		if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
+		    (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
+			/**
+			 * If vlan_num is 0, that's the first time to add mac,
+			 * set mask for vlan_id 0.
+			 */
+			if (vsi->vlan_num == 0) {
+				i40e_set_vlan_filter(vsi, 0, 1);
+				vsi->vlan_num = 1;
+			}
+			vlan_num = vsi->vlan_num;
+		} else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
+			   (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
+			vlan_num = 1;
+
+		mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
+		if (!mv_f) {
+			PMD_DRV_LOG(ERR, "failed to allocate memory");
+			return I40E_ERR_NO_MEMORY;
+		}
+
+		for (i = 0; i < vlan_num; i++) {
+			mv_f[i].filter_type = f->mac_info.filter_type;
+			(void)rte_memcpy(&mv_f[i].macaddr,
+					 &f->mac_info.mac_addr,
+					 ETH_ADDR_LEN);
+		}
+
+		if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
+		    f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
+			ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
+							 &f->mac_info.mac_addr);
+			if (ret != I40E_SUCCESS) {
+				rte_free(mv_f);
+				return ret;
+			}
+		}
+
+		ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
+		if (ret != I40E_SUCCESS) {
+			rte_free(mv_f);
+			return ret;
+		}
+
+		rte_free(mv_f);
+		ret = I40E_SUCCESS;
+	}
+
+	return ret;
+}
+
+static int
+i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
+{
+	struct i40e_vsi_context ctxt;
+	struct i40e_hw *hw;
+	int ret;
+
+	if (!vsi)
+		return -EINVAL;
+
+	hw = I40E_VSI_TO_HW(vsi);
+
+	/* Use the FW API if FW >= v5.0 */
+	if (hw->aq.fw_maj_ver < 5) {
+		PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
+		return -ENOTSUP;
+	}
+
+	/* Check if it has been already on or off */
+	if (vsi->info.valid_sections &
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
+		if (on) {
+			if ((vsi->info.switch_id &
+			     I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
+			    I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
+				return 0; /* already on */
+		} else {
+			if ((vsi->info.switch_id &
+			     I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
+				return 0; /* already off */
+		}
+	}
+
+	/* remove all the MAC and VLAN first */
+	ret = i40e_vsi_rm_mac_filter(vsi);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
+		return ret;
+	}
+	if (vsi->vlan_anti_spoof_on) {
+		ret = i40e_add_rm_all_vlan_filter(vsi, 0);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Failed to remove VLAN filters.");
+			return ret;
+		}
+	}
+
+	vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
+	if (on)
+		vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+	else
+		vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+	(void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
+	ctxt.seid = vsi->seid;
+
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(ERR, "Failed to update VSI params");
+		return ret;
+	}
+
+	/* add all the MAC and VLAN back */
+	ret = i40e_vsi_restore_mac_filter(vsi);
+	if (ret)
+		return ret;
+	if (vsi->vlan_anti_spoof_on) {
+		ret = i40e_add_rm_all_vlan_filter(vsi, 1);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+int
+rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf *pf;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	uint16_t vf_id;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (is_i40e_pmd(dev->data->drv_name))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	/* setup PF TX loopback */
+	vsi = pf->main_vsi;
+	ret = i40e_vsi_set_tx_loopback(vsi, on);
+	if (ret)
+		return -ENOTSUP;
+
+	/* setup TX loopback for all the VFs */
+	if (!pf->vfs) {
+		/* if no VF, do nothing. */
+		return 0;
+	}
+
+	for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
+		vf = &pf->vfs[vf_id];
+		vsi = vf->vsi;
+
+		ret = i40e_vsi_set_tx_loopback(vsi, on);
+		if (ret)
+			return -ENOTSUP;
+	}
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index be6e704..14fce97 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -117,4 +117,20 @@ int rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port,
 					uint16_t vf_id,
 					uint8_t on);
 
+/**
+ * Enable/Disable TX loopback on all the PF and VFs.
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param on
+ *    1 - Enable TX loopback.
+ *    0 - Disable TX loopback.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if bad parameter.
+ */
+int rte_pmd_i40e_set_tx_loopback(uint8_t port,
+				 uint8_t on);
+
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 028f0ef..51eda65 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -7,6 +7,7 @@ DPDK_17.02 {
 	global:
 
 	rte_pmd_i40e_ping_vfs;
+	rte_pmd_i40e_set_tx_loopback;
 	rte_pmd_i40e_set_vf_mac_anti_spoof;
 	rte_pmd_i40e_set_vf_vlan_anti_spoof;
 
-- 
1.9.3

^ 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