machyve / xhyve

xhyve, a lightweight OS X virtualization solution
Other
6.44k stars 353 forks source link

RFC: generic user-mode networking driver using popen() (and tweaked slirp) #123

Open ayourtch opened 7 years ago

ayourtch commented 7 years ago

Hi all,

This is not really an issue but more a request for comments.

First, what I have done:

I've experimented a little bit with adding user-mode support with slirp (the original one - I slightly tweaked it to compile and work on 64-bit), and wanted to share some experiences here and solicit the feedback if this is interesting for the community.

First, the slirp itself. It has very clever way of sharing the space between the packet headers and pointers, which assumes the pointers are always less than or equal to 32 bit. Luckily the conditional code that triggers on "sizeof(void *) != 32" does a lot of casting between int32 and pointer, which triggers a nice set of warnings pointing all the places in the code where the transition happens.

So I opted for something that is in principle an UB, but in practice worked fairly well: make two functions - int32_to_ptr and ptr_to_int32, and have them use a static variable that is a result of a malloc(100), as a base for conversion. Turns out all the dynamic allocations are within +/-2GB of each other so that worked quite beautifully from all the practical purposes.

Nonetheless, it is Undefined Behavior, so I did not want to couple this source with xhyve, so I came up with an idea of how to use it: write a networking driver for xhyve which would accept a program name as a parameter, then would launch the program using popen(), and write the packets coming from the guest into its stdin, and send everything that comes from program's stdout to the guest.

Of course the writes can be buffered together so I used a trivial framing with length of the packet in front of it and after it for the extra resiliency (they both have to match, of course, for this to be detected a valid packet).

After making a similar driver for the slirp (with an extremely simplistic ethernet encapsulator and ARP responder), I compiled slirp under OSX and tried this all out.

Turned out this contraption worked reasonably well: I could get about 10-15mbps throughput, I could forward the ports on the loopback to the guest.

Still not enough performance for me since I fullscreen VNC into the linux guest from my Mac, and on retina it is a lot of pixels - but I will try to use large frames and see what happens.

Why I am writing here:

I was experimenting on a fairly xhyve tree (just upgraded to Sierra yesterday), so will need to redo the exercise - and I was curious whether this xhyve network driver with popen and stdio writes would be useful to contribute to the xhyve. Probably the I/O format could be documented and used for other backends in the future - this "halved" abstraction should make it much easier to work, though might be at an impact to performance.

(I will put the slirp with UB hack of 32-bit pointers on my GitHub, but it does not have to be coupled nor in the future it has to be slirp - it can be something else. I would like to add IPv6 support at some point so don't want to proliferate what feels to be quite IPv4-specific code)