qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH V4 0/7] CAN bus support for QEMU (SJA1000 PCI so


From: Pavel Pisa
Subject: Re: [Qemu-devel] [PATCH V4 0/7] CAN bus support for QEMU (SJA1000 PCI so far)
Date: Thu, 25 Jan 2018 22:33:45 +0100
User-agent: KMail/1.9.10 (enterprise35 0.20100827.1168748)

Hello Paolo,

thanks for suggestions. I understand and fully agree with your
request to switch to QOM. I have succeed with that for CAN devices
some time ago. It worth to be done for the rest of the objects
but I fear that I do not find time to complete QOMification
in reasonable future. Contributions/suggestions from other
are welcomed. I can look for students for GSoC at our university
or under other funding.

On Thursday 25 of January 2018 14:58:41 Paolo Bonzini wrote:
> On 23/01/2018 22:42, Pavel Pisa wrote:
> > Do you think QOM based? I would like it to be implemented
> > that way but I need some assistance where to look how this
> > object kind should be implemented and from which base object
> > inherit from. But I prefer to left that for later work.
> >
> > I would definitely like to use some mechanism which allows
> > to get rid of externally visible pointer and need to assign
> > it in the stub. It has been my initial idea and your review
> > sumbled across this hack as well. But I need suggestion what
> > is the preferred way for QEMU.
>
> The best way would be a QOM object.  That is, you would do
>
>    -object can-bus,id=canbus0
>    -object can-host-socketcan,id=can0-host,canbus=canbus0,if=can0
>    -device kvaser_pci,canbus=canbus0

I would prefer to allow CAN emulation to be used without
explicit can-bus object creation specified on the command line.
The bus object could be created when requested by
can-host-socketcan or device (kvaser_pci) automatically.

When multiple QOM object are put on the list then the list content
should be preserved over save+restore (mostly hypothetical question
for now). There should be probably used some other construct instead
of

  QTAILQ_HEAD(, CanBusClientState) clients;
  QTAILQ_ENTRY(CanBusState) next;

> In the current version, it's not clear to me:
>
> * what it means if multiple controllers have the same canbus

That is fully supported and sane configuration.
CAN is publis/subscribe network in principle
so sending message from one controller to another
one on the host side is intended and can be used
to test drivers even if host connection is
not available/supported on given OS/setup.
Interconnection of multiple controllers with
host CAN bus is functional as well.

> * what it means if multiple controllers with the same canbus have
> different host interfaces

It is legitimate but probably not much usesfull/intended setup.
It would result is bridging two host CAN busses
together. It would work because SocketCAN does not
deliver message back to the socket which has been used to send
it by default. Connecting twice to the same SocketCAN bus
would lead to infinite message loop.

Connection of given can bus to the host twice can be prevented
if host connection flag is included in CanBusState and if it is
already set then next host connection attempt would be reported
as error.

> Separating the QOM objects is a bit more work, but it makes the
> semantics clearer.  The classes would be:
>
> - can-bus and an abstract class can-host, which would inherit directly
> from TYPE_OBJECT and implement TYPE_USER_CREATABLE
>
> - can-host-socketcan, which would inherit from can-host (and take the
> TYPE_USER_CREATABLE implementation from there)
>
> while CanBusClientState and CanBusClientInfo need not be QOMified.

May it be, can-host-socketcan can be based directly on TYPE_OBJECT,
because only QEMU CAN bus specific part is CanBusClientState which
allows it to connect to the CAN bus same way as other CAN controllers
connect to the bus.

> can-host's class structure would define a function pointer corresponding
> to what you have now for the function pointer, more or less---except
> that allocation is handled by QOM and the method only has to do the
> connection.  You would have something like this:
>
> static void can_host_disconnect(CANHost *ch, Error **errp)
> {
>     CANHostClass *chc = CAN_HOST_GET_CLASS(ch);
>
>     chc->disconnect(ch);
> }
>
> static void can_host_connect(CANHost *ch, Error **errp)
> {
>     CANHostClass *chc = CAN_HOST_GET_CLASS(ch);
>     Error *local_err = NULL;
>
>     chc->connect(ch, &local_err);
>     if (local_err) {
>         error_propagate(errp, local_err);
>         return;
>     }
>
>     can_bus_insert_client(ch->bus, &ch->bus_client, local_err);
>     if (local_err) {
>         can_host_disconnect(ch);
>         error_propagate(errp, local_err);
>         return;
>     }
> }
>
> and TYPE_USER_CREATABLE's "complete" method would simply invoke
> can_host_connect.  For can-host-socketcan, chc->connect would be
> assigned something like this:
>
> static void can_host_socketcan_connect(CANHost *ch, Error **errp)
> {
>     CANHostSocketCAN *chs = CAN_HOST_SOCKETCAN(ch);
>
>     s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
>     if (s < 0) {
>         error_setg_errno(errp, errno "CAN_RAW socket create failed");
>         return;
>     }
>
>     addr.can_family = AF_CAN;
>     memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
>     strcpy(ifr.ifr_name, chs->host_dev_name);
>     if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
>         error_setg_errno(errp, "host interface %s not available",
>                          chs->host_dev_name);
>         goto fail;
>     }
>     addr.can_ifindex = ifr.ifr_ifindex;
>     ....
> }

Thanks for providing ideas for future development directions.

> In particular, note the difference in error reporting with
> error_report/exit vs. error_setg/error_propagate.  Any call to "exit" is
> probably grounds for instant rejection of your patch. :)

It seems that it is necessary to switch to use realize()
method instead of init() to have initial **errp pointer
in the call chain.

> This also means that you have to check for leaks in the failure paths,
> such as  forgetting to close the PF_CAN socket.

The socket is closed in can_bus_socketcan_cleanup()
in the failure case. g_free(c->rfilter); is there
as well.

Thanks for ideas and review,

Pavel



reply via email to

[Prev in Thread] Current Thread [Next in Thread]