How to use the in-qemu API for virtio serial device - linux

I want to exchange "complex" data (hierarchical structs) between the guest and the host in a KVM+Qemu setup.
My idea was to use the virtio serial driver to do so. A guest application would use the normal I/O functions such as open(2), close(2), read(2) and write(2) to send the "buffer" (=the struct I want to send) to the virtio serial back-end. The back-end driver would run inside Qemu and receive the pointer to the struct through the in-qemu host API described here: http://www.linux-kvm.org/page/Virtio-serial_API
My question now may be relatively trivial, but I was looking around all over Google and couldn't find anything: How do I "hook into qemu" such that I can use the virtio serial host API?
I understand that I have to provide an init function like void my_init(void) { virtio_serial_port_qdev_register(&myinfo); } and register it with qemu using device_init(&my_init). However, I do not understand how I link my module with qemu? Do I have to add my source files to the qemu code base and makefiles and recompile qemu? Or can I compile it separately and use some magic qemu command line option to load it? Or something completely different?
(Note: I know that I could optionally serialize my data, send it to a socket on the host, and de-serialize it there, but I wanted to avoid the serialization overhead. If there is a way to use a shared memory region instead of a socket with an out-of-the-box virtIO serial device, this could be an option, too).
Thank you all for your help!
Christoph

you can start vm using
qemu-system-x86_64 -m 1024 -name mac -hda ~/Documents/ubuntu -device virtio-serial -chardev socket,path=/tmp/foo,server,nowait,id=foo -device virtconsole,name=jobsfoo,chardev=foo,name=org.fedoraproject.console.foo
and transfer data by using
socat /tmp/foo (host)
socat /tmp/hvc0 (guest)
or you can use socket program on host and simple file i/o on guest

on the host side a serial port can be attached to a pipe or socket using the "-chardev" option. If you specify for example "-chardev socket,path=/tmp/foo.sock,server,nowait,id=foo", you can connect a virtio-serial port to that socket with "-device virtserialport,chardev=foo". You do not need to modify QEMU (or I don't understand what you want to do).

Related

Retrieve variable (or state file) from remote host using telnet?

I have wifi module as client that connected to my router (linux based firmware, Openwrt).
And sometime, i need to retrieve GPIO state from wifi module. It can be done simply by connect in to usb serial and type
print (gpio.read(1))
It will return value 1 or 0. Active or not.
The thing is, can i save the value of gpio to my openwrt through telnet?
Using ash or bash maybe?
I've succesfully connected to wifi module using telnet and execute command via telnet.
Many thanks :)
Note :
-my module wifi is esp8266-07,
-Router HW Echolife HG553 (openwrt,Debian based linux)
Linux doesn't provide us with any "standardtized" solution.
You would need to implement some kind of interface, e.g. service that will read data and make nicely structured JSON file, which is shared over HTTP, so you can read and parse it.

linux network drivers --- net_device_ops

so far i have only used file operational structure in device driver.
Using system call open & read , write.
How to open device driver & transmit data using net_device_ops ?
Is there reference example on net for the user program to interact with it ?
http://lnxpps.de/rpie/mcp2515_mod.c
I'm not sure I understand the question, so let me know if my answer doesn't make sense.
I see you have defined functions for .ndo_open, .ndo_stop, and .ndo_start_xmit. .ndo_open is called by the kernel when you configure the interface using ifconfig up or use ifconfig to assign an address to the interface. .ndo_stop is called by the kernel when you remove the module or if you shutdown the interface using ifconfig down.
ifconfig is described here: http://linux.die.net/man/8/ifconfig
.ndo_start_xmit is called by the kernel network stack when a socket is used to transmit a packet. So, to transmit data using .ndo_start_xmit you'll need to create a socket, assign an appropriate destination address, and send the data via the socket. If you're using IP, there are tools you can use send packets easily, such as netperf or iperf.

How create a virtual io device in Linux that proxies data to real device?

I have an interesting problem. I am working on an embedded box with multiple instances of Linux running each on an ARM processor. They are connected over internal 1GBps network. I have a serial port device node attached to processor A (Lets say Linux-A running on it). I have a program running on processor B (Lets say on Linux-B) access the serial port device as if it is attached to Linux-B locally.
My program invokes term i/o type api calls on device node to control tty echo, character mode input. What I am wondering is if there is a way to create a virtual serial device that is available on Linux-B somehow talking to real serial device on Linux-A over internal network.
I am thinking something along the lines of:
Linux-B has /dev/ttyvirtual. Anything that gets written to it gets transported over network socket to Linux-A serialserver. The serial server exrcises the api calls on real device lets say /dev/ttys0.
Any data waiting on ttys0 gets transported back to /dev/ttyvirtual.
What are all the things involved to get this done fast?
Thanks
Videoguy
Update:
I found a discussion at
http://fixunix.com/bsd/261068-network-socket-serial-port-question.html with great pointers.
Another useful link is http://blog.philippklaus.de/2011/08/make-rs232-serial-devices-accessible-via-ethernet/
Take a look at openpty(3). This lets you create a pseudo-TTY (like /dev/pts/0, the sort that ssh connections use), which will respond as a normal TTY would, but give you direct programmatic control over the connections.
This way you can host a serial device (eg. /dev/pts/5) that you forward data between a network connection, and then other apps can perform serial operations on it without knowing about the underlying network bridge.
I ended up using socat
Examples can be found here: socat examples
You socat back to back on both the machines. One listens on a tcp port and forwards data to local virtual port or pty. The socat on other box uses real device as input and forwards any data to tcp port.

Coding for Ethernet PHY Loopback Test

I have to write a Ethernet PHY loopback test in Linux. I've never done it before and had no clue where to start. After some researching, I came up with the plan for the test, and I wonder if anyone can help me to verify it and give me some pointers to my questions.
This is a external loopback setup. It connects the TX+/- to RX+/- pins for each internal PHY's on the Ethernet switch chip.
So the loopback high level packet path is as follow:
CPU->PHY0(chip)->Ethernet switch(chip)'s internal PHY->PHY0(chip)->CPU
For this test, I plan to
configure the internal PHYs on the Ethernet switch with specific MAC addresses,
pack the Ethernet test packet using CPU's MAC address as the source address and the
MAC address configured in step 1. as the destination address,
send and wait to receive the test packet,
compare sent and received data pattern.
Any suggestions? Also, I wonder if there are functions in Linux that I can use to generate the packets for step 2, and send the packets for step 3.
Thank you very much.
Most Phys can be switched to a test mode. We used the bootloader to write directly to the
Phy and switch to testing mode.
There is also an ioctl taken from documentation/networking/phy.txt
Ethtool convenience functions.
int phy_mii_ioctl(struct phy_device *phydev,
struct mii_ioctl_data *mii_data, int cmd);
The MII ioctl. Note that this function will completely screw up the state
machine if you write registers like BMCR, BMSR, ADVERTISE, etc. Best to
use this only to write registers which are not standard, and don't set off
a renegotiation.

Binary data over serial terminal

My only way of communication with my embedded device is a serial port. By default, embedded Linux uses this port as a terminal. How do I disable this terminal and use the serial link to transfer binary data? I heard of commands like rx and tx but i cannot find them.
I think I can just read() from and write() stuff to /dev/tty but I want to make sure no error messages or whatever mess with my data stream.
You can use an application like xmodem to transfer file over any terminal. Is the serial port you speak off a terminal, or is it also the kernel console.
If you're kernel is not noisy, then you can use your current connection to make xmodem like transfer. On the host side, you can use kermit, which is nice AND scriptable.
If you want to make your serial port raw, and you have file descriptor ttyfd opened,
here is one way to do it :
struct termios tty, orig_tty;
...
if(tcgetattr(ttyfd, &tty) < 0)
{
// error checking
}
// backup tty, make it raw and apply changes
orig_tty = tty;
cfmakeraw(&tty);
if(tcsetattr(ttyfd, TCSAFLUSH, &tty) < 0)
{
// error checking
}
...
//end of program or error path :
tcsetattr(ttyfd, TCSAFLUSH, &orig_tty)
Don't forget to restore the setting at the end of your program if you still want a good behaved terminal.
Can't you just set the terminal to raw?
Have a look at this tutorial.
To disable the Linux console you have to change the Linux command line create by the bootloader from :
console=/dev/ttyS?
to :
console=null
You can run on the terminal a command that will transfer the data through an application-level protocol. The rx and tx commands you refer to implement the XMODEM file transfer protocol. It could be a solution, if the binary data you want to transfer consists of files, the throughput demands are low, and you don't mind the administrative overhead of running the commands. Alternatively, you may want to multiplex the serial port for handling both data transfer and the terminal. Disable the serial terminal driver command (getty), and run the PPP protocoll over the serial line to establish an IP connection to your device. You can then login to the device through ssh or telnet and transfer your data through an IP socket.
As the other notes have implied, there are several things to check, collected here:
Make sure the linux kernel isn't using the serial port. Make sure there is either no console= option on the bootload command in your grub file. It usually isn't there by default.
Make sure there is no getty running on the serial port. Look in /etc/inittab for an entry for /dev/ttyS0 (serial port A) and comment it out if it is there.
Make sure the /dev/ttyS0 is readable and writable by your process. You might create a specific user under which the control program is run, and which owns the /dev/ttyS0, then chmod 700 /dev/ttyS0. This will help make sure some other user/program doesn't also try using the serial port.
Use open() on ttyS0 to get an fd, then use the tcsetattr family of routines to set the line speed and discipline.
Terminal programs probably won't be useful to you unless you can run the same program on the embedded device to manage the other end of the connection.
Yes, all of your serial ports are in /dev/ttyxx. Note that /dev/tty is a shortcut that stands for your current terminal, not a specific serial port. Often, these are owned by root, and require you to either have privileges or be in the adm group to access the device directly from your application.
You may want to chown the device so you can access it. I'm not sure what the consequence of changing device ownership are; IIRC, it's easy to do and works nicely. The alternative is to use setuid to elevate your program to a privileged state.
There's a program named getty that lets users login from a serial port. Your inittab will start getty on serial ports so people can login.
You want to disable getty. In some cases, there's a port manager that helps do this.
In some cases, you can change your inittab to use mgetty, which is a smarter and easier to control version of getty.

Resources