Browse Source

Detect kernel support for MPTCP at runtime

pull/2911/head
Maxim Galaganov 2 years ago
committed by Max Lv
parent
commit
d61d09aa0c
8 changed files with 57 additions and 44 deletions
  1. 2
      src/jconf.c
  2. 19
      src/local.c
  3. 9
      src/netutils.h
  4. 19
      src/redir.c
  5. 16
      src/server.c
  6. 18
      src/tunnel.c
  7. 17
      src/utils.c
  8. 1
      src/utils.h

2
src/jconf.c

@ -340,7 +340,7 @@ read_jconf(const char *file)
} else if (strcmp(name, "mptcp") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'mptcp' must be a boolean");
conf.mptcp = value->u.boolean;
conf.mptcp = get_mptcp(value->u.boolean);
} else if (strcmp(name, "ipv6_first") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'ipv6_first' must be a boolean");

19
src/local.c

@ -1273,13 +1273,10 @@ create_remote(listen_ctx_t *listener,
}
int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);
if (remotefd == -1) {
ERROR("socket");
return NULL;
@ -1291,11 +1288,11 @@ create_remote(listen_ctx_t *listener,
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
#ifndef IPPROTO_MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
@ -1307,10 +1304,9 @@ create_remote(listen_ctx_t *listener,
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif
if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
@ -1499,8 +1495,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;

9
src/netutils.h

@ -60,14 +60,19 @@ typedef struct {
char *port;
} ss_addr_t;
// Be compatible with older libc.
#ifndef IPPROTO_MPTCP
/* MPTCP_ENABLED setsockopt values for kernel 4 & 3, best behaviour to be independant of kernel version is to test from newest to the latest values */
#define IPPROTO_MPTCP 262
#endif
/* MPTCP_ENABLED setsockopt values for out-of-tree kernel 4 & 3, best behaviour
* to be independent of kernel version is to test from newest to latest values.
*/
#ifndef MPTCP_ENABLED
static const char mptcp_enabled_values[] = { 42, 26, 0 };
#else
static const char mptcp_enabled_values[] = { MPTCP_ENABLED, 0 };
#endif
#endif
#ifndef UPDATE_INTERVAL
#define UPDATE_INTERVAL 5

19
src/redir.c

@ -771,11 +771,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];
int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);
if (remotefd == -1) {
ERROR("socket");
@ -814,12 +812,11 @@ accept_cb(EV_P_ ev_io *w, int revents)
#endif
}
#ifndef IPPROTO_MPTCP
// Enable MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
@ -831,10 +828,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif
if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
@ -959,8 +955,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;

16
src/server.c

@ -595,11 +595,9 @@ create_and_bind(const char *host, const char *port, int mptcp)
for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {
int protocol = rp->ai_protocol;
#ifdef IPPROTO_MPTCP
if (mptcp == 1) {
protocol = IPPROTO_MPTCP;
if (mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
listen_sock = socket(rp->ai_family, rp->ai_socktype, protocol);
if (listen_sock == -1) {
continue;
@ -622,7 +620,7 @@ create_and_bind(const char *host, const char *port, int mptcp)
}
}
#ifndef IPPROTO_MPTCP
// Enable out-of-tree mptcp
if (mptcp == 1) {
int i = 0;
while ((mptcp = mptcp_enabled_values[i]) > 0) {
@ -633,10 +631,9 @@ create_and_bind(const char *host, const char *port, int mptcp)
i++;
}
if (mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
@ -1874,8 +1871,9 @@ main(int argc, char **argv)
plugin_opts = optarg;
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_KEY:
key = optarg;

18
src/tunnel.c

@ -737,11 +737,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];
int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);
if (remotefd == -1) {
ERROR("socket");
@ -773,11 +771,11 @@ accept_cb(EV_P_ ev_io *w, int revents)
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
#ifndef IPPROTO_MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
@ -789,10 +787,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif
if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
@ -956,8 +953,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;

17
src/utils.c

@ -578,3 +578,20 @@ load16_be(const void *s)
return ((uint16_t)in[0] << 8)
| ((uint16_t)in[1]);
}
int
get_mptcp(int enable)
{
const char oldpath[] = "/proc/sys/net/mptcp/mptcp_enabled";
if (enable) {
// Check if kernel has out-of-tree MPTCP support.
if (access(oldpath, F_OK) != -1)
return 1;
// Otherwise, just use IPPROTO_MPTCP.
return -1;
}
return 0;
}

1
src/utils.h

@ -250,5 +250,6 @@ void *ss_realloc(void *ptr, size_t new_size);
int ss_is_ipv6addr(const char *addr);
char *get_default_conf(void);
uint16_t load16_be(const void *s);
int get_mptcp(int enable);
#endif // _UTILS_H
Loading…
Cancel
Save