Skip to content

Instantly share code, notes, and snippets.

@rpedde
Last active August 29, 2015 13:56
Show Gist options
  • Save rpedde/8927215 to your computer and use it in GitHub Desktop.
Save rpedde/8927215 to your computer and use it in GitHub Desktop.
network thoughts

Requirements

  • Minimize code and deps in ZeroVM proper
  • Make the back-end networking implementation interchangeable
  • Make the back-end services extensible

Proposal

The problem of implementing a networking interface to ZeroVM breaks down into two separate but related problems:

  • Defining an interface protocol between ZeroVM and a broker
  • Defining the back-end network implementation that wires ZeroVM instances together

There has been much disagreement about the best method of solving both of these problems. Some of the areas of disagreement revolve around whether or not the interface protocol requires a local broker versus a centralized remote broker, preferred protocols for the interface protocol and/or the back-end network protocol, etc.

A good interface boundary would allow these decisions to be made as an implementation decision, and allow any manner of both interface protocol and back-end network implementation.

Based on some conversations and ideas raised by Cam, I would propose that the proper interface boundary between ZeroVM and an arbitrary broker should be a programming API, not a specific application protocol over a specific transport.

Details

Given that a network stream is functionally identical to a non-stream-able local file, like a named pipe, it makes sense to make a library or API contract around network streams that behave like named pipes. Specifically, the API contract provides four functions (naming up for debate) declared in zvm.h:

struct netpipe_t;
typedef struct netpipe_t netpipe_t;

extern netpipe_t *netpipe_open(const char *descriptor);
extern int netpipe_close(netpipe_t *pipe);
extern int64_t netpipe_read(netpipe_t *pipe, void *buf, int32_t count);
extern int64_t netpipe_write(netpipe_t *pipe, void *buf, int32_t count);

descriptor in this case would be an opaque back-end-specific identifier for the remote pipe, as specified in the manifest. At a minimum, a descriptor would have to provide enough information to be able to:

  • Determine direction of the pipe (read or write)
  • Provide enough information to be able to locate the remote instance. This might be a combination of broker id and instance name, or, if the back-end supports some sort of auto-discovery, merely an instance name.

These symbols would be provided by a "glue" library that would interface with the implementation-specific broker. This library would be linked to ZeroVM to implement a particular back-end network strategy. This would imply that for a first-pass implementation, there could only be one network back-end, and further that this back-end would be required to be specified at compile-time.

From a ZeroVM perspective, these netpipes would look very much like a local file, and would in fact provide the same semantics as a named pipe. Specifically:

  • Writes to a netpipe block until a reader connects
  • Reads from a netpipe block until data has been submitted by a writer
  • When the pipe has been exhausted and the last writer disconnects, reads return 0
  • When writing to a pipe that the reader has disconnected from, write returns EPIPE

Multiple readers and writer behavior is unspecified, and may be implementation specific. Atomicity of writes is therefore also unspecified.

Manifest

Specifying a netpipe in the manifest would be a matter of identifying the channel as a netpipe channel, and passing the opaque descriptor in a format specified by the back-end implementation.

Example:

Channel = Netpipe:<opaque_descriptor>, /dev/out/net, 0, 1, 0, 0, 100, 1000
Channel = Netpipe:<opaque_descriptor>, /dev/in/net, 0, 1, 100, 1000, 0, 0

For example, a naive network implementation might require the IP address of the remote broker, a pipe direction ("r" or "w"), and the node id of the remote instance. In this case, the descriptor might look like this:

Channel = Netpipe:192.168.0.1:2:w, /dev/out/net, 0 1, 0, 0, 100, 1000

In this case, ZeroVM itself would get a new opaque pipe descriptor with a call like this:

netpipe_t *np = netpipe_open("192.168.0.1:2:w");

Note that ZeroVM itself makes no attempt to parse the opaque descriptor, it is passed in directly as specified in the manifest.

ZeroVM Impact

Of the requirements specified above:

  • Minimize code and deps in ZeroVM proper
  • Make the back-end networking implementation interchangeable
  • Make the back-end services extensible

This meets the second two criteria. In addition, it meets the additional criteria of making the ZeroVM to broker protocol interchangeable.

The first criterion: "Minimize code and deps in ZeroVM proper", is now no longer a requirement on ZeroVM. It is the responsibility of the implementer to ensure that the linked code is both small and error free.

Future

I can imagine a future extension of this approach that would allow for a pluggable vfs-like implementation of netpipe-like providers. These plugins would register a vtable for specific protocols, with the vtable providing common fileish operations (open, close, read, write, truncate, seek, tell, seekable?, readable?, writable?, etc)

In this case, more complex protocols (http, ftp, torrent, peer-to-peer connections, whatever) could be realized, and what protocols are available could be controlled by the provider by limiting what pluggable libraries they choose to load in ZeroVM.

@rpedde
Copy link
Author

rpedde commented Mar 20, 2014

Dmitri - oops. Yes, I'm sorry, you are absolutely correct. It should really be in a zerovm/vfs.h or something, I suppose, so people could develop external vfs laters.

I'd also like to think about the possibility of making ZeroVM a library, and having a public trusted interface so people could wrap ZeroVM at the library level. Then they could make a mod_zerovm apache module, or a nginx plugin, or query plugins for redis or something like that.

@bortoq
Copy link

bortoq commented Mar 23, 2014

by the way, zerovm has space preallocation. it is enabled by default, but it can be disabled with "-P" command line switch. it will extend channels api. and another question: how to pass broker's path? each time on channel opening?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment