[dpdk-dev,v10,20/20] ethdev: add control interface support

Message ID 20170704161337.45926-21-ferruh.yigit@intel.com (mailing list archive)
State Changes Requested, archived
Headers

Checks

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

Commit Message

Ferruh Yigit July 4, 2017, 4:13 p.m. UTC
  To have the support corresponding kernel module (UNCI) needs to be
inserted.  If kernel module is not there, application will run as
it is without kernel control path support.

When UNCI module inserted, running application creates a virtual Linux
network interface (dpdk$) per DPDK port. This interface can be used by
traditional Linux tools.

If Userspace Network Control Interface (UNCI) kernel module
(rte_unci.ko) inserted, virtual interfaces created for each DPDK port
for control purposes.

Created interfaces are named as dpdk#, like:

    $ ifconfig dpdk0; ifconfig dpdk1
    dpdk0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            ether 90:e2:ba:0e:49:b9  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    dpdk1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            ether 00:1b:21:76:fa:21  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Regular Linux commands can be issued on interfaces:

	$ ethtool -i dpdk0
	driver: net_ixgbe
	version: DPDK 17.08.0-rc0
	firmware-version: 0x61bf0001
	expansion-rom-version:
	bus-info: 0000:08:00.1
	supports-statistics: no
	supports-test: no
	supports-eeprom-access: yes
	supports-register-dump: yes
	supports-priv-flags: no

Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
v9:
* fix shared build
---
 drivers/net/Makefile              |  4 ++++
 lib/librte_ether/rte_ethdev_pci.h | 15 ++++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)
  

Comments

Yuanhan Liu July 8, 2017, 6:28 a.m. UTC | #1
On Tue, Jul 04, 2017 at 05:13:37PM +0100, Ferruh Yigit wrote:
> @@ -157,8 +164,12 @@ rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev,
>  
>  	RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL);
>  	ret = dev_init(eth_dev);
> -	if (ret)
> +	if (ret) {
>  		rte_eth_dev_pci_release(eth_dev);
> +		return ret;
> +	}
> +
> +	rte_eth_control_interface_create(eth_dev->data->port_id);

Hi,

So you are creating a virtual kernel interface for each PCI port. What
about the VDEVs? If you plan to create one for each port, why not create
it at the stage while allocating the eth device, or at the stage while
starting the port if the former is too earlier?

Another thing comes to my mind is have you tried it with multi-process
model? Looks like it will create the control interface twice? Or it will
just be failed since the interface already exists?


I also have few questions regarding the whole design. So seems that the
ctrl_if only exports two APIs and they all will be only used in the EAL
layer. Thus, one question is did you plan to let APP use them? Judging
EAL already calls them automatically, I don't think it makes sense to
let the APP call it again. That being said, what's the point of the making
it be an lib? Why not just put it under EAL or somewhere else, and let
EAL invoke it as normal helper functions (instead of by public APIs)?

I will avoid adding a new lib if possible. Otherwise, it increases the
chance of ABI/API breakage is needed in future for extensions.

The same question goes to the ethtool lib. Since your solution can work
well with the well-known ethtool, which is also way more widely available
than the DPDK ethtool app, what's the point of keeping the ethtool app
then? Like above, I also don't think those APIs are meant for APPs (or
are they?). Thus, with the ethtool app removed, we then could again avoid
introducing a new lib.

	--yliu
  
Ferruh Yigit July 20, 2017, 2:55 p.m. UTC | #2
On 7/8/2017 7:28 AM, Yuanhan Liu wrote:
> On Tue, Jul 04, 2017 at 05:13:37PM +0100, Ferruh Yigit wrote:
>> @@ -157,8 +164,12 @@ rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev,
>>  
>>  	RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL);
>>  	ret = dev_init(eth_dev);
>> -	if (ret)
>> +	if (ret) {
>>  		rte_eth_dev_pci_release(eth_dev);
>> +		return ret;
>> +	}
>> +
>> +	rte_eth_control_interface_create(eth_dev->data->port_id);
> 
> Hi,
> 
> So you are creating a virtual kernel interface for each PCI port. What
> about the VDEVs? If you plan to create one for each port, why not create
> it at the stage while allocating the eth device, or at the stage while
> starting the port if the former is too earlier?

Technically it is possible to support vdevs, but I don't know if there
is usecase for it. If this is required, the change is simple, as you
said this can be possible by moving create API to port start.

> 
> Another thing comes to my mind is have you tried it with multi-process
> model? Looks like it will create the control interface twice? Or it will
> just be failed since the interface already exists?

I didn't test mult-process scenarios, I will test.

> 
> 
> I also have few questions regarding the whole design. So seems that the
> ctrl_if only exports two APIs and they all will be only used in the EAL
> layer. Thus, one question is did you plan to let APP use them? Judging
> EAL already calls them automatically, I don't think it makes sense to
> let the APP call it again. That being said, what's the point of the making
> it be an lib? Why not just put it under EAL or somewhere else, and let
> EAL invoke it as normal helper functions (instead of by public APIs)?

Public APIs are from previous version of the patchset, where user
application was in control on create/destroy and processing messages.
With interfaces automatically created as you said these APIs are not
very meaningful for application.

But code is not so small to put into another library, I believe it is
good to separate this code.

> 
> I will avoid adding a new lib if possible. Otherwise, it increases the
> chance of ABI/API breakage is needed in future for extensions.

Those API are required for other libraries, not sure how to include the
code otherwise.

> 
> The same question goes to the ethtool lib. Since your solution can work
> well with the well-known ethtool, which is also way more widely available
> than the DPDK ethtool app, what's the point of keeping the ethtool app
> then? Like above, I also don't think those APIs are meant for APPs (or
> are they?). Thus, with the ethtool app removed, we then could again avoid
> introducing a new lib.

Ethtool library is ready to use abstraction on ethdev layer, I don't
insist on having it as a separate library, but I believe it is good to
reuse that code instead of re-writing it.

> 
> 	--yliu
>
  

Patch

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 35ed8135a..cdabc2349 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -39,6 +39,10 @@  endif
 core-libs := librte_eal librte_mbuf librte_mempool librte_ring librte_ether
 core-libs += librte_net librte_kvargs
 
+ifeq ($(CONFIG_RTE_LIBRTE_CTRL_IF),y)
+core-libs += librte_ctrl_if
+endif
+
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += af_packet
 DEPDIRS-af_packet = $(core-libs)
 DIRS-$(CONFIG_RTE_LIBRTE_ARK_PMD) += ark
diff --git a/lib/librte_ether/rte_ethdev_pci.h b/lib/librte_ether/rte_ethdev_pci.h
index 69aab03fb..fcdee9229 100644
--- a/lib/librte_ether/rte_ethdev_pci.h
+++ b/lib/librte_ether/rte_ethdev_pci.h
@@ -38,6 +38,13 @@ 
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 
+#ifdef RTE_LIBRTE_CTRL_IF
+#include <rte_ctrl_if.h>
+#else
+#define rte_eth_control_interface_create(port_id) do { } while (0)
+#define rte_eth_control_interface_destroy(port_id) do { } while (0)
+#endif
+
 /**
  * Copy pci device info to the Ethernet device data.
  *
@@ -157,8 +164,12 @@  rte_eth_dev_pci_generic_probe(struct rte_pci_device *pci_dev,
 
 	RTE_FUNC_PTR_OR_ERR_RET(*dev_init, -EINVAL);
 	ret = dev_init(eth_dev);
-	if (ret)
+	if (ret) {
 		rte_eth_dev_pci_release(eth_dev);
+		return ret;
+	}
+
+	rte_eth_control_interface_create(eth_dev->data->port_id);
 
 	return ret;
 }
@@ -179,6 +190,8 @@  rte_eth_dev_pci_generic_remove(struct rte_pci_device *pci_dev,
 	if (!eth_dev)
 		return -ENODEV;
 
+	rte_eth_control_interface_destroy(eth_dev->data->port_id);
+
 	if (dev_uninit) {
 		ret = dev_uninit(eth_dev);
 		if (ret)