Skip to content

The unified API for the Internet of Threads

License

LGPL-2.1, GPL-2.0 licenses found

Licenses found

LGPL-2.1
COPYING
GPL-2.0
COPYING.test
Notifications You must be signed in to change notification settings

virtualsquare/libioth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libioth

The unified API for the Internet of Threads

  • the API is minimal: Berkeley Sockets + msocket + newstack/delstack.
  • the stack implementation can be chosen as a plugin at run time.
  • netlink based stack/interface/ip configuration via nlinline.
  • ioth sockets are real file descriptors, poll/select/ppoll/pselect/epoll friendly
  • plug-ins are loaded in private address namespaces: libioth supports several stacks of the same type (same plugin) even if the stack implementation library was designed to provide just one stack.

Compile and Install

Pre-requisites: fduserdata, nlinline.

Libioth uses cmake. The standard building/installing procedure is:

mkdir build
cd build
cmake ..
make
sudo make install

An uninstaller is provided for your convenience. In the build directory run:

sudo make uninstall

The API

newstack

There are three flavours of ioth_newstack:

struct ioth *ioth_newstack(const char *stack, const char *vnl);
struct ioth *ioth_newstackl(const char *stack, const char *vnl, ... /* (char  *) NULL */);
struct ioth *ioth_newstackv(const char *stack, const char *vnlv[]);
  • ioth_newstack creates a new stack without any interface if vnl is NULL, otherwise the new stack has a virtual interface connected to the vde network identified by the VNL (Virtual Network Locator, see vdeplug4 ).
  • ioth_newstackl and ioth_newstackv (l = list, v = vector) support the creation of a new stack with several interfaces. It is possible to provide the VNLs as a sequence of arguments (as in execl) or as a NULL terminated array of VNLs (as the arguments in execv).

The return value is the ioth stack descriptor, NULL in case of error (errno provides the caller with a more detailed description of the error).

delstack

int ioth_delstack(struct ioth *iothstack);

This function terminates/deletes a stack. It returns -1 in case of error, 0 otherwise. If there are file descriptors already in use, this function fails and errno is EBUSY.

msocket

int ioth_msocket(struct ioth *iothstack, int domain, int type, int protocol);

This is the multi-stack supporting extension of socket(2). It behaves exactly as socket except for the added heading argument that allows the choice of the stack among those currently available (previously created by a ioth_newstack*.

default stack

void ioth_set_defstack(struct ioth *iothstack);
struct ioth *ioth_get_defstack(void);

These functions define and retrieve the default stack, respectively.

The default stack is implicitely used by ioth_msocket when its first argument iothstack is NULL.

The default stack is initially defined as the native stack provided by the kernel. Use ioth_set_defstack(mystack) to define mystack as the current default stack. ioth_set_defstack(NULL) to revert the default stack to the native stack.

socket

int ioth_socket(int domain, int type, int protocol);

ioth_socket opens a socket using the default stack: ioth_socket(d, t, p) is an alias for ioth_msocket(NULL, d, t, p)

for everything else... Berkeley Sockets

ioth_close, ioth_bind, ioth_connect, ioth_listen, ioth_accept, ioth_getsockname, ioth_getpeername, ioth_setsockopt, ioth_getsockopt, ioth_shutdown, ioth_ioctl, ioth_fcntl, ioth_read, ioth_readv, ioth_recv, ioth_recvfrom, ioth_recvmsg, ioth_write, ioth_writev, ioth_send, ioth_sendto and ioth_sendmsg have the same signature and functionalities of their counterpart without the ioth_ prefix.

extra features for free: nlinline netlink configuration functions

nlinline+ provides a set of inline functions for the stack interface/ip address and route configuration:

int ioth_if_nametoindex(const char *ifname);
int ioth_linksetupdown(unsigned int ifindex, int updown);
int ioth_ipaddr_add(int family, void *addr, int prefixlen, unsigned int ifindex);
int ioth_ipaddr_del(int family, void *addr, int prefixlen, unsigned int ifindex);
int ioth_iproute_add(int family, void *dst_addr, int dst_prefixlen, void *gw_addr,
    unsigned int ifindex);
int ioth_iproute_del(int family, void *dst_addr, int dst_prefixlen, void *gw_addr,
    unsigned int ifindex);
int ioth_iplink_add(const char *ifname, unsigned int ifindex, const char *type,
    const char *data);
int ioth_iplink_del(const char *ifname, unsigned int ifindex);
int ioth_linksetaddr(unsigned int ifindex, void *macaddr);
int ioth_linkgetaddr(unsigned int ifindex, void *macaddr);

a detailed description can be found in nlinline(3).

License management.

liblwip verifies that the program and the stack implementation plugin have compatible licenses.

A program can specify its license by the ioth_set_license function. Licenses are encoded using SPDX. e.g.:

#define SPDX_LICENSE "SPDX-License-Identifier: GPL-2.0-or-later"
...
    ioth_set_license(SPDX_LICENSE);

If a program does not specify its license it can load a stack plugin only if the plugin can be linked to proprietary programs.

The license of a plugin is defined by a global variable named ioth_xxxx_license (where xxxx is the name of the plugin). e.g.:

const char *ioth_vdestack_license = "SPDX-License-Identifier: LGPL-2.1-or-later";

or

const char *ioth_picox_license = "SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only";

If a plugin does not specify any license tag it means that has no license requirements.

Note: the current implementation of the license checker supports the following plugin licenses: LGPL-*, GPL-2.0-or-later, GPL-3.0-or-later, GPL-2.0-only OR GPL-3.0-only.

Example: an IPv4 TCP echo server

The complete source code of this example is provided in this git repository: iothtest_server.c. The code creates a virtual stack, activates the interface named vde0, sets the interface's address to 192.168.250.50/24 and runs a TCP echo server on port 5000.

When a new connection begins, i.e. when accept(2) returns a new file descriptor, iothtest_server creates a thread to process the new stream.

Example: an IPv4 TCP terminal client

The complete source code of this example is provided in this git repository: iothtest_client.c. The code creates a virtual stack, activates the interface named vde0, sets the interface's address to 192.168.250.51/24 and runs a TCP terminal emulation client trying to get connected to 192.168.250.50 port 5000.

Please note that iothtest_client.c uses a poll(2) system call to wait for available input on a ioth socket and on stdin.

testing

  • start a vde switch:
     vde_plug null:// switch:///tmp/sw
  • in a second terminal run the server using one of the following commands:
     ./iothtest_server vdestack vde:///tmp/sw
     vdens vde:// ./iothtest_server kernel
  • in a third terminal run the client, again the stack implementation can be decided by choosing one of the following commands:
     ./iothtest_client vdestack vde:///tmp/sw
     vdens vde:// ./iothtest_client kernel
  • now whatever is typed in the client is echoed back, the serveer produces a log of open/closed connections and echoed messages.

The API for plugin development

The structure of the source code a ioth plugin for the stack foo is the following:

file ioth_foo.c:

#include <ioth.h>

static typeof(getstackdata_prototype) *getstackdata;

void *ioth_foo_newstack(const char *vnlv[], struct ioth_functions *ioth_f) {
    // create a new foo stack and save some data for the other functions
    struct vdestack *stackdata = ...

    // save getstackdata for the other functions
    getstackdata = ioth_f->getstackdata;

    // set the handler for all the functions
    // example 1: use the system call
    ioth_f->bind = bind;

    // example 2: provide a specific function (implicit assignment).
    // just name the function as ioth_foo_bind.
    // in such a case the  following assignment is automatic:
    // ioth->bind = ioth_foo_bind;

    // example 2: provide a specific function (explicit assignment)
    ioth_f->bind = mybind;

    .... and so on for all the other functions
     return stackdata;
}

int ioth_foo_delstack(void *stackdata) {
  // delete the foo stack
  return .... // 0 = success, -1 = failure (+ errno)
}

// example for socket
int ioth_foo_socket(int domain, int type, int protocol) {
  struct foodata *stackdata = getstackdata();
  return foo_msocket(stackdata, domain, type, protocol);
}

This plugin can be compiled using the following command:

gcc -o ioth_foo.so -fPIC -shared ioth_foo.c

The plugin does not need any ioth specific library.

The plugin ioth_foo.so must be installed:

  • in the global plugin directory: /usr/lib/ioth or /usr/local/lib/ioth or /usr/lib/x86_64-linux-gnu/ioth (or similar) depending on where libioth.so is installed (/usr/lib or /usr/local/lib or /usr/lib/x86_64-linux-gnu respectively).
  • in the user local directory: the hidden subdirectory named .ioth of the user's home directory.

When libioth is required to create a new stack of type foo, it loads the plugin named ioth_foo.so. If the plugin has a -r suffix in its name (e.g. ioth_foo-r.so) it means that the plugin is reentrant, it is able to manage several stacks concurrently in the same address space (otherwise libioth creates a new memory address space for each stack).

When the plugin has been loaded, ioth searches and runs the function ioth_foo_newstack passing it two parameters: the array on VNLs to define the virtual interfaces, and a structure whose fields are function pointers: ioth_functions. This structure includes getstackdata, newstack, delstack and all the functions of the Berkeley Sockets API.

The function getstackdata is provided by libioth and can be saved (all the other function can call getstackdata() to retrieve the pointer returned by ioth_foo_newstack).

All the other function pointers (except getstackdata) can be assigned to their implementation. Alternatively, if the plugin defines functions prefixed by ioth_foo_, these are automatically recognized and used.

About

The unified API for the Internet of Threads

Resources

License

LGPL-2.1, GPL-2.0 licenses found

Licenses found

LGPL-2.1
COPYING
GPL-2.0
COPYING.test

Stars

Watchers

Forks

Packages

No packages published