-
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. For more details about the MPTCP path-manager, please see this global overview.
Note that the upstream MPTCP kernel implementation currently has two path-managers controllable via the net.mptcp.pm_type
sysctl, and mptcpd
can control both of them:
- The in-kernel one (
0
, default): the same rules are applied to all connections. Address endpoints and limits can be set from the userspace to control its behavior, see the address-advertiseradd_adv
reference plugin. - The userspace one (
1
): different rules can be applied for each connection for advanced custom behaviour. The path-manager will then need to be controlled by a userspace daemon, see the single-subflow-per-interfacesspi
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-capable 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