Git Product home page Git Product logo

mptcpd's People

Contributors

dcaratti avatar dddaniel avatar dulive avatar matttbe avatar mjmartineau avatar ossama-othman avatar pabeni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mptcpd's Issues

C++ build test exhibits _FORTIFY_SOURCE warning

Describe the bug
Compilation of the test-xcxx-build mptcpd test triggers a gcc preprocessor warning related to insufficient optimization to support gcc's _FORTIFY_SOURCE feature.

To Reproduce
Steps to reproduce the behavior:

  1. ./configure --enable-debug
  2. make check

Expected behavior
No warning should occur when building test-cxx-build.

Screenshots

                 from ../../tests/test-cxx-build.cpp:12:
/usr/include/features.h:397:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp]
  397 | #  warning _FORTIFY_SOURCE requires compiling with optimization (-O)
      |    ^~~~~~~

Desktop (please complete the following information):

  • Linux Kernel: 5.8.9
  • Compiler: gcc 10.2.1
  • Distribution: Fedora Core 32

How can the path manager immediately create or close a subflow when the network monitor listens for a change in the network interface or network address?

MPTCPD is an amazing project. I'm trying to use it. I want to write a plugin similar to mptcp_fullmesh. The plugin needs to create or destroy the subflow by listening for changes in the network interface or network address. But this functionality is not provided in the API.

The network monitor in the source code listens for changes in the network interface or network address to modify interfacesinfo, but does not provide a callback interface for the plugin.

How can I finish this work?Thanks for your reply.

Re-enable path management selection from genl attribute.

Transitioning to the new MPTCP generic netlink API (see #12) forced the code that retrieves the path management strategy through the generic netlink API to be disabled since it doesn't support such a netlink attribute. Re-enable the code currently disabled through the MPTCPD_ENABLE_PM_NAME preprocessor symbol once the necessary kernel side implementation is available.

"reinstallation" issues on mptcp.service and mptcpd.conf

mptcpd.conf and mptcpd.service contain the dirname of libmtcpd.so. This can create a "reinstallation conflict", as reported by rpmdelint CI:

Undeclared file conflicts:
mptcpd-0.7-1.el9.i686 provides /etc/mptcpd/mptcpd.conf which is also provided by mptcpd-0.7-1.el9.x86_64
mptcpd-0.7-1.el9.i686 provides /usr/lib/systemd/system/mptcp.service which is also provided by mptcpd-0.7-1.el9.x86_64
mptcpd-0.7-1.el9.x86_64 provides /etc/mptcpd/mptcpd.conf which is also provided by mptcpd-0.7-1.el9.i686
mptcpd-0.7-1.el9.x86_64 provides /usr/lib/systemd/system/mptcp.service which is also provided by mptcpd-0.7-1.el9.i686

To Reproduce

$ rpmdeplint check-conflicts mptcpd-0.7-1.el9.i686.rpm mptcpd-0.7-1.el9.x86_64.rpm

Improve IPv6 address hash function in ID manager

Is your feature request related to a problem? Please describe.
The mptcpd ID manager currently maps IP addresses to MPTCP address IDs using a hash map, where the hash function simply returns the last four bytes of the IPv6 address. Depending on the local address configuration on the host, such a trivial hash function may incur collisions when inserting entries to the hash map.

Describe the solution you'd like
Implement hash function with better collision characteristics.

Describe alternatives you've considered

  • Consider using something like the 32 bit version of MurmurHash3. Only the 32 bit version is needed since the underlying hash map, ELL's l_hash_map, expects hash functions to return an unsigned int, which is 32 bits wide on Linux platforms.
  • Consider replacing the underlying hash map with a simple linked list (e.g. ELL l_queue) or array. The hash map lookup speed (O(log n)) won't be very different from a linear (O(n)) lookup speed when the number of entries is small. That is likely the case for the mptcpd ID manager case since it is unlikely that hosts will have many local addresses.

mptcpd should populate its ID manager from kernel netlink PM state at process start

Is your feature request related to a problem? Please describe.
It is possible that some IDs may have been associated with local IP addresses prior to mptcpd start, e.g. through previous runs of mptcpd or other non-mptcpd initiated calls to the netlink path manager.

Describe the solution you'd like
Mptcpd should populate its ID manager with address/ID pairs obtained through a MPTCP_PM_CMD_GET_ADDR netlink PM command based dump, such as through mptcpd's own mptcpd_pm_dump_addrs() function. This would prevent an address ID that is already in use prior to mptcpd start from being re-used by mptcpd.

Describe alternatives you've considered
mptcpd could stop tracking address IDs altogether, but that would make it difficult to stop advertising addresses since the netlink path management API requires an address ID in that case. To obtain the address ID through the current netlink path management API mptcpd would have to dump the addresses through that API to determine which address ID is associated with a given IP address.

Additional context
Related issue: #89

Add mptcpd path manager readiness callback.

Add new callback registration that allows users to be informed when the mptcpd path manager is ready for use instead of having to poll through mptcpd_pm_ready().

This would also allow unit tests to wait for the PM to be ready before executing their test cases rather than exit prematurely.

MPTCP genl "backup" attribute is no longer a NLA_FLAG

Describe the bug
The generic netlink code in mptcpd that retrieves and sends the MPTCP "backup" priority still implements the deprecated API where the corresponding attribute was a NLA_FLAG instead of the new API's NLA_U8 (type uint8_t).

Expected behavior
Treat the MPTCP genl "backup" priority attribute as a NLA_U8 instead of a NLA_FLAG.

Screenshots
From src/path_manager.c:

                case MPTCP_ATTR_BACKUP:
                        /*
                          The backup attribute is a NLA_FLAG,
                          meaning its existence *is* the flag.  No
                          payload data exists in such an attribute.
                         */
                        assert(validate_attr_len(len, 0));
                        assert(data == NULL);
                        *backup = true;
                        break;

From lib/path_manager.c:

                    || l_genl_msg_append_attr(msg,
                                              MPTCP_ATTR_BACKUP,
                                              0,
                                              NULL));  // NLA_FLAG

Additional context

  • See PR #15 for other changes related to migration to the new generic netlink API.
  • Issue #19 is also related since some of the generic netlink commands sent by mptcpd contain a "backup" attribute.

mptcpd 0.7 on linux kernel 5.10.0

I have compiled mptcpd release 0.7 on ubuntu 20.04 (kernel - 5.10.0), but when I try to run it I'm getting below warning

ip@ip-VirtualBox:~/$ sudo src/mptcpd --debug
configuration.c:mptcpd_config_create() plugin directory: /usr/local/lib/mptcpd
configuration.c:mptcpd_config_create() default path manager plugin: addr_adv
path_manager.c:family_appeared() "mptcp_pm" generic netlink family appeared
**Unable to register handler for mptcp_pm_events multicast messages**        // warning line
MPTCP single-subflow-per-interface path manager initialized.
MPTCP address advertiser path manager initialized.

which means mptcpd can't listen to pm Netlink events from kernel space? As you can see, I'm running it as the root user.
I have two interfaces on both client and server and only the first interface being used as Master subflow and I expect sspi path manager plugins will detect the second interface on both sides and create the second subflow between them but it's not happening.

Apologise for asking questions on the GitHub issue page but I couldn't find any other medium to get help on this repo.

mptcpd aborts when removing an address from monitoring

Describe the bug
An assert() in the mptcpd network monitor is triggered when it handles an rtnetlink RTM_DELADDR message. There are two problems with the code:

  • The assert() that checks the "right hand side" argument's address family in this case is unnecessary.
  • The user_data argument to the mptcpd_in_addr_match() is incorrectly assumed to be of type struct mptcpd_in_addr when it is actually void* that contains either a in_addr_t* or in6_addr_t*, depending on the address family found in the RTM_DELADDR message.

Expected behavior
No abort, and no crash due to function parameter mismatch.

Screenshots
From the host's systemd journal:

Jun 04 13:37:04 mptcp-vm-server mptcpd[6299]: mptcpd: network_monitor.c:152: mptcpd_in_addr_match: Assertion `rhs->family == AF_INET || rhs->family == AF_INET6' failed.

Desktop (please complete the following information):

  • Linux Kernel: 4.19 (multipath-tcp.org 0.95 kernel)
  • Compiler: gcc 8.30

Crash may occur if a plugin operation field is NULL.

Describe the bug
A memory access violation (e.g. seg fault) may occur if a plugin registers a mptcpd_plugin_ops instance with one or more NULL callback fields.

To Reproduce
Steps to reproduce the behavior:

  1. Create a mptcpd_plugin_ops instance with NULL callback fields.
  2. Register that instance.
  3. Invoke any of the NULL callbacks through the private mptcpd plugin API.
#include <mptcpd/plugin.h>
#include <mptcpd/plugin_private.h>

int main(int argc, char *argv[])
{
    static char const        dir[]          = "INSERT PLUGIN DIR HERE";
    static char const *const default_plugin = NULL;

    bool const loaded = mptcpd_plugin_load(dir, default_plugin);
    assert(loaded);

    char const name[] = "bad plugin";
    struct mptcpd_plugin_ops const ops = { .new_connection = NULL };

    bool registered = mptcpd_plugin_register_ops(name, &ops);
    if (!registered)
        return -1;

    // Dummy arguments that won't trigger the seg fault described
    // in this bug report.
    mptcpd_token_t token = 0;
    struct sockaddr const *const laddr = NULL;
    struct sockaddr const *const raddr = NULL;
    struct mptcpd_pm *const pm = NULL;

    // Invoke NULL new_connection callback, and crash.
    mptcpd_plugin_new_connection(name, token, laddr, raddr, pm);

    mptcpd_plugin_unload();

    return 0;
}

Expected behavior
Mptcpd should not call plugin callbacks that are NULL. No crash should occur.

mptcpd tests fail to compile with clang

Describe the bug
Some mptcpd tests fail to compile with the clang C compiler.

  • test-plugin fails with undefined reference errors:
  CCLD     test-plugin
test_plugin-test-plugin.o: In function `test_plugin_dispatch':
/home/ossama/MPTCP/OTC/mptcpd/tests/test-plugin.c:131: undefined reference to `call_plugin_ops'
/home/ossama/MPTCP/OTC/mptcpd/tests/test-plugin.c:141: undefined reference to `call_plugin_ops'
/home/ossama/MPTCP/OTC/mptcpd/tests/test-plugin.c:151: undefined reference to `call_plugin_ops'
test_plugin-test-plugin.o: In function `run_plugin_load':
/home/ossama/MPTCP/OTC/mptcpd/tests/test-plugin.c:40: undefined reference to `call_plugin_ops'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • test-path-manager fails with a missing field initializer error
  CC       test_path_manager-test-path-manager.o
test-path-manager.c:119:40: error: missing field 'pm' initializer
      [-Werror,-Wmissing-field-initializers]
        struct test_info info = { NULL };
                                       ^
1 error generated.

To Reproduce
Steps to reproduce the behavior:

  1. ./configure CC=clang CXX=clang++
  2. make check
  3. tests/test-plugin will fail to link.
  4. Apply the following patch :
diff --git a/tests/test-plugin.h b/tests/test-plugin.h
index d53634a..61584ed 100644
--- a/tests/test-plugin.h
+++ b/tests/test-plugin.h
@@ -275,7 +275,7 @@ inline bool mptcpd_addr_is_equal(struct mptcpd_addr const *lhs,
         return false;
 }
 
-inline void call_plugin_ops(struct plugin_call_count const *count,
+extern void call_plugin_ops(struct plugin_call_count const *count,
                             char const *name,
                             mptcpd_cid_t connection_id,
                             mptcpd_aid_t laddr_id,
  1. tests/test-path-manager will fail to compile.

Expected behavior
The entire mptcpd source distribution should build without error when using other C and C++ compilers, such as clang.

Desktop (please complete the following information):

  • Compiler: clang 6.0.0

make install also installs the tests

Describe the bug
make DESTDIR="/wherever/" install also copies tests

To Reproduce
./configure --prefix=/usr
make
make DESTDIR="/wherever/" install

this creates the $PWD directory tree and tests, like /home/zoe/Downloads/mptcpdpkg/pkg/mptcpd/home/zoe/Downloads/mptcpdpkg/src/mptcpd-0.4/tests in my case. (here DESTDIR was "/home/zoe/Downloads/mptcpdpkg/pkg/mptcpd/"

Expected behavior
tests should not be installed, and especially not under /prefix/$build_pwd

Desktop:

  • Linux Kernel: 5.6.14-arch1-1
  • Compiler: gcc version 10.1.0

Additional context
an arch PKGBUILD:

pkgname=mptcpd
pkgver=0.4
pkgrel=1
pkgdesc="Multipath TCP daemon"
url="https://github.com/intel/mptcpd"
arch=('x86_64')
license=('GPL2' 'BSD')
depends=('ell')
source=("https://github.com/intel/mptcpd/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz")
sha512sums=('1db9fa7182b167d45c44e16dcec051f426039eeeb84dc5b7352819f5b5048e5f5cdc22c567b32054b72bed444869cad36b24c3354e63d671a807010d0b9aab68')

#prepare() {
#       cd "$pkgname-$pkgver"
#    #./bootstrap # only required when building a git clone
#}

build() {
        cd "$pkgname-$pkgver"
    ./configure --prefix=/usr 
    make
}

package() {
        cd "$pkgname-$pkgver"
    make DESTDIR="$pkgdir/" install
    echo "$PWD"
}

Can't bootstrap

I can't bootstrap the source code I've pulled from the git, it ends up with this error:

$ ./bootstrap
libtoolize: putting auxiliary files in '.'.
libtoolize: linking file './ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: linking file 'm4/libtool.m4'
libtoolize: linking file 'm4/ltoptions.m4'
libtoolize: linking file 'm4/ltsugar.m4'
libtoolize: linking file 'm4/ltversion.m4'
libtoolize: linking file 'm4/lt~obsolete.m4'
configure.ac:25: error: possibly undefined macro: AC_SUBST
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
autoreconf: /opt/rh/autotools-latest/root/usr/bin/autoconf failed with exit status: 1

I've reproduced this in CentOS 7.6. I also tried this on Debian 10 and it ended up in the same error.

Version information:
autoconf / autoreconf: 2.69
automake: 1.16.1
autoconf-archive: 2017.03.21
libell: 0.22
libtool: 2.4.6
pkg-config: 0.29
gcc: tried with 4.8.5 and 7.3.1

Incorrect MPTCP genl API command attributes

Describe the bug
The mptcpd path management command functions in lib/path_manager.c still implement the deprecated MPTCP generic netlink command API, and were not updated as part of the API migration effort in PR #15. The current implementation is missing required attributes, as well as some mismatches.

Expected behavior
The MPTCP genl command implementation in lib/path_manager.c should be updated to conform to the new API.

Test full kernel-to-user and user-to-kernel path management code paths

Existing tests focus predominantly on individual mptcpd components, without much kernel involvement. Tests should be written or improved to cover the full path management code path, including:

  • Kernel to user space
    • Trigger path management events in the kernel so that they are handled by mptcpd, and eventually routed to a mptcpd plugin.
  • User to kernel space
    • Issue path management commands through a mptcpd plugin, and very that the commands were handled by the kernel.

Failed config file parse prevents command line from being parsed.

Describe the bug
A problem with the mptcpd configuration file, e.g. /etc/mptcpd/mptcpd.conf, prevents commands line parsing from occurring.

To Reproduce
Steps to reproduce the behavior:

  1. Comment out the required plugin-dir configuration setting.
  2. Attempt to get the mptcpd help message, e.g.. /usr/local/bin/mptcpd --help.
  3. No help message will be displayed. Instead, an error message will be displayed. In this case, the message will be "No plugin directory set in mptcpd configuration".

Expected behavior
Command line parsing should always succeed, regardless of whether or not a problem exists in the mptcpd configuration file. Otherwise it would not be possible to override missing or invalid settings through the command line.

Desktop (please complete the following information):

  • Linux Kernel: 5.8
  • Compiler: gcc 10.2

mptcpd configuration parser leaks memory.

Describe the bug
Providing mptcpd with multiple string typed configuration parameters, i.e. more than one plugin directory or more than one path manager name, causes a memory leak in mptcpd_config. This is caused by failing to deallocate the strings in mptcpd_config before resetting their values:

struct mptcpd_config
{
        ...
        char const *plugin_dir;
        char const *default_plugin;
};

To Reproduce
Steps to reproduce the behavior:

  1. ./configure --enable-debug
  2. make
  3. sudo make install
  4. ./libtool --mode=execute valgrind --leak-check=full ./src/mptcpd --plugin-dir=./tests/plugins_noop
  5. Terminate mptcpd through the usual ^C keyboard key combination.
  6. Valgrind will show the memory leak locations in its output.
  7. sudo make uninstall

Installation of mptcpd shown above is needed to allow mptcpd to find its configuration file in the expected (compiled-in) location.

Expected behavior
Valgrind should report no memory leaks or errors in mptcpd after performing the above steps.

Screenshots
Valgrind output:

==9042== Memcheck, a memory error detector
==9042== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9042== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9042== Command: /home/.../MPTCP/mptcpd/src/.libs/mptcpd --plugin-dir=./tests/plugins_noop
==9042== 
^C==9042== 
==9042== HEAP SUMMARY:
==9042==     in use at exit: 22 bytes in 1 blocks
==9042==   total heap usage: 169 allocs, 168 frees, 77,202 bytes allocated
==9042== 
==9042== 22 bytes in 1 blocks are definitely lost in loss record 1 of 1
==9042==    at 0x483774F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9042==    by 0x485B7BD: l_malloc (util.c:62)
==9042==    by 0x485EA37: unescape_value (settings.c:118)
==9042==    by 0x10A7ED: parse_config_file (configuration.c:277)
==9042==    by 0x10A8CC: parse_config_files (configuration.c:334)
==9042==    by 0x10AAD1: mptcpd_config_create (configuration.c:359)
==9042==    by 0x10A45D: main (mptcpd.c:42)
==9042== 
==9042== LEAK SUMMARY:
==9042==    definitely lost: 22 bytes in 1 blocks
==9042==    indirectly lost: 0 bytes in 0 blocks
==9042==      possibly lost: 0 bytes in 0 blocks
==9042==    still reachable: 0 bytes in 0 blocks
==9042==         suppressed: 0 bytes in 0 blocks
==9042== 
==9042== For counts of detected and suppressed errors, rerun with: -v
==9042== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Desktop (please complete the following information):

  • Linux Kernel: 4.19.36-mpttcp
  • Compiler: gcc 8.3.0

optional values for MPTCP_CMD_SUB_CREATE in netlink_pm_mptcp_org.c

Hi,

It looks like the comment https://github.com/intel/mptcpd/blob/master/src/netlink_pm_mptcp_org.c#L317-L321 are not correct. Local address, remote address and remote port are not optional for MPTCP_CMD_SUB_CREATE command. Only source port, backup flag and if_idx are optional. Please check the out of tree mptcp Netlink path manager implementation at kernel side https://github.com/multipath-tcp/mptcp/blob/mptcp_v0.95/net/mptcp/mptcp_netlink.c#L862-L872

Also, why we are not adding MPTCP_ATTR_FAMILY for subflow create command? I see the bug comment https://github.com/intel/mptcpd/blob/v0.7/src/netlink_pm_mptcp_org.c#L333 but I don't understand it.

Am I missing something here?

test-path-manager leaks memory

Describe the bug
The unit test tests/test-path-manager leaks memory, and contains memory violations despite a successful run.

To Reproduce
Steps to reproduce the behavior:

  1. ./configure --enable-debug
  2. make check
  3. ./libtool --mode=execute valgrind --leak-check=full tests/test-path-manager

Expected behavior
No leaks should be detected at test-path-manager process exit. The Valgrind summary should look similar to the following, in particular "no leaks possible":

==26069== HEAP SUMMARY:
==26069==     in use at exit: 0 bytes in 0 blocks
==26069==   total heap usage: 37 allocs, 37 frees, 30,696 bytes allocated
==26069== 
==26069== All heap blocks were freed -- no leaks are possible
==26069== 
==26069== For counts of detected and suppressed errors, rerun with: -v
==26069== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Screenshots

==25640== Memcheck, a memory error detector
==25640== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25640== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==25640== Command: /home/void/MPTCP/OTC/mptcpd/genl-update/tests/.libs/test-path-manager
==25640== 
configuration.c:check_file_perms() File "/usr/local/etc/mptcpd/mptcpd.conf" does not exist.
configuration.c:parse_config_file() Unable to mptcpd load settings from file '/usr/local/etc/mptcpd/mptcpd.conf'
configuration.c:mptcpd_config_create() plugin directory: /home/void/MPTCP/OTC/mptcpd/genl-update/tests/plugins_noop
TEST: pm_create
TEST: pm_destroy
==25640== Invalid read of size 8
==25640==    at 0x485D11B: l_queue_push_tail (queue.c:141)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==  Address 0x4ac6948 is 8 bytes inside a block of size 24 free'd
==25640==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x4863DAE: l_netlink_destroy (netlink.c:377)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640==    by 0x4860B8B: l_main_run (main.c:520)
==25640==    by 0x10A5C6: main (test-path-manager.c:127)
==25640==  Block was alloc'd at
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D04D: l_queue_new (queue.c:63)
==25640==    by 0x4863D1D: l_netlink_new (netlink.c:359)
==25640==    by 0x484A008: mptcpd_nm_create (network_monitor.c:873)
==25640==    by 0x10BE04: mptcpd_pm_create (path_manager.c:748)
==25640==    by 0x10A3E0: test_pm_create (test-path-manager.c:38)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640== 
==25640== Invalid read of size 8
==25640==    at 0x485D133: l_queue_push_tail (queue.c:146)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==  Address 0x4ac6940 is 0 bytes inside a block of size 24 free'd
==25640==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x4863DAE: l_netlink_destroy (netlink.c:377)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640==    by 0x4860B8B: l_main_run (main.c:520)
==25640==    by 0x10A5C6: main (test-path-manager.c:127)
==25640==  Block was alloc'd at
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D04D: l_queue_new (queue.c:63)
==25640==    by 0x4863D1D: l_netlink_new (netlink.c:359)
==25640==    by 0x484A008: mptcpd_nm_create (network_monitor.c:873)
==25640==    by 0x10BE04: mptcpd_pm_create (path_manager.c:748)
==25640==    by 0x10A3E0: test_pm_create (test-path-manager.c:38)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640== 
==25640== Invalid write of size 8
==25640==    at 0x485D137: l_queue_push_tail (queue.c:144)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==  Address 0x4ac6948 is 8 bytes inside a block of size 24 free'd
==25640==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x4863DAE: l_netlink_destroy (netlink.c:377)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640==    by 0x4860B8B: l_main_run (main.c:520)
==25640==    by 0x10A5C6: main (test-path-manager.c:127)
==25640==  Block was alloc'd at
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D04D: l_queue_new (queue.c:63)
==25640==    by 0x4863D1D: l_netlink_new (netlink.c:359)
==25640==    by 0x484A008: mptcpd_nm_create (network_monitor.c:873)
==25640==    by 0x10BE04: mptcpd_pm_create (path_manager.c:748)
==25640==    by 0x10A3E0: test_pm_create (test-path-manager.c:38)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640== 
==25640== Invalid write of size 8
==25640==    at 0x485D150: l_queue_push_tail (queue.c:147)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==  Address 0x4ac6940 is 0 bytes inside a block of size 24 free'd
==25640==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x4863DAE: l_netlink_destroy (netlink.c:377)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640==    by 0x4860B8B: l_main_run (main.c:520)
==25640==    by 0x10A5C6: main (test-path-manager.c:127)
==25640==  Block was alloc'd at
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D04D: l_queue_new (queue.c:63)
==25640==    by 0x4863D1D: l_netlink_new (netlink.c:359)
==25640==    by 0x484A008: mptcpd_nm_create (network_monitor.c:873)
==25640==    by 0x10BE04: mptcpd_pm_create (path_manager.c:748)
==25640==    by 0x10A3E0: test_pm_create (test-path-manager.c:38)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640== 
==25640== Invalid read of size 4
==25640==    at 0x485D158: l_queue_push_tail (queue.c:149)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==  Address 0x4ac6950 is 16 bytes inside a block of size 24 free'd
==25640==    at 0x483997B: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x4863DAE: l_netlink_destroy (netlink.c:377)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640==    by 0x4860B8B: l_main_run (main.c:520)
==25640==    by 0x10A5C6: main (test-path-manager.c:127)
==25640==  Block was alloc'd at
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D04D: l_queue_new (queue.c:63)
==25640==    by 0x4863D1D: l_netlink_new (netlink.c:359)
==25640==    by 0x484A008: mptcpd_nm_create (network_monitor.c:873)
==25640==    by 0x10BE04: mptcpd_pm_create (path_manager.c:748)
==25640==    by 0x10A3E0: test_pm_create (test-path-manager.c:38)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640==    by 0x10A4E7: idle_callback (test-path-manager.c:86)
==25640==    by 0x4860305: idle_dispatch (main.c:333)
==25640==    by 0x485D4D7: l_queue_foreach (queue.c:441)
==25640==    by 0x4860B0C: l_main_iterate (main.c:486)
==25640== 
==25640== 
==25640== HEAP SUMMARY:
==25640==     in use at exit: 16 bytes in 1 blocks
==25640==   total heap usage: 77 allocs, 76 frees, 76,319 bytes allocated
==25640== 
==25640== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==25640==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25640==    by 0x485B76D: l_malloc (util.c:62)
==25640==    by 0x485D11A: l_queue_push_tail (queue.c:136)
==25640==    by 0x4863F15: l_netlink_send (netlink.c:438)
==25640==    by 0x484939B: send_getaddr_command (network_monitor.c:845)
==25640==    by 0x4863792: destroy_command (netlink.c:76)
==25640==    by 0x485D9DB: l_hashmap_destroy (hashmap.c:336)
==25640==    by 0x4863DC9: l_netlink_destroy (netlink.c:379)
==25640==    by 0x4849F0B: mptcpd_nm_destroy (network_monitor.c:972)
==25640==    by 0x10BD17: mptcpd_pm_destroy (path_manager.c:764)
==25640==    by 0x10A4AE: test_pm_destroy (test-path-manager.c:51)
==25640==    by 0x485C238: l_test_run (test.c:83)
==25640== 
==25640== LEAK SUMMARY:
==25640==    definitely lost: 16 bytes in 1 blocks
==25640==    indirectly lost: 0 bytes in 0 blocks
==25640==      possibly lost: 0 bytes in 0 blocks
==25640==    still reachable: 0 bytes in 0 blocks
==25640==         suppressed: 0 bytes in 0 blocks
==25640== 
==25640== For counts of detected and suppressed errors, rerun with: -v
==25640== ERROR SUMMARY: 7 errors from 6 contexts (suppressed: 0 from 0)

Desktop (please complete the following information):

  • Linux Kernel: 5.0.0
  • Compiler: gcc 8.3

Additional context
The call stack shows the static function send_getaddr_command() being called as the Netlink destroy command. That really shouldn't happen, but occurs because of a workaround in the mptcpd network monitor for an issue in the ELL l_netlink API that allows the second call to l_netlink_send() to be processed asynchronously prior to completion of the first l_netlink_send(). The code in question is in lib/network_monitor.c:

        /**
         * Get network interface information.
         *
         * @note We force the second rtnetlink command, RTM_GETADDR,
         *       to be sent after this one completes by doing so in
         *       the destroy callback for this command.  That
         *       guarantees that the potential multipart message
         *       response from this dump is fully read prior to
         *       sending the second command.  This works around an
         *       issue in ELL where it was possible that the second
         *       command would be sent prior to receiving all of the
         *       parts of the multipart @c RTM_GETLINK response, which
         *       resulted in an EBUSY error.
         */
        struct ifinfomsg link_msg = { .ifi_family = AF_UNSPEC };
        if (l_netlink_send(nm->rtnl,
                           RTM_GETLINK,
                           NLM_F_DUMP,
                           &link_msg,
                           sizeof(link_msg),
                           handle_rtm_getlink,
                           nm,
                           send_getaddr_command)
            == 0) {
                l_error("Unable to obtain network devices.");
                mptcpd_nm_destroy(nm);
                return NULL;
        }

The send_getaddr_command() function gets called as the "destroy command" even though that is not what we really want in the case of the tests/test-path-manager unit test. The test/test-network-monitor unit test doesn't exhibit a memory leak, so we should look into what is done differently in tests/test-path-manager that ultimately triggers the leak.

Duplicate address IDs may be generated for multiple plugins

Describe the bug
Mptcpd plugins may each create their own mptcpd_idm instance, potentially resulting in duplicate address IDs being generated between plugins.

To Reproduce
Steps to reproduce the behavior:

  1. Plugin "A" calls mptcpd_idm_create().
  2. Plugin "A" mptcpd_idm_get_id().
  3. Initially returned address ID will be 1.
  4. Plugin "A" calls mptcpd_pm_add_addr().
  5. Plugin "B" calls mptcpd_idm_create().
  6. Plugin "B" mptcpd_get_id().
  7. Initially returned address ID will also be 1.
  8. Plugin "B" calls mptcpd_pm_add_addr().
  9. The same address ID will end up being associated with two potentially different local IP addresses.

Expected behavior
There should be no overlap of address IDs between plugins.

Desktop (please complete the following information):

  • Linux Kernel: 5.9.10
  • Compiler: 10.2.1

Additional context
Part of the problem lies in the fact that mptcpd network monitoring events are propagated to all loaded plugins. This gives an opportunity for multiple plugins to potentially issue duplicate or conflicting path management commands to the kernel.

Address ID passed to pm netlink add_addr command is overridden

NOTE: This issue is meant to document an address ID tracking conflict between the user-space (mptcpd) and the kernel. It is not necessarily an issue that needs to be corrected in mptcpd, at least at this point in time.

Describe the bug
The address ID passed to the mptcpd_pm_add_addr() function is overridden by the kernel. Finding out what the actual address ID associated with the added local address is can only be done by iterating through the list of addresses obtained through the dump_addr PM netlink command, This makes keeping track of address IDs in the user-space difficult.

To Reproduce
Steps to reproduce the behavior:

  1. On a kernel with no addresses advertised through ADD_ADDR, e.g. a freshly booted kernel, call mptcpd_pm_addr() with an address ID other than 1.
  2. Call mptcpd_pm_get_addr() with the same address ID used in the first step.
  3. The get_addr call will fail with an "address not found" error returned from the kernel since the address ID passed to the kernel in step 1 is overridden.

Expected behavior
Ideally the kernel should not override user IDs managed by the user space, e.g. mptcpd. Otherwise it becomes difficult for the user-space to trigger a MPTCP REMOVE_ADDR since the required address ID is unknown due to the kernel override.

Desktop (please complete the following information):

  • Linux Kernel: 5.9.10
  • Compiler: 10.2.1

Additional context
See "Address ID assignment in netlink PM" on the old MPTCP community mailing list or the same thread on the current mailing list.

Support network monitoring in the "sspi" plugin

Implement at least the new_local_address and delete_local_address callbacks in the single-sublflow-per-interface (sspi) reference plugin to trigger MPTCP ADD_ADDR and REMOVE_ADDR operations through the MPTCP path management netlink command API.

Add ASAN/UBSAN/LSAN

The GCC (and clang) sanitizers are supported for ELL, and for development and debugging it would be helpful to have them available for mptcpd as well. The currently available sanitizers are address, leak, and undefined-behavior.

These are enabled with the following flags for the compiler and linker:

  • -fsanitize=address
  • -fsanitize=leak
  • -fsanitize=undefined

Valgrind can catch some of the same bugs.

Building and Installation issue

Please, help me to find the solution and resolve installation issue.
I would appreciate any suggestion..
I follow the steps described in README and when I run ./bootstrap the following errors appear:

 vad@mp-vm:~/mptcpd$ ./bootstrap
libtoolize: putting auxiliary files in '.'.
libtoolize: linking file './ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: linking file 'm4/libtool.m4'
libtoolize: linking file 'm4/ltoptions.m4'
libtoolize: linking file 'm4/ltsugar.m4'
libtoolize: linking file 'm4/ltversion.m4'
libtoolize: linking file 'm4/lt~obsolete.m4'
configure.ac:103: error: possibly undefined macro: AC_MSG_ERROR
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
configure.ac:164: error: possibly undefined macro: AC_DEFINE
autoreconf: /usr/bin/autoconf failed with exit status: 1

My configuration :

MPTCP v0.95 from multipath-tcp.org
Linux Mint 20.2 kernel 5.4 with mptcp patch

vad@mp-vm:~/mptcpd$ m4 --version
m4 (GNU M4) 1.4.18
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Rene' Seindal.
vad@mp-vm:~/mptcpd$ command -v autoconf
/usr/bin/autoconf
vad@mp-vm:~/mptcpd$ autoconf --version
autoconf (GNU Autoconf) 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+/Autoconf: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>, <http://gnu.org/licenses/exceptions.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by David J. MacKenzie and Akim Demaille.
vad@mp-vm:~/mptcpd$ command -v automake
/usr/bin/automake
vad@mp-vm:~/mptcpd$ automake --version
automake (GNU automake) 1.16.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv2+: GNU GPL version 2 or later <https://gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Tom Tromey <[email protected]>
       and Alexandre Duret-Lutz <[email protected]>.

vad@mp-vm:~/mptcpd$ command -v libtool
/usr/bin/libtool
vad@mp-vm:~/mptcpd$ libtool --version
libtool (GNU libtool) 2.4.6
Written by Gordon Matzigkeit, 1996

Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
vad@mp-vm:~/mptcpd$ command -v pkg-config
/usr/bin/pkg-config
vad@mp-vm:~/mptcpd$ pkg-config --version
0.29.1

vad@mp-vm:~/mptcpd$ pandoc --version
pandoc 2.5
Compiled with pandoc-types 1.17.5.4, texmath 0.11.2.2, skylighting 0.7.7
Default user data directory: /home/vad/.pandoc
Copyright (C) 2006-2018 John MacFarlane
Web:  http://pandoc.org
This is free software; see the source for copying conditions.
There is no warranty, not even for merchantability or fitness
for a particular purpose.

vad@mp-vm:~/mptcpd$ apt-cache policy libell-dev
libell-dev:
  Installed: 0.27-1
  Candidate: 0.27-1
  Version table:
 *** 0.27-1 500
        500 http://archive.ubuntu.com/ubuntu focal/universe amd64 Packages
        100 /var/lib/dpkg/status
vad@mp-vm:~/mptcpd$ apt-cache policy libargtable2-dev
libargtable2-dev:
  Installed: 13-1
  Candidate: 13-1
  Version table:
 *** 13-1 500
        500 http://archive.ubuntu.com/ubuntu focal/universe amd64 Packages
        100 /var/lib/dpkg/status

vad@mp-vm:~/mptcpd$ sudo sysctl -a | grep -i mptcp
kernel.osrelease = 5.4.0-mptcp
net.mptcp.mptcp_binder_gateways =
net.mptcp.mptcp_checksum = 1
net.mptcp.mptcp_debug = 0
net.mptcp.mptcp_enabled = 1
net.mptcp.mptcp_path_manager = fullmesh
net.mptcp.mptcp_scheduler = default
net.mptcp.mptcp_syn_retries = 3
net.mptcp.mptcp_version = 0

sspi: using wrong dev when send local address to kernel?

Describe the bug
When a new mptcp conntion create, SSPI will send each address associate with all the network interfaces other than which the new connection was created to kernel,but it is always using the same network interface index in sspi_send_addr(),and it is not the interface which address belongs to.
eg. I have two nic, ens33 and ens37, when get a new mptcp connection at 192.168.174.128(ens37), addresses in ens33 is send to kernel by SSPI, but these addresses are associated with ens37.

Is this a BUG?

2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:bb:2e:ca brd ff:ff:ff:ff:ff:ff
inet 192.168.234.147/24 brd 192.168.234.255 scope global noprefixroute dynamic ens33
valid_lft 1715sec preferred_lft 1715sec
inet 192.168.234.140/24 brd 192.168.234.255 scope global secondary dynamic ens33
valid_lft 1290sec preferred_lft 1290sec
inet6 fe80::63d2:1cb6:e7c6:ae30/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:bb:2e:d4 brd ff:ff:ff:ff:ff:ff
inet 192.168.174.128/24 brd 192.168.174.255 scope global noprefixroute ens37
valid_lft forever preferred_lft forever
inet 192.168.174.130/24 brd 192.168.174.255 scope global secondary dynamic ens37
valid_lft 1480sec preferred_lft 1480sec
inet6 fe80::2ace:2b3c:1129:67b4/64 scope link noprefixroute
valid_lft forever preferred_lft forever

[root@bogon mptcp]# ./pm_nl_ctl dump
id 1 flags dev ens37 192.168.234.147
id 2 flags dev ens37 192.168.234.140
id 3 flags dev ens37 fe80::63d2:1cb6:e7c6:ae30

To Reproduce
Steps to reproduce the behavior:

  1. run mptcpd
  2. create mptcp connection
  3. ./pm_nl_ctl dump

mptcp generic netlink family has not appeared - with 5.7.10 kernel

Describe the bug
mptcpd is reporting the following in systemd logs

mptcp generic netlink family has not appeared. Verify MPTCP "netlink" path manager kernel support.

However, running genl-ctrl-list shows this entry: 0x001b mptcp_pm version 1 .

Should this work with the 5.7 kernel and this is a configuration problem or do I need to wait for future versions?

Desktop (please complete the following information):

  • arch linux installed/updated on 2020-07-28

Additional context

[filip@archlinux1 src]$ uname -a
Linux archlinux1 5.7.10-arch1-1 #1 SMP PREEMPT Wed, 22 Jul 2020 19:57:42 +0000 x86_64 GNU/Linux
[filip@archlinux1 src]$ systemctl status mptcp
● mptcp.service - Multipath TCP service
     Loaded: loaded (/usr/lib/systemd/system/mptcp.service; enabled; vendor preset: disabled)
     Active: active (running) since Tue 2020-07-28 12:38:00 CEST; 24min ago
       Docs: man:mptcpd(8)
   Main PID: 243 (mptcpd)
      Tasks: 1 (limit: 1157)
     Memory: 824.0K
     CGroup: /system.slice/mptcp.service
             └─243 /usr/libexec/mptcpd --log=journal

Jul 28 12:38:00 archlinux1 systemd[1]: Started Multipath TCP service.
Jul 28 12:38:00 archlinux1 mptcpd[243]: MPTCP single-subflow-per-interface path manager initialized.
Jul 28 12:38:10 archlinux1 mptcpd[243]: mptcp generic netlink family has not appeared.
Jul 28 12:38:10 archlinux1 mptcpd[243]: Verify MPTCP "netlink" path manager kernel support.
[filip@archlinux1 src]$ genl-ctrl-list
0x0010 nlctrl version 2
0x0011 VFS_DQUOT version 1
0x0013 devlink version 1
0x0014 ethtool version 1
0x0015 NLBL_MGMT version 3
0x0016 NLBL_CIPSOv4 version 3
0x0017 NLBL_CALIPSO version 3
0x0018 NLBL_UNLBL version 3
0x0019 acpi_event version 1
0x001a tcp_metrics version 1
0x001b mptcp_pm version 1
0x001c NET_DM version 2
0x001d SEG6 version 1
0x001e TASKSTATS version 1

sspi dosn't print any debug log when run mptcpd with --debug options

Describe the bug
I run mptcpd by: /usr/local/libexec/mptcpd --debug, and create a mptcp connection, sspi dosn't print any debug logs,but sspi_send_addrs() call l_debug() to print debug log.

To Reproduce
Steps to reproduce the behavior:

  1. set "path-manager=sspi" in /usr/local/etc/mptcpd/mptcpd.conf
  2. run mptcpd by: /usr/local/libexec/mptcpd --debug
  3. create a new mptcp connection.

Desktop (please complete the following information):

  • Linux Kernel: [5.12]
  • mptpd: [0.7]

mptcp.service systemd unit file does not grant CAP_NET_ADMIN capability

Describe the bug
The multipath-tcp.org kernel's "netlink" path manager requires processes that invoke commands over its generic netlink API to have the CAP_NET_ADMIN capability. However, the mptcpd mptcp.service file doesn't explicitly grant that capability since it runs mptcpd under an unprivileged dynamically created user (DynamicUser=yes), resulting in mptcpd being in incapable of successfully issuing path management commands to the kernel.

To Reproduce
Steps to reproduce the behavior:
Server

  1. Set up a host, such as a virtual machine, as an MPTCP server with multiple network interfaces. Make sure the multipath-tcp.org kernel is built with the mptcp_netlink path manager enabled.
  2. Build and install mptcpd (e.g. ./configure; make; sudo make install)
  3. sudo systemctl daemon-reload
  4. sudo systemctl restart mptcp
  5. Execute an MPTCP capable process that listens for connections.

Client

  1. Set up a host, such as a virtual machine, as an MPTCP client. Make sure the kernel is built with MPTCP support enabled.
  2. Execute an MPTCP capable process that establishes a connection with the process listening for connection on the server host.

Server
The server host's log will show "operation not permitted" errors from mptcpd. The errors occur because the mptcpd process doesn't have the CAP_NET_ADMIN capability needed for sending MPTCP generic netlink API commands to the kernel. See the Screenshots section below for a system journal excerpt showing the errors.

Expected behavior
MPTCP generic netlink API commands emanating from a mptcpd process started by systemd should not be rejected due to lack of privileges.

Screenshots

Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted
Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted
Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted
Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted
Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted
Jun 06 10:18:03 vm-server mptcpd[20672]: Path manager command error: Operation not permitted

Desktop (please complete the following information):

  • Linux Kernel: 4.19 (multipath-tcp.org kernel built for an Ubuntu system)
  • Compiler: 8.3.0

Additional context
The mptcp.service unit file explicitly avoids starting mptcpd as the root user by setting DynamicUser=yes to minimize security risks.

Security: Do not log MPTCP token

Describe the bug
mptcpd currently logs MPTCP connection tokens that may be visible to unprivileged users. That is a potential security risk.

Expected behavior
mptcpd should not log security tokens.

Additional context
A similar issue in the multipath-tcp.org kernel was addressed by masking the MPTCP connection token in /proc/net/mptcp content if the process accessing the content did not have the CAP_NET_ADMIN capability. See multipath-tcp/mptcp@e993b77.

Automatically enable netlink path manager

Is your feature request related to a problem? Please describe.
When using the multipath-tcp.org kernel, it may be necessary to explicitly enable the netlink path manager In order for the Multipath TCP Daemon - mptcpd - to be used as the path manager for multipath TCP connections.

Describe the solution you'd like
mptcpd should enable MPTCP and the netlink path manager at run-time if their corresponding entries in /proc/sys/net/mptcp/ exist. Specific mptcpd should do the following:

  • write 1 to /proc/sys/net/mptcp/mptcp_enabled
  • write netlink to /proc/sys/net/mptcp/mptcp_path_manager

Describe alternatives you've considered
Write a script to perform the same operations through the sysctl command, e.g.:

#!/bin/sh

sysctl -w net.mptcp.mptcp_enabled=1 net.mptcp.mptcp_path_manager=netlink

Documenting the necessary sysctl command would be useful, too.

Data type inconsistency in handle_subflow

Describe the bug
The token parameter to handle_subflow() is causing a compile error at line 599 in handle_subflow(), where there's a mismatch between the formatting specifier and the token variable.

Should the second parameter to the function be a mptcp_token_t const *token, with callers of handle_subflow() providing storage for a mptcp_token_t on the stack? It does look like the current approach should work (other than the debug statement), since the l_genl_msg remains valid in the callers of handle_subflow() - so the minimal fix is to add a * in the debug statement at line 599 and change the !token to !*token at line 588.

To Reproduce
Steps to reproduce the behavior:

  1. Build using gcc 9.1.1

Expected behavior
No compile error

Desktop (please complete the following information):

  • Linux Kernel: 5.1.5
  • Compiler: gcc 9.1.1

OpenWrt support

Please provide OpenWrt support for this software along with its Makefile to include in the package list that can be selected from menuconfig.

0.5.1: test suite is failing

Looks like test suite is not prepared to be executed when /etc/mptcpd/mptcpd.conf is not available yet.

make[3]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
/usr/bin/make  check-TESTS
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
PASS: test-plugin
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
PASS: test-network-monitor
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
PASS: test-configuration
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
PASS: test-cxx-build
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-log-long
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-plugin-dir
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-log-short
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-log-empty
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-option
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
XFAIL: test-bad-path-manager
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
PASS: test-start-stop
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
../test-driver: line 107: 2055817 Aborted                 (core dumped) "$@" > $log_file 2>&1
FAIL: test-path-manager
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
../test-driver: line 107: 2055816 Aborted                 (core dumped) "$@" > $log_file 2>&1
FAIL: test-commands
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[4]: Entering directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
========================================
   mptcpd 0.5.1: tests/test-suite.log
========================================

# TOTAL: 13
# PASS:  5
# SKIP:  0
# XFAIL: 6
# FAIL:  2
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: test-path-manager
=======================

configuration.c:check_file_perms() File "/etc/mptcpd/mptcpd.conf" does not exist.
configuration.c:parse_config_file() Unable to mptcpd load settings from file '/etc/mptcpd/mptcpd.conf'
configuration.c:mptcpd_config_create() plugin directory: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/plugins/noop/.libs
test-path-manager.c:timeout_callback() test timed out
lt-test-path-manager: test-path-manager.c:171: main: Assertion `info.tests_called' failed.
FAIL test-path-manager (exit status: 134)

FAIL: test-commands
===================

configuration.c:check_file_perms() File "/etc/mptcpd/mptcpd.conf" does not exist.
configuration.c:parse_config_file() Unable to mptcpd load settings from file '/etc/mptcpd/mptcpd.conf'
configuration.c:mptcpd_config_create() plugin directory: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/plugins/noop/.libs
path_manager.c:family_appeared() Request for "mptcp" Generic Netlink family failed.  Waiting.
test-commands.c:timeout_callback() test timed out
lt-test-commands: test-commands.c:242: main: Assertion `tests_called' failed.
FAIL test-commands (exit status: 134)

XFAIL: test-bad-log-empty
=========================

lt-mptcpd: Unknown logging option: ""
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-log-empty (exit status: 64)

XFAIL: test-bad-log-long
========================

lt-mptcpd: Unknown logging option: "foo"
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-log-long (exit status: 64)

XFAIL: test-bad-log-short
=========================

lt-mptcpd: Unknown logging option: "foo"
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-log-short (exit status: 64)

XFAIL: test-bad-option
======================

/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/src/.libs/lt-mptcpd: unrecognized option '--foo'
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-option (exit status: 64)

XFAIL: test-bad-path-manager
============================

lt-mptcpd: Empty default path manager plugin command line option.
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-path-manager (exit status: 64)

XFAIL: test-bad-plugin-dir
==========================

lt-mptcpd: Empty plugin directory command line option.
Try `lt-mptcpd --help' or `lt-mptcpd --usage' for more information.
XFAIL test-bad-plugin-dir (exit status: 64)

============================================================================
Testsuite summary for mptcpd 0.5.1
============================================================================
# TOTAL: 13
# PASS:  5
# SKIP:  0
# XFAIL: 6
# FAIL:  2
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
Please report to [email protected]
============================================================================
make[4]: *** [Makefile:1083: test-suite.log] Error 1
make[4]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests'
make[3]: *** [Makefile:1191: check-TESTS] Error 2
make[2]: *** [Makefile:1374: check-am] Error 2
make[1]: *** [Makefile:975: check-recursive] Error 1
make: *** [Makefile:467: check-recursive] Error 1

As well there are some SIGSEGVs

Wed 2021-01-20 09:54:25 GMT  2055817  1000  1000   6 present   /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-path-manager
Wed 2021-01-20 09:54:26 GMT  2055816  1000  1000   6 present   /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-commands
[tkloczko@barrel SPECS]$ coredumpctl --debugger=lldb gdb 2055817
           PID: 2055817 (lt-test-path-ma)
           UID: 1000 (tkloczko)
           GID: 1000 (tkloczko)
        Signal: 6 (ABRT)
     Timestamp: Wed 2021-01-20 09:54:25 GMT (5min ago)
  Command Line: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-path-manager
    Executable: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-path-manager
 Control Group: /user.slice/user-1000.slice/session-30.scope
          Unit: session-30.scope
         Slice: user-1000.slice
       Session: 30
     Owner UID: 1000 (tkloczko)
       Boot ID: 5af33f0c3a8843fea23159bab1ddfd37
    Machine ID: d033f66b249a4ec09acfa81ac205554f
      Hostname: barrel
       Storage: /var/lib/systemd/coredump/core.lt-test-path-ma.1000.5af33f0c3a8843fea23159bab1ddfd37.2055817.1611136465000000.zst
       Message: Process 2055817 (lt-test-path-ma) of user 1000 dumped core.

                Stack trace of thread 2055817:
                #0  0x00007f9edf3bc282 raise (libc.so.6 + 0x3d282)
                #1  0x00007f9edf3a58a4 abort (libc.so.6 + 0x268a4)
                #2  0x00007f9edf3a5789 __assert_fail_base.cold (libc.so.6 + 0x26789)
                #3  0x00007f9edf3b4a06 __assert_fail (libc.so.6 + 0x35a06)
                #4  0x000055caf09e2d57 n/a (/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-path-manager + 0x2d57)

(lldb) target create "/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-path-manager" --core "/var/tmp/coredump-Fmpc16"
Core file '/var/tmp/coredump-Fmpc16' (x86_64) was loaded.

(lldb) bt all
* thread #1, name = 'lt-test-path-ma', stop reason = hit program assert
    frame #0: 0x00007f9edf3bc282 libc.so.6`raise + 322
    frame #1: 0x00007f9edf3a58a4 libc.so.6`abort + 278
    frame #2: 0x00007f9edf3a5789 libc.so.6`.annobin_unwind_resume.c_end.unlikely + 15
    frame #3: 0x00007f9edf3b4a06 libc.so.6`__assert_fail + 70
  * frame #4: 0x000055caf09e2d57 lt-test-path-manager`main at test-path-manager.c:171:9
    frame #5: 0x00007f9edf3a6b75 libc.so.6`__libc_start_main + 213
    frame #6: 0x000055caf09e2dee lt-test-path-manager`_start + 46
[tkloczko@barrel SPECS]$ coredumpctl --debugger=lldb gdb 2055816
           PID: 2055816 (lt-test-command)
           UID: 1000 (tkloczko)
           GID: 1000 (tkloczko)
        Signal: 6 (ABRT)
     Timestamp: Wed 2021-01-20 09:54:25 GMT (6min ago)
  Command Line: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-commands
    Executable: /home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-commands
 Control Group: /user.slice/user-1000.slice/session-30.scope
          Unit: session-30.scope
         Slice: user-1000.slice
       Session: 30
     Owner UID: 1000 (tkloczko)
       Boot ID: 5af33f0c3a8843fea23159bab1ddfd37
    Machine ID: d033f66b249a4ec09acfa81ac205554f
      Hostname: barrel
       Storage: /var/lib/systemd/coredump/core.lt-test-command.1000.5af33f0c3a8843fea23159bab1ddfd37.2055816.1611136465000000.zst
       Message: Process 2055816 (lt-test-command) of user 1000 dumped core.

                Stack trace of thread 2055816:
                #0  0x00007f7a6bb5f282 raise (libc.so.6 + 0x3d282)
                #1  0x00007f7a6bb488a4 abort (libc.so.6 + 0x268a4)
                #2  0x00007f7a6bb48789 __assert_fail_base.cold (libc.so.6 + 0x26789)
                #3  0x00007f7a6bb57a06 __assert_fail (libc.so.6 + 0x35a06)
                #4  0x00005636ed2d0235 n/a (/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-commands + 0x3235)

(lldb) target create "/home/tkloczko/rpmbuild/BUILD/mptcpd-0.5.1/tests/.libs/lt-test-commands" --core "/var/tmp/coredump-JoqL3G"
Core file '/var/tmp/coredump-JoqL3G' (x86_64) was loaded.

(lldb) bt all
* thread #1, name = 'lt-test-command', stop reason = hit program assert
    frame #0: 0x00007f7a6bb5f282 libc.so.6`raise + 322
    frame #1: 0x00007f7a6bb488a4 libc.so.6`abort + 278
    frame #2: 0x00007f7a6bb48789 libc.so.6`.annobin_unwind_resume.c_end.unlikely + 15
    frame #3: 0x00007f7a6bb57a06 libc.so.6`__assert_fail + 70
  * frame #4: 0x00005636ed2d0235 lt-test-commands`main at test-commands.c:242:9
    frame #5: 0x00007f7a6bb49b75 libc.so.6`__libc_start_main + 213
    frame #6: 0x00005636ed2d026e lt-test-commands`_start + 46
(lldb)

Memory leak on plugin load failure

A quick leak check through valgrind reveals a small memory leak at process exit on plugin load failure:

==11756== 40 bytes in 1 blocks are definitely lost in loss record 19 of 25
==11756==    at 0x4839809: malloc (vg_replace_malloc.c:307)
==11756==    by 0x48608FD: l_malloc (util.c:62)
==11756==    by 0x4865D26: watch_add (main.c:144)
==11756==    by 0x4867158: l_io_new (io.c:191)
==11756==    by 0x486BC54: l_genl_new (genl.c:1140)
==11756==    by 0x10D59F: mptcpd_pm_create (path_manager.c:1166)
==11756==    by 0x10B62E: main (mptcpd.c:58)

Originally posted by @ossama-othman in #98 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.