-
Notifications
You must be signed in to change notification settings - Fork 38
Plugins
MPTCP path management in the Multipath TCP Daemon is implemented through plugins. Concrete path management strategies implement the mptcpd
plugin API. One such example is the single-subflow-per-interface sspi
reference plugin.
mptcpd
leverages the Embedded Linux Library plugin interface for its underlying plugin infrastructure, and consequently expects plugins to use the ELL plugin conventions. At a basic level, this involves calling the ELL L_PLUGIN_DEFINE()
macro with plugin-specific arguments, with the exception of the symbol
argument which must be MPTCPD_PLUGIN_DESC
. At program start mptcpd
will then load all plugins in the plugin directory, and call the init
function used in the L_PLUGIN_DEFINE()
macro.
Plugins define each of the mptcpd plugin API functions found in the mptcpd_plugin_ops
structure, and register those path management operations with mptcpd
in the plugin init
function by calling the mptcpd_plugin_register_ops()
function. These functions each correspond to a specific MPTCP event (e.g. new connection, new subflow, etc.) defined in the Linux kernel MPTCP generic netlink API.
There are times when a plugin may need to alter MPTCP connections or subflows, such as explicitly advertising new network addresses. mptcpd
exposes a path management command API corresponding to the commands defined in the MPTCP generic netlink API that may be leveraged by plugins. The path management command functions are declared in the <mptcpd/path_manager.h>
header.
mptcpd
monitors all MPTCP-capabble network interfaces. Plugins may examine those network interfaces, along with associated network addresses, by retrieving a pointer to the network monitor from the mptcpd_pm_get_nm()
function found in the mptcpd path manager API defined in <mptcpd/path_manager.h>
. Iteration over the monitored network interfaces may then be performed through the mptcpd_nm_foreach_interface()
function declared in the <mptcpd/network_monitor.h>
header.
A very basic implementation for mptcpd
plugin foo
could look like the following:
#include <ell/ell.h>
#include <mptcpd/network_monitor.h>
#include <mptcpd/path_manager.h>
#include <mptcpd/plugin.h>
#define PLUGIN_NAME foo
static void foo_new_connection(mptcpd_token_t token,
struct sockaddr const *laddr,
struct sockaddr const *raddr,
struct mptcpd_pm *pm)
{
// Handle creation of new MPTCP connection.
}
static void foo_connection_established(
mptcpd_token_t token,
struct sockaddr const *laddr,
struct sockaddr const *raddr,
struct mptcpd_pm *pm)
{
// Handle establishment of new MPTCP connection.
}
static void foo_connection_closed(mptcpd_token_t token,
struct mptcpd_pm *pm)
{
// Handle MPTCP connection closure.
}
static void foo_new_address(mptcpd_token_t token,
mptcpd_aid_t addr_id,
struct sockaddr const *addr,
struct mptcpd_pm *pm)
{
// Handle address advertised by MPTCP capable peer.
}
static void foo_address_removed(mptcpd_token_t token,
mptcpd_aid_t addr_id,
struct mptcpd_pm *pm)
{
// Handle address no longer advertised by MPTCP capable peer.
}
static void foo_new_subflow(mptcpd_token_t token,
struct sockaddr const *laddr,
struct sockaddr const *raddr,
bool backup,
struct mptcpd_pm *pm)
{
// Handle new subflow added to the MPTCP connection.
}
static void foo_subflow_closed(mptcpd_token_t token,
struct sockaddr const *laddr,
struct sockaddr const *raddr,
bool backup,
struct mptcpd_pm *pm)
{
// Handle MPTCP subflow closure.
}
static void foo_subflow_priority(mptcpd_token_t token,
struct sockaddr const *laddr,
struct sockaddr const *raddr,
bool backup,
struct mptcpd_pm *pm)
{
// Handle change in MPTCP subflow priority.
}
static struct mptcpd_plugin_ops const pm_ops = {
.new_connection = foo_new_connection,
.connection_established = foo_connection_established,
.connection_closed = foo_connection_closed,
.new_address = foo_new_address,
.address_removed = foo_address_removed,
.new_subflow = foo_new_subflow,
.subflow_closed = foo_subflow_closed,
.subflow_priority = foo_subflow_priority
};
static int foo_init(void)
{
static char const name[] = L_STRINGIFY(PLUGIN_NAME);
if (!mptcpd_plugin_register_ops(name, &pm_ops)) {
l_error("Failed to initialize plugin '%s'.", name);
return -1;
}
return 0;
}
static void foo_exit(void)
{
}
L_PLUGIN_DEFINE(MPTCPD_PLUGIN_DESC,
PLUGIN_NAME,
"foo path management plugin",
VERSION,
L_PLUGIN_PRIORITY_DEFAULT,
foo_init,
foo_exit)
Mptcpd plugins should be built as shared libraries. For example, given a GNU Autotool enabled mptcpd
plugin called "foo
", snippets of the configure.ac
and Makefile.am
could be implemented as follows.
AC_PREREQ([2.69])
AC_INIT([foo_plugin], [0.1])
AM_INIT_AUTOMAKE([foreign])
LT_INIT([disable-static])
AC_CONFIG_SRCDIR([foo.c])
AC_CONFIG_MACRO_DIRS([m4])
# ---------------------------------------------------------------
# Checks for programs.
# ---------------------------------------------------------------
AC_PROG_CC_STDC
AM_PROG_CC_C_O
# ---------------------------------------------------------------
# Checks for libraries.
# ---------------------------------------------------------------
# Find mptcpd.
PKG_CHECK_MODULES([MPTCPD], [mptcpd])
# Determine default mptcpd plugin directory.
PKG_CHECK_VAR([MPTCPD_PLUGINDIR], [mptcpd], [plugindir])
# ---------------------------------------------------------------
# Generate our build files.
# ---------------------------------------------------------------
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
## "plugindir" specifies where plugins should be installed.
## Override as needed if the default mptcpd plugin directory
## is not used.
plugindir = @MPTCPD_PLUGINDIR@
plugin_LTLIBRARIES = foo.la
foo_la_SOURCES = foo.c
foo_la_CFLAGS = $(MPTCPD_CFLAGS)
foo_la_LDFLAGS = -no-undefined -module -avoid-version
foo_la_LIBADD = $(MPTCPD_LIBS)
Plugins should be installed in the plugin directory specified in the mptcpd
configuration file. This normally corresponds to the compile-time default plugin directory (e.g. the result of the command pkg-config --variable=plugindir mptcpd
), but the default could be potentially overridden if the mptcpd
configuration was changed. For example, plugins would be installed in the directory /usr/lib/mptcpd
if the mptcpd
configuration file found at /etc/mptcpd/mptcpd.conf
contains an entry such as the following:
# ----------------
# Plugin directory
# ----------------
plugin-dir=/usr/lib/mptcpd
or installed in the directory specified in the mptcpd
--plugin-dir
command line option. The order of precedence is:
- command line
- configuration file
- compile-time default