[dpdk-dev,2/4] bus/vdev: bus scan by multi-process channel

Message ID 1520177405-59091-3-git-send-email-jianfeng.tan@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

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

Commit Message

Jianfeng Tan March 4, 2018, 3:30 p.m. UTC
  To scan the vdevs in primary, we send request to primary process
to obtain the names for vdevs.

Only the name is shared from the primary. In probe(), the device
driver is supposed to locate (or request more) the detail
information from the primary.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/bus/vdev/Makefile |   1 +
 drivers/bus/vdev/vdev.c   | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)
  

Comments

Anatoly Burakov March 5, 2018, 9:36 a.m. UTC | #1
On 04-Mar-18 3:30 PM, Jianfeng Tan wrote:
> To scan the vdevs in primary, we send request to primary process
> to obtain the names for vdevs.
> 
> Only the name is shared from the primary. In probe(), the device
> driver is supposed to locate (or request more) the detail
> information from the primary.
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> ---

Is there much point in having private vdevs? Granted, i'm not exactly a 
heavy user of vdev's, but to me this would seem like a way to introduce 
more confusion. How do i tell which devices are shared between 
processes, and which are private to one process? Can i control which one 
do i get? To me it would seem like it would be better to just switch all 
vdevs to being shared.
  
Jianfeng Tan March 6, 2018, 12:50 a.m. UTC | #2
Hi Anatoly,

> -----Original Message-----

> From: Burakov, Anatoly

> Sent: Monday, March 5, 2018 5:37 PM

> To: Tan, Jianfeng; dev@dpdk.org

> Cc: Richardson, Bruce; Ananyev, Konstantin; thomas@monjalon.net;

> maxime.coquelin@redhat.com; Yigit, Ferruh

> Subject: Re: [PATCH 2/4] bus/vdev: bus scan by multi-process channel

> 

> On 04-Mar-18 3:30 PM, Jianfeng Tan wrote:

> > To scan the vdevs in primary, we send request to primary process

> > to obtain the names for vdevs.

> >

> > Only the name is shared from the primary. In probe(), the device

> > driver is supposed to locate (or request more) the detail

> > information from the primary.

> >

> > Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>

> > ---

> 

> Is there much point in having private vdevs? Granted, i'm not exactly a

> heavy user of vdev's, but to me this would seem like a way to introduce

> more confusion. How do i tell which devices are shared between

> processes, and which are private to one process? Can i control which one

> do i get? To me it would seem like it would be better to just switch all

> vdevs to being shared.


Yes, that’s the final target: to make every vdev shared between primary and secondary process.

However, now most kinds of the vdevs do not support multi-process. For those devices,

- If they are firstly probed in primary, then we will share the rte_eth_dev_data to the secondary, so that the secondary can get stats or pdump the port.
- If they are firstly probed in secondary, considering it's mostly used by the secondary process, so we will allocate the "port id" exclusively, and keep it in that secondary process privately.

Thanks,
Jianfeng
  
Anatoly Burakov March 7, 2018, 2 p.m. UTC | #3
On 04-Mar-18 3:30 PM, Jianfeng Tan wrote:
> To scan the vdevs in primary, we send request to primary process
> to obtain the names for vdevs.
> 
> Only the name is shared from the primary. In probe(), the device
> driver is supposed to locate (or request more) the detail
> information from the primary.
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
> ---

General note - you probably want to syncrhonize access to the tailq. 
Multiple secondaries may initialize, a vdev hotplug event may be in 
process, etc.
  
Jianfeng Tan March 12, 2018, 3:22 a.m. UTC | #4
On 3/7/2018 10:00 PM, Burakov, Anatoly wrote:
> On 04-Mar-18 3:30 PM, Jianfeng Tan wrote:
>> To scan the vdevs in primary, we send request to primary process
>> to obtain the names for vdevs.
>>
>> Only the name is shared from the primary. In probe(), the device
>> driver is supposed to locate (or request more) the detail
>> information from the primary.
>>
>> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
>> ---
>
> General note - you probably want to syncrhonize access to the tailq. 
> Multiple secondaries may initialize, a vdev hotplug event may be in 
> process, etc.
>

Make sense, will change it in next version.

Thanks,
Jianfeng
  

Patch

diff --git a/drivers/bus/vdev/Makefile b/drivers/bus/vdev/Makefile
index 24d424a..bd0bb89 100644
--- a/drivers/bus/vdev/Makefile
+++ b/drivers/bus/vdev/Makefile
@@ -10,6 +10,7 @@  LIB = librte_bus_vdev.a
 
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 # versioning export map
 EXPORT_MAP := rte_bus_vdev_version.map
diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
index e4bc724..0a3ea52 100644
--- a/drivers/bus/vdev/vdev.c
+++ b/drivers/bus/vdev/vdev.c
@@ -314,6 +314,88 @@  rte_vdev_uninit(const char *name)
 	return 0;
 }
 
+struct vdev_param {
+#define VDEV_SCAN_REQ	1
+#define VDEV_SCAN_ONE	2
+#define VDEV_SCAN_REP	3
+	int type;
+	int num;
+	char name[RTE_DEV_NAME_MAX_LEN];
+};
+
+static int vdev_plug(struct rte_device *dev);
+
+static int
+vdev_action(const struct rte_mp_msg *mp_msg, const void *peer)
+{
+	struct rte_vdev_device *dev;
+	struct rte_devargs *devargs;
+	struct rte_mp_msg mp_resp;
+	struct vdev_param *ou = (struct vdev_param *)&mp_resp.param;
+	const struct vdev_param *in = (const struct vdev_param *)mp_msg->param;
+	const char *devname;
+	int num;
+
+	strcpy(mp_resp.name, "vdev");
+	mp_resp.len_param = sizeof(*ou);
+	mp_resp.num_fds = 0;
+
+	switch (in->type) {
+	case VDEV_SCAN_REQ:
+		ou->type = VDEV_SCAN_ONE;
+		ou->num = 1;
+		num = 0;
+		TAILQ_FOREACH(dev, &vdev_device_list, next) {
+			devname = rte_vdev_device_name(dev);
+			if (strlen(devname) == 0)
+				VDEV_LOG(INFO, "vdev with no name is not sent");
+			VDEV_LOG(INFO, "send vdev, %s", devname);
+			strncpy(ou->name, devname, RTE_DEV_NAME_MAX_LEN);
+			if (rte_mp_sendmsg(&mp_resp) < 0)
+				VDEV_LOG(ERR, "send vdev, %s, failed, %s",
+					 devname, strerror(rte_errno));
+			num++;
+		}
+		ou->type = VDEV_SCAN_REP;
+		ou->num = num;
+		if (rte_mp_reply(&mp_resp, peer) < 0)
+			VDEV_LOG(ERR, "Failed to reply a scan request");
+		break;
+	case VDEV_SCAN_ONE:
+		VDEV_LOG(INFO, "receive vdev, %s", in->name);
+		dev = find_vdev(in->name);
+		if (dev) {
+			VDEV_LOG(ERR, "vdev already exists: %s", in->name);
+			break;
+		}
+
+		devargs = alloc_devargs(in->name, NULL);
+		if (!devargs) {
+			VDEV_LOG(ERR, "failed to allocate memory");
+			break;
+		}
+
+		dev = calloc(1, sizeof(*dev));
+		if (!dev) {
+			VDEV_LOG(ERR, "failed to allocate memory");
+			free(devargs);
+			break;
+		}
+
+		dev->device.devargs = devargs;
+		dev->device.numa_node = 0; /* to be corrected in probe() */
+		dev->device.name = devargs->name;
+
+		TAILQ_INSERT_TAIL(&devargs_list, devargs, next);
+		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
+		break;
+	default:
+		VDEV_LOG(ERR, "vdev cannot recognize this message");
+	}
+
+	return 0;
+}
+
 static int
 vdev_scan(void)
 {
@@ -321,6 +403,34 @@  vdev_scan(void)
 	struct rte_devargs *devargs;
 	struct vdev_custom_scan *custom_scan;
 
+	if (rte_mp_action_register("vdev", vdev_action) < 0 &&
+	    rte_errno != EEXIST) {
+		VDEV_LOG(ERR, "vdev fails to add action");
+		return -1;
+	}
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		struct rte_mp_msg mp_req, *mp_rep;
+		struct rte_mp_reply mp_reply;
+		struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
+		struct vdev_param *req = (struct vdev_param *)mp_req.param;
+		struct vdev_param *resp;
+
+		strcpy(mp_req.name, "vdev");
+		mp_req.len_param = sizeof(*req);
+		mp_req.num_fds = 0;
+		req->type = VDEV_SCAN_REQ;
+		if (rte_mp_request(&mp_req, &mp_reply, &ts) == 0 &&
+		    mp_reply.nb_received == 1) {
+			mp_rep = &mp_reply.msgs[0];
+			resp = (struct vdev_param *)mp_rep->param;
+			VDEV_LOG(INFO, "Received %d vdevs", resp->num);
+		} else
+			VDEV_LOG(ERR, "Failed to request vdev from primary");
+
+		/* Fall through to allow private vdevs in secondary process */
+	}
+
 	/* call custom scan callbacks if any */
 	rte_spinlock_lock(&vdev_custom_scan_lock);
 	TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {