RE: [PATCH v6 04/11] usbip: kernel module for userspace URBs transmission

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear Bjørn,

I might not fully understand your comments but I try my best.

> usbip-host.ko and vhci-hcd.ko are running on different hosts, likely
> on different hardware and kernel versions, so this picture is
> impossible.

If this discusses USB level interoperability, the issue is came from
USB/IP itself before this patch.
I started from 3.14.2. I tested several combinations and almost good
except USB storage error in 3.14.2 which fixed later kernel.
I tested a host side porting with libusb using Windows 7 and 8.1.
WebCam failed in setup phase but others work well.

I think integrators who utilize this infrastructure arrange certain
conditions including application delivery, update mechanism, manual 
operation rules and etc. There may be problems but they can be managed.

> two TCP sessions.

Sorry for my poor picture.
TCP session is one as well as original USB/IP.
After preparing phase, the URBs are transferred in same session.

> You can implement a TCP<->websocket proxy in userspace on each side

Yes.
But assuming small device (like raspberry Pi) with WebCam isochronous
transfer, this patch helps to get smoother motion.
I think it's not bad to put small hooks to usbip-host.ko and vhci-hcd.ko
, introduce a separate module for userspace transfer if it clears
errors pointed out below.

> a) old and new client/server versions, and
> b) clients/servers with and without usbip-ux.ko

> Is a new userspace required if usbip-ux.ko is loaded, or will the old
> ABI continue to work as before?

Yes. New userspace is required if usbip-ux.ko is loaded.
Old ABI works as before if usbip-ux.ko is not loaded. 

It's possible to change that old user space binary works as before even
if usbip-ux.ko exists.
Is it needed? 

usbip-ux.ko is written in usbip/websocket/README and not in usbip/README.
It is assumed to be loaded when usbws and usbwsd/usbwsa are used.

> So you didn't run checkpatch on this?  I guess not:
> total: 52 errors, 51 warnings, 1183 lines checked

No. I'm very sorry that I didn't understand SubmittingPatches.
I will clear them. 

> Ouch. What happened to usbip_trx_ops on errors?

I will fix.

> Testing for mode before calling a mode dependent callback looks weird.
> Why don't you do all the USBIP_TRX_MODE_KERNEL work in
> usbip_kernel_sendmsg? 

I will check the logic.

> Please don't break string constants.

I will fix.

> Is this really compat-safe?

I used these pointers for debug messages in userspace to identify
connection instead of sockfd.
I will change the interface.

Thank you spending time,

nobuo iwata
//
> -----Original Message-----
> From: Bjørn Mork [mailto:bjorn@xxxxxxx]
> Sent: Tuesday, January 05, 2016 8:35 PM
> To: fx IWATA NOBUO
> Cc: valentina.manea.m@xxxxxxxxx; shuah.kh@xxxxxxxxxxx;
> gregkh@xxxxxxxxxxxxxxxxxxx; linux-usb@xxxxxxxxxxxxxxx; fx MICHIMURA
> TADAO
> Subject: Re: [PATCH v6 04/11] usbip: kernel module for userspace URBs
> transmission
> 
> Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx> writes:
> 
> > Originally, USB/IP transmits requests and response PDUs for
> > preparation to transfer URBs in user space, after the preparation,
> > URBs are transmitted in kernel space.
> >
> > To make easy to introduce application network protocols like WebSocket
> > and so on, the driver, usbip_ux.ko, forwards URBs to USB/IP user space
> > utilities. It's just like fuse driver for user space file system.
> > Then, utilities transfer URBs in user space.
> >
> > To do so, usbip_trx_ops makes send/receive functions pluggable.
> > kernel_sendmsg() and kernel_recvmsg() for kernel mode transfer can be
> > substituted by read/write methods to user space utilities.
> >
> > In the absence of usbip_ux.ko, original kernel space transferring is
> > valid. usbip_ux.ko replaces usbip_trx_ops in its init routine.
> >
> > A) Original - kernel space URBs transfer
> >
> > User            +-------+   1) import/export   +-------+
> > space           |uspipd,|<-------------------->|usbip, |
> >                 |usbip  |                      |usbipa |
> >                 +---+---+                      +---+---+
> >                     |                              |
> >         2)Set sockfd|                              |2)Set sockfd
> >           thru sysfs|                              |  thru sysfs
> >                     V                              V
> > Kernel          +-------+        4)URBs        +-------+
> > space           |usbip  |<-------------------->|vhci   |
> >                 |host.ko|                      |hcd.ko |
> >                 +-------+                      +-------+
> >                 3)link to kernel trx_ops       3)link to kernel trx_ops
> 
> 
> AFAICS, usbip-host.ko and vhci-hcd.ko are running on different hosts,
> likely on different hardware and kernel versions, so this picture is
> impossible.
> 
> But I'm not going to be more difficult than necessary :) I can see what
> you are getting at: There is a kernel TCP socket on each side of the "4)URBs"
> channel, and you want to be able to replace it with something else.
> 
> But I am still not convinced about this strategy.  There is nothing in the
> old protocol preventing you from terminating a TCP session locally on each
> host, and do whatever you like between these two TCP sessions.
> You can implement a TCP<->websocket proxy in userspace on each side of the
> link without hooking into the kernel at all, passing one end of each session
> to the existing usbip kernel implementation.
> 
> Or am I missing something?
> 
> 
> > B) New - user space URBs transfer
> >
> > User            +-------+    1)import/export   +-------+
> > space           |uspipd,|<-------------------->|usbip, |
> >             +---|usbip  |<-------------------->|usbipa |---+
> > 2)Set sockfd|+--+-------+        6)URBs        +-------+--+|2)Set
> sockfd
> >   thru ioctl||      ^                             ^       ||  thru
> ioctl
> >   (right)   ||      |5)read/write     5)read/write|       ||  (left)
> > 3)Set sockfd||      +-------+              +------+       ||3)Set
> Sockfd
> >   thru sysfs|+-----------+  | /dev/usbip-ux|  +-----------+|  thru
> sysfs
> >   (left)    V            V  V              V  V            V
> (right)
> > Kernel  +-------+       +-------+      +-------+       +-------+
> > space   |usbip  |<----->|usbip  |      |usbip  |<----->|vhci   |
> >         |host.ko|5)send |ux.ko  |      |ux.ko  |5)send |hcd.ko |
> >         +-------+  recv +-------+      +-------+  recv +-------+
> >         4)link to user trx_ops         4)link to user trx_ops
> 
> 
> Thanks for trying to draw it up.  That really helps understaning. But this
> got a little complicated....  I assume you keep the protocol (the
> "1) import/export" arrow) compatible, so that you can mix and match
> (assuming fallback to TCP transport):
> 
>  a) old and new client/server versions, and
>  b) clients/servers with and without usbip-ux.ko
> 
> Is this correct?
> 
> How about userspace<->kernel compatibility in each side:  Is a new
> userspace required if usbip-ux.ko is loaded, or will the old ABI continue
> to work as before?
> 
> > @@ -335,26 +336,28 @@ int usbip_recv(struct socket *sock, void *buf,
> > int size)
> >
> >  	usbip_dbg_xmit("enter\n");
> >
> > -	if (!sock || !buf || !size) {
> > -		pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf,
> > -		       size);
> > +	if ((!ud->tcp_socket && !ud->ux) || !buf || !size) {
> > +		pr_err("invalid arg, sock %p ux %p buff %p size %d\n",
> > +			ud->tcp_socket, ud->ux, buf, size);
> >  		return -EINVAL;
> >  	}
> >
> >  	do {
> > -		sock->sk->sk_allocation = GFP_NOIO;
> >  		iov.iov_base    = buf;
> >  		iov.iov_len     = size;
> > -		msg.msg_name    = NULL;
> > -		msg.msg_namelen = 0;
> > -		msg.msg_control = NULL;
> > -		msg.msg_controllen = 0;
> > -		msg.msg_flags      = MSG_NOSIGNAL;
> > +		if (usbip_trx_ops->mode == USBIP_TRX_MODE_KERNEL) {
> 
> Testing for mode before calling a mode dependent callback looks weird.
> Why don't you do all the USBIP_TRX_MODE_KERNEL work in
> usbip_kernel_sendmsg?
> 
> 
> > +	if (ux->ud) {
> > +		return 1;
> > +	}
> 
> So you didn't run checkpatch on this?  I guess not:
> 
>  total: 52 errors, 51 warnings, 1183 lines checked
> 
> 
> > +static int usbip_ux_getkaddr(usbip_ux_t *ux, void __user *ubuf) {
> > +	struct usbip_ux_kaddr kaddr = {(void*)ux,
> (void*)(ux->tcp_socket)};
> > +	if (copy_to_user(ubuf, &kaddr, sizeof(kaddr))) {
> > +		return -EFAULT;
> > +	}
> > +	return 0;
> > +}
> 
> Huh?
> 
> > +static int __init usbip_ux_init(void) {
> > +	int ret;
> > +
> > +	usbip_trx_ops_bak = usbip_trx_ops;
> > +	usbip_trx_ops = &usbip_trx_user_ops;
> > +
> > +	INIT_LIST_HEAD(&usbip_ux_list);
> > +	ret = alloc_chrdev_region(&usbip_ux_devno, USBIP_UX_MINOR, 1,
> USBIP_UX_DEV_NAME);
> > +	if (ret < 0) {
> > +		pr_err("Fail to alloc chrdev for %s\n",
> USBIP_UX_DEV_NAME);
> > +		goto err_out;
> > +	}
> > +	cdev_init(&usbip_ux_cdev, &usbip_ux_fops);
> > +	usbip_ux_cdev.owner = usbip_ux_fops.owner;
> > +	ret = cdev_add(&usbip_ux_cdev, usbip_ux_devno, 1);
> > +	if (ret < 0) {
> > +		pr_err("Fail to add cdev: %s\n", USBIP_UX_DEV_NAME);
> > +		kobject_put(&usbip_ux_cdev.kobj);
> > +		goto err_unregister_chrdev;
> > +	}
> > +	usbip_ux_class = class_create(THIS_MODULE, USBIP_UX_CLASS_NAME);
> > +	if (IS_ERR(usbip_ux_class)) {
> > +		pr_err("Fail to create class: %s\n",
> USBIP_UX_CLASS_NAME);
> > +		ret = PTR_ERR(usbip_ux_class);
> > +		goto err_cdev_del;
> > +	}
> > +	usbip_ux_dev = device_create(usbip_ux_class, NULL,
> usbip_ux_devno, NULL, USBIP_UX_DEV_NAME);
> > +	if (IS_ERR(usbip_ux_dev)) {
> > +		pr_err("Fail to create sysfs entry for %s\n",
> USBIP_UX_DEV_NAME);
> > +		ret = PTR_ERR(usbip_ux_class);
> > +		goto err_cdev_del;
> > +	}
> > +	return 0;
> > +err_cdev_del:
> > +	cdev_del(&usbip_ux_cdev);
> > +err_unregister_chrdev:
> > +	unregister_chrdev_region(usbip_ux_devno, 1);
> > +err_out:
> > +	return ret;
> 
> Ouch. What happened to usbip_trx_ops on errors?
> 
> In any case: The whole usbib-ux.ko looks like a special purpose
> chardev<->sock proxy.  Why do that in the kernel?
> 
> 
> > --- a/drivers/usb/usbip/vhci_sysfs.c
> > +++ b/drivers/usb/usbip/vhci_sysfs.c
> > @@ -1,5 +1,6 @@
> >  /*
> >   * Copyright (C) 2003-2008 Takahiro Hirofuchi
> > + * Copyright (C) 2015 Nobuo Iwata
> >   *
> >   * This is free software; you can redistribute it and/or modify
> >   * it under the terms of the GNU General Public License as published
> > by @@ -39,16 +40,17 @@ static ssize_t status_show(struct device *dev,
> > struct device_attribute *attr,
> >
> >  	/*
> >  	 * output example:
> > -	 * prt sta spd dev socket           local_busid
> > -	 * 000 004 000 000         c5a7bb80 1-2.3
> > -	 * 001 004 000 000         d8cee980 2-3.4
> > +	 * prt sta spd dev      socket           ux
> local_busid
> > +	 * 000 004 000 00010002         c5a7bb80                0 1-2.3
> > +	 * 001 004 000 00020003         d8cee980                0 2-3.4
> >  	 *
> >  	 * IP address can be retrieved from a socket pointer address by
> looking
> >  	 * up /proc/net/{tcp,tcp6}. Also, a userland program may remember
> a
> >  	 * port number and its peer IP address.
> >  	 */
> >  	out += sprintf(out,
> > -		       "prt sta spd bus dev socket
> local_busid\n");
> > +		       "prt sta spd dev      socket           "
> > +		       "ux               local_busid\n");
> >
> >  	for (i = 0; i < VHCI_NPORTS; i++) {
> >  		struct vhci_device *vdev = port_to_vdev(i); @@ -59,11
> +61,19 @@
> > static ssize_t status_show(struct device *dev, struct device_attribute
> *attr,
> >  		if (vdev->ud.status == VDEV_ST_USED) {
> >  			out += sprintf(out, "%03u %08x ",
> >  				       vdev->speed, vdev->devid);
> > -			out += sprintf(out, "%16p ",
> vdev->ud.tcp_socket);
> > +			if (vdev->ud.tcp_socket)
> > +				out += sprintf(out, "%16p ",
> vdev->ud.tcp_socket);
> > +			else
> > +				out += sprintf(out, "%016x ", 0);
> > +			if (vdev->ud.ux)
> > +				out += sprintf(out, "%16p ",
> vdev->ud.ux);
> > +			else
> > +				out += sprintf(out, "%016x ", 0);
> >  			out += sprintf(out, "%s",
> dev_name(&vdev->udev->dev));
> >
> >  		} else {
> > -			out += sprintf(out, "000 000 000 0000000000000000
> 0-0");
> > +			out += sprintf(out, "000 00000000
> 0000000000000000 "
> > +					    "0000000000000000 0-0");
> >  		}
> >
> >  		out += sprintf(out, "\n");
> 
> 
> I don't think you can change the format.  And if you are allowed to do
> that:  Please don't break string constants.  Ref CodingStyle Chapter 2:
>   "never break user-visible strings".
> 
> 
> > +struct usbip_ux_kaddr {
> > +	void *ux;
> > +	void *sock;
> > +};
> 
> Is this really compat-safe?
> 
> Note that I haven't really gone through the details in your immplementation.
> Just pointing out a few random details I find unlcear.
> 
> 
> 
> Bjørn
��.n��������+%������w��{.n�����{���)��jg��������ݢj����G�������j:+v���w�m������w�������h�����٥




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux