Skip to content
Please note that GitHub no longer supports Internet Explorer.

We recommend upgrading to the latest Microsoft Edge, Google Chrome, or Firefox.

Learn more
Permalink
Browse files

Allow enabling MPTCP on a listening socket through the records.config

  • Loading branch information
cpaasch authored and zwoop committed Aug 28, 2018
1 parent 23b8d5b commit 2755a80a8c55866591f20345ea5e275084fc4e03
Showing with 62 additions and 1 deletion.
  1. +6 −0 doc/admin-guide/files/records.config.en.rst
  2. +3 −0 lib/records/I_RecHttp.h
  3. +30 −1 lib/records/RecHttp.cc
  4. +23 −0 mgmt/LocalManager.cc
@@ -609,6 +609,7 @@ HTTP Engine
tr-in Inbound transparent.
tr-out Outbound transparent.
tr-pass Pass through enabled.
mptcp Multipath TCP.
=========== =============== ========================================

*number*
@@ -674,6 +675,11 @@ ip-resolve

Not compatible with: ``tr-out`` - this option requires a value of ``client;none`` which is forced and should not be explicitly specified.

mptcp
Enable Multipath TCP on this proxy port.

Requires custom Linux kernel available at https://multipath-tcp.org.

.. topic:: Example

Listen on port 80 on any address for IPv4 and IPv6.::
@@ -245,6 +245,8 @@ struct HttpProxyPort {
bool m_outbound_transparent_p;
// True if transparent pass-through is enabled on this port.
bool m_transparent_passthrough;
/// True if MPTCP is enabled on this port.
bool m_mptcp;
/// Local address for inbound connections (listen address).
IpAddr m_inbound_ip;
/// Local address for outbound connections (to origin server).
@@ -395,6 +397,7 @@ struct HttpProxyPort {
static const char *const OPT_COMPRESSED; ///< Compressed.
static const char *const OPT_HOST_RES_PREFIX; ///< Set DNS family preference.
static const char *const OPT_PROTO_PREFIX; ///< Transport layer protocols.
static const char *const OPT_MPTCP; ///< MPTCP.

static std::vector<self> &m_global; ///< Global ("default") data.

@@ -25,6 +25,7 @@
#include <records/I_RecHttp.h>
#include "tscore/ink_defs.h"
#include "tscore/ink_hash_table.h"
#include "tscore/TextBuffer.h"
#include "tscore/Tokenizer.h"
#include <strings.h>
#include "tscore/ink_inet.h"
@@ -70,6 +71,22 @@ SessionProtocolSet HTTP2_PROTOCOL_SET;
SessionProtocolSet DEFAULT_NON_TLS_SESSION_PROTOCOL_SET;
SessionProtocolSet DEFAULT_TLS_SESSION_PROTOCOL_SET;

static bool
mptcp_supported()
{
ats_scoped_fd fd(::open("/proc/sys/net/mptcp/mptcp_enabled", O_RDONLY));
int value = 0;

if (fd) {
TextBuffer buffer(16);

buffer.slurp(fd.get());
value = atoi(buffer.bufPtr());
}

return value != 0;
}

void
RecHttpLoadIp(const char *value_name, IpAddr &ip4, IpAddr &ip6)
{
@@ -130,6 +147,7 @@ const char *const HttpProxyPort::OPT_SSL = "ssl";
const char *const HttpProxyPort::OPT_PLUGIN = "plugin";
const char *const HttpProxyPort::OPT_BLIND_TUNNEL = "blind";
const char *const HttpProxyPort::OPT_COMPRESSED = "compressed";
const char *const HttpProxyPort::OPT_MPTCP = "mptcp";

// File local constants.
namespace
@@ -160,7 +178,8 @@ HttpProxyPort::HttpProxyPort()
m_family(AF_INET),
m_inbound_transparent_p(false),
m_outbound_transparent_p(false),
m_transparent_passthrough(false)
m_transparent_passthrough(false),
m_mptcp(false)
{
memcpy(m_host_res_preference, host_res_default_preference_order, sizeof(m_host_res_preference));
}
@@ -364,6 +383,12 @@ HttpProxyPort::processOptions(const char *opts)
#else
Warning("Transparent pass-through requested [%s] in port descriptor '%s' but TPROXY was not configured.", item, opts);
#endif
} else if (0 == strcasecmp(OPT_MPTCP, item)) {
if (mptcp_supported()) {
m_mptcp = true;
} else {
Warning("Multipath TCP requested [%s] in port descriptor '%s' but it is not supported by this host.", item, opts);
}
} else if (nullptr != (value = this->checkPrefix(item, OPT_HOST_RES_PREFIX, OPT_HOST_RES_PREFIX_LEN))) {
this->processFamilyPreference(value);
host_res_set_p = true;
@@ -541,6 +566,10 @@ HttpProxyPort::print(char *out, size_t n)
zret += snprintf(out + zret, n - zret, ":%s", OPT_TRANSPARENT_OUTBOUND);
}

if (m_mptcp) {
zret += snprintf(out + zret, n - zret, ":%s", OPT_MPTCP);
}

if (m_transparent_passthrough) {
zret += snprintf(out + zret, n - zret, ":%s", OPT_TRANSPARENT_PASSTHROUGH);
}
@@ -47,6 +47,14 @@ using namespace std::literals;
static const std::string_view MGMT_OPT{"-M"};
static const std::string_view RUNROOT_OPT{"--run-root="};

#ifndef MPTCP_ENABLED
#if defined(linux)
#define MPTCP_ENABLED 42
#else
#define MPTCP_ENABLED 0
#endif
#endif

void
LocalManager::mgmtCleanup()
{
@@ -1025,6 +1033,21 @@ LocalManager::bindProxyPort(HttpProxyPort &port)
}
}

if (port.m_mptcp) {
#if MPTCP_ENABLED
int err;

err = setsockopt(port.m_fd, IPPROTO_TCP, MPTCP_ENABLED, &one, sizeof(one));
if (err < 0) {
mgmt_log("[bindProxyPort] Unable to enable MPTCP: %s\n", strerror(errno));
} else {
mgmt_log("[bindProxyPort] Successfully enabled MPTCP on %d\n", port.m_port);
}
#else
Debug("lm", "[bindProxyPort] Multipath TCP requested but not configured on this host");
#endif
}

if (port.m_family == AF_INET6) {
if (setsockopt(port.m_fd, IPPROTO_IPV6, IPV6_V6ONLY, SOCKOPT_ON, sizeof(int)) < 0) {
mgmt_log("[bindProxyPort] Unable to set socket options: %d : %s\n", port.m_port, strerror(errno));

0 comments on commit 2755a80

Please sign in to comment.
You can’t perform that action at this time.