aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr/doc/interface.md
diff options
context:
space:
mode:
Diffstat (limited to 'ctrl/facemgr/doc/interface.md')
-rw-r--r--ctrl/facemgr/doc/interface.md358
1 files changed, 358 insertions, 0 deletions
diff --git a/ctrl/facemgr/doc/interface.md b/ctrl/facemgr/doc/interface.md
new file mode 100644
index 000000000..11c8da275
--- /dev/null
+++ b/ctrl/facemgr/doc/interface.md
@@ -0,0 +1,358 @@
+# Face manager : Interfaces
+
+## Overview
+
+The architecture of the face manager is built around the concept of interfaces,
+which allows for a modular and extensible deployment.
+
+Interfaces are used to implement in isolation various sources of information
+which help with the construction of faces (such as network interface and service
+discovery), and with handling the heterogeneity of host platforms.
+
+
+### Platform and supported interfaces
+
+Currently, Android, Linux and MacOS are supported through the following
+interfaces:
+
+- hicn-light [Linux, Android, MacOS, iOS]
+ An interface to the hicn-light forwarder, and more specifically to the Face
+ Table and FIB data structures. This component is responsible to effectively
+ create, update and delete faces in the forwarder, based on the information
+ provided by third party interfaces, plus adding default routes for each of
+ the newly created face. The communication with the forwarder is based on the
+ hicn control library (`libhicnctrl`).
+
+- netlink [Linux, Android]
+ The default interface on Linux systems (including Android) to communicate
+ with the kernel and receive information from various sources, including link
+ and address information (both IPv4 and IPv6) about network interfaces.
+
+- android\_utility [Android only]
+ Information available through Netlink is limited with respect to cellular
+ interfaces. This component allows querying the Android layer through SDK
+ functions to get the type of a given network interface (Wired, WiFi or
+ Cellular).
+
+- bonjour [Linux, Android]
+ This component performs remote service discovery based on the bonjour
+ protocol to discover a remote hICN forwarder that might be needed to
+ establish overlay faces.
+
+- network\_framework [MacOS, iOS]
+
+ This component uses the recommended Network framework on Apple devices,
+ which provided all required information to query faces in a unified API:
+ link and address information, interface types, and bonjour service
+ discovery.
+
+
+### Architectural overview
+
+#### Facelets
+
+TODO:
+- Key attributes (netdevice and protocol family)
+- Facelet API
+
+#### Events
+
+TODO
+
+#### Facelet cache & event scheduling
+
+TODO:
+ - Facelet cache
+ - Joins
+ - How synchronization work
+
+### Interface API
+
+TODO
+
+## Developing a new interface
+
+### Dummy template
+
+The face manager source code includes a template that can be used as a skeleton
+to develop new faces. It can be found in `src/interface/dummy/dummy.{h,c}`. Both
+include guard and specific interface functions are prefixed by a (short)
+identifier which acts as a namespace for interface specific code (in our case
+the string 'dummy\_').
+
+Registration and instanciation of the different interfaces is currently done at
+compile time in the file `src/api.c`, and the appropriate hooks to use the dummy
+interface are avaialble in the code between `#if 0/#endif` tags.
+
+#### Interface template header; configuration parameters
+
+All interfaces have a standard interface defined in `src/interface.{h,c}`, and
+as such the header file is only used to specify the configuration parameters of
+the interface, if any.
+
+In the template, these configuration options are empty:
+```
+/*
+ * Configuration data
+ */
+typedef struct {
+ /* ... */
+} dummy_cfg_t;
+```
+
+#### Overview of the interface template
+
+The file starts with useful includes:
+- the global include `<hicn/facemgr.h>` : this provides public facing elements
+ of the face manager, such the standard definition of faces (`face_t` from
+ `libhicnctrl`), helper classes (such as `ip_address_t` from `libhicn`), etc.
+- common.h
+- facelet.h : facelets are the basic unit of communication between the face
+manager and the different interfaces. They are used to construct the faces
+incrementally.
+- interface.h : the parent class of interfaces, such as the current dummy
+interface.
+
+Each interface can hold a pointer to an internal data structure, which is
+declared as follows:
+```
+/*
+ * Internal data
+ */
+typedef struct {
+ /* The configuration data will likely be allocated on the stack (or should
+ * be freed) by the caller, we recommend to make a copy of this data.
+ * This copy can further be altered with default values.
+ */
+ dummy_cfg_t cfg;
+
+ /* ... */
+
+ int fd; /* Sample internal data: file descriptor */
+} dummy_data_t;
+```
+
+We find here a copy of the configuration settings (which allows the called to
+instanciate the structure on the stack), as well as a file descriptor
+(assuming most interfaces will react on events on a file descriptor).
+
+The rest of the file consists in the implementation of the interface, in
+particular the different function required by the registration of a new
+interface to the system. They are grouped as part of the `interface_ops_t` data
+structure declared at the end of the file:
+
+```
+interface\_ops\_t dummy\_ops = {
+ .type = "dummy",
+ .initialize = dummy_initialize,
+ .finalize = dummy_finalize,
+ .callback = dummy_callback,
+ .on_event = dummy_on_event,
+};
+```
+
+The structure itself is declared and documented in `src/interface.h`
+```
+/**
+ * \brief Interface operations
+ */
+typedef struct {
+ /** The type given to the interfaces */
+ char * type;
+ /* Constructor */
+ int (*initialize)(struct interface\_s * interface, void * cfg);
+ /* Destructor */
+ int (*finalize)(struct interface_s * interface);
+ /* Callback upon file descriptor event (iif previously registered) */
+ int (*callback)(struct interface_s * interface);
+ /* Callback upon facelet events coming from the face manager */
+ int (*on_event)(struct interface_s * interface, const struct facelet_s * facelet);
+} interface\_ops\_t;
+```
+
+Such an interface has to be registered first, then one (or multiple) instance(s)
+can be created (see `src/interface.c` for the function prototypes, and
+`src/api.c` for their usage).
+
+- interface registration:
+
+```
+extern interface\_ops\_t dummy\_ops;
+
+/* [...] */
+
+rc = interface\_register(&dummy\_ops);
+if (rc < 0)
+ goto ERR_REGISTER;
+```
+
+- interface instanciation:
+
+```
+#include "interfaces/dummy/dummy.h"
+
+/* [...] */
+
+rc = facemgr_create_interface(facemgr, "dummy0", "dummy", &facemgr->dummy);
+if (rc < 0) {
+ ERROR("Error creating 'Dummy' interface\n");
+ goto ERR_DUMMY_CREATE;
+}
+```
+
+#### Implementation of the interface API
+
+We now quickly go other the different functions, but their usage will be better
+understood through the hands-on example treated in the following section.
+
+In the template, the constructor is the most involved as it need to:
+
+- initialize the internal data structure:
+
+```
+ dummy_data_t * data = malloc(sizeof(dummy_data_t));
+ if (!data)
+ goto ERR_MALLOC;
+ interface->data = data;
+```
+
+- process configuration parameters, eventually setting some default values:
+
+```
+ /* Use default values for unspecified configuration parameters */
+ if (cfg) {
+ data->cfg = *(dummy_cfg_t *)cfg;
+ } else {
+ memset(&data->cfg, 0, sizeof(data->cfg));
+ }
+```
+
+- open an eventually required file descriptor
+
+For the sake of simplicity, the current API only supports a single file
+descriptor per-interface, and it has to be created in the constructor, and
+set as the return value so as to be registered by the system, and added to the
+event loop for read events. A return value of 0 means the interface does not
+require any file descriptor. As usual, a negative return value indicates an
+error.
+
+```
+ data->fd = 0;
+
+ /* ... */
+
+ /*
+ * We should return a negative value in case of error, and a positive value
+ * otherwise:
+ * - a file descriptor (>0) will be added to the event loop; or
+ * - 0 if we don't use any file descriptor
+ */
+ return data->fd;
+```
+
+While support for multiple file descriptors might be added in the future, an
+alternative short-term implementation might consider the instanciation of
+multiple interface, as is done for Bonjour in the current codebase, in
+`src/api.c`.
+
+Data reception on the file descriptor will get the callback function called, in
+our case `dummy_callback`. Finally, the destructor `dummy_finalize` should close
+an eventual open file descriptor.
+
+In order to retrieve the internal data structure, that should in particular
+store such a file descriptor, all other function but the constructor can
+dereference it from the interface pointer they receive as parameter:
+
+```
+dummy\_data\_t * data = (dummy\_data\_t*)interface->data;
+```
+
+#### Raising and receiving events
+
+An interface will receive events in the form of a facelet through the `*_on_event`
+function. It can then use the facelet API we have describe above to read
+information about the face.
+
+As this information is declared const, the interface can either create a new
+facelet (identified by the same netdevice and protocol family), or eventually
+clone it.
+
+The facelet event can then be defined and raised to the face maanger for further
+processing through the following code:
+```
+ facelet_set_event(facelet, EVENT_TYPE_CREATE);
+ facelet_raise_event(facelet, interface);
+```
+
+Here the event is a facelet creation (`EVENT_TYPE_CREATE`). The full facelet API
+and the list of possible event types is available in `src/facelet.h`
+
+
+#### Integration in the build system
+
+The build system is based on CMake. Each interface should declare its source
+files, private and public header files, as well as link dependencies in the
+local `CMakeLists.txt` file.
+
+TODO: detail the structure of the file
+
+
+### Hands-on example
+
+#### Overview
+
+In order to better illustrate the development of a new interface, we will
+consider the integration of a sample server providing a signal instructing the
+face manager to alternatively use either the WiFi or the LTE interface. The code
+of this server is available in the folder `examples/updownsrv/`, and the
+corresponding client code in `examples/updowncli`.
+
+Communication between client and server is done through unix sockets over an
+abstract namespace (thereby not using the file system, which would cause issues
+on Android). The server listens for client connections, and periodically
+broadcast a binary information to all connected clients, in the form of one byte
+equal to either \0 (which we might interpret as enable LTE, disable WiFi), or \1
+(enable WiFi, disable LTE).
+
+Our objective is to develop a new face manager interface that would listen to
+such event in order to update the administrative status of the current faces.
+This would thus alternatively set the different interfaces admnistratively up
+and down (which takes precedence over the actual status of the interface when
+the forwarder establishes the set of available next hops for a given prefix).
+The actual realization of such queries will be ultimately performed by the
+hicn-light interface.
+
+#### Sample server and client
+
+In the folder containing the source code of hICN, the following commands allow
+to run the sample server:
+
+```
+cd ctrl/facemgr/examples/updownsrv
+make
+./updownsrv
+```
+
+The server should display "Waiting for clients..."
+
+Similar commands allow to run the sample client:
+```
+cd ctrl/facemgr/examples/updowncli
+make
+./updowncli
+```
+
+The client should display "Waiting for server data...", then every couple of
+seconds display either "WiFi" or "LTE".
+
+#### Facemanager interface
+
+An example illustrating how to connect to the dummy service from `updownsrv` is
+provided as the `updown` interface in the facemgr source code.
+
+This interface periodically swaps the status of the LTE interface up and down.
+It is instanciated as part of the facemgr codebase when the code is compiled
+with the ``-DWITH_EXAMPLE_UPDOWN` cmake option.
+
+
+