tcp, netlink, HAS{BYTES_ACKED,MIN_RTT,GETRANDOM} and NETLINK_GET_STRICT_CHK
tcpi_bytes_acked and tcpi_min_rtt are only available on recent kernel versions: provide fall-back paths (incurring some grade of performance penalty). Support for getrandom() was introduced in Linux 3.17 and glibc 2.25: provide an alternate mechanism for that as well, reading from /dev/random. Also check if NETLINK_GET_STRICT_CHK is defined before using it: it's not strictly needed, we'll filter out irrelevant results from netlink anyway. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
daf8d057ce
commit
1776de0140
3 changed files with 58 additions and 2 deletions
15
Makefile
15
Makefile
|
@ -45,6 +45,21 @@ ifeq ($(shell printf "$(C)" | $(CC) -S -xc - -o - >/dev/null 2>&1; echo $$?),0)
|
||||||
CFLAGS += -DHAS_SND_WND
|
CFLAGS += -DHAS_SND_WND
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
C := \#include <linux/tcp.h>\nstruct tcp_info x = { .tcpi_bytes_acked = 0 };
|
||||||
|
ifeq ($(shell printf "$(C)" | $(CC) -S -xc - -o - >/dev/null 2>&1; echo $$?),0)
|
||||||
|
CFLAGS += -DHAS_BYTES_ACKED
|
||||||
|
endif
|
||||||
|
|
||||||
|
C := \#include <linux/tcp.h>\nstruct tcp_info x = { .tcpi_min_rtt = 0 };
|
||||||
|
ifeq ($(shell printf "$(C)" | $(CC) -S -xc - -o - >/dev/null 2>&1; echo $$?),0)
|
||||||
|
CFLAGS += -DHAS_MIN_RTT
|
||||||
|
endif
|
||||||
|
|
||||||
|
C := \#include <sys/random.h>\nint main(){int a=getrandom(0, 0, 0);}
|
||||||
|
ifeq ($(shell printf "$(C)" | $(CC) -S -xc - -o - >/dev/null 2>&1; echo $$?),0)
|
||||||
|
CFLAGS += -DHAS_GETRANDOM
|
||||||
|
endif
|
||||||
|
|
||||||
prefix ?= /usr/local
|
prefix ?= /usr/local
|
||||||
|
|
||||||
all: passt pasta passt4netns qrap
|
all: passt pasta passt4netns qrap
|
||||||
|
|
|
@ -46,7 +46,10 @@ static int nl_seq;
|
||||||
static int nl_sock_init_do(void *arg)
|
static int nl_sock_init_do(void *arg)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };
|
struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };
|
||||||
int *s = &nl_sock, v = 1;
|
int *s = &nl_sock;
|
||||||
|
#ifdef NETLINK_GET_STRICT_CHK
|
||||||
|
int y = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
ns:
|
ns:
|
||||||
if (((*s) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0 ||
|
if (((*s) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0 ||
|
||||||
|
@ -56,7 +59,9 @@ ns:
|
||||||
if (*s == -1 || !arg || s == &nl_sock_ns)
|
if (*s == -1 || !arg || s == &nl_sock_ns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
setsockopt(*s, SOL_NETLINK, NETLINK_GET_STRICT_CHK, &v, sizeof(v));
|
#ifdef NETLINK_GET_STRICT_CHK
|
||||||
|
setsockopt(*s, SOL_NETLINK, NETLINK_GET_STRICT_CHK, &y, sizeof(y));
|
||||||
|
#endif
|
||||||
|
|
||||||
ns_enter((struct ctx *)arg);
|
ns_enter((struct ctx *)arg);
|
||||||
s = &nl_sock_ns;
|
s = &nl_sock_ns;
|
||||||
|
|
36
tcp.c
36
tcp.c
|
@ -321,7 +321,9 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
#ifdef HAS_GETRANDOM
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
|
#endif
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
@ -760,6 +762,7 @@ static int tcp_rtt_dst_low(struct tcp_tap_conn *conn)
|
||||||
*/
|
*/
|
||||||
static void tcp_rtt_dst_check(struct tcp_tap_conn *conn, struct tcp_info *tinfo)
|
static void tcp_rtt_dst_check(struct tcp_tap_conn *conn, struct tcp_info *tinfo)
|
||||||
{
|
{
|
||||||
|
#ifdef HAS_MIN_RTT
|
||||||
int i, hole = -1;
|
int i, hole = -1;
|
||||||
|
|
||||||
if (!tinfo->tcpi_min_rtt ||
|
if (!tinfo->tcpi_min_rtt ||
|
||||||
|
@ -777,6 +780,10 @@ static void tcp_rtt_dst_check(struct tcp_tap_conn *conn, struct tcp_info *tinfo)
|
||||||
if (hole == LOW_RTT_TABLE_SIZE)
|
if (hole == LOW_RTT_TABLE_SIZE)
|
||||||
hole = 0;
|
hole = 0;
|
||||||
memcpy(low_rtt_dst + hole, &in6addr_any, sizeof(conn->a.a6));
|
memcpy(low_rtt_dst + hole, &in6addr_any, sizeof(conn->a.a6));
|
||||||
|
#else
|
||||||
|
(void)conn;
|
||||||
|
(void)tinfo;
|
||||||
|
#endif /* HAS_MIN_RTT */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1552,6 +1559,13 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
|
||||||
struct tcp_info tinfo_new;
|
struct tcp_info tinfo_new;
|
||||||
int s = conn->sock;
|
int s = conn->sock;
|
||||||
|
|
||||||
|
#ifndef HAS_BYTES_ACKED
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
|
conn->seq_ack_to_tap = conn->seq_from_tap;
|
||||||
|
if (SEQ_LT(conn->seq_ack_to_tap, prev_ack_to_tap))
|
||||||
|
conn->seq_ack_to_tap = prev_ack_to_tap;
|
||||||
|
#else
|
||||||
if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK)) ||
|
if (conn->state > ESTABLISHED || (flags & (DUP_ACK | FORCE_ACK)) ||
|
||||||
conn->local || tcp_rtt_dst_low(conn) ||
|
conn->local || tcp_rtt_dst_low(conn) ||
|
||||||
conn->snd_buf < SNDBUF_SMALL) {
|
conn->snd_buf < SNDBUF_SMALL) {
|
||||||
|
@ -1569,6 +1583,7 @@ static int tcp_update_seqack_wnd(struct ctx *c, struct tcp_tap_conn *conn,
|
||||||
if (SEQ_LT(conn->seq_ack_to_tap, prev_ack_to_tap))
|
if (SEQ_LT(conn->seq_ack_to_tap, prev_ack_to_tap))
|
||||||
conn->seq_ack_to_tap = prev_ack_to_tap;
|
conn->seq_ack_to_tap = prev_ack_to_tap;
|
||||||
}
|
}
|
||||||
|
#endif /* !HAS_BYTES_ACKED */
|
||||||
|
|
||||||
if (!KERNEL_REPORTS_SND_WND(c)) {
|
if (!KERNEL_REPORTS_SND_WND(c)) {
|
||||||
tcp_get_sndbuf(conn);
|
tcp_get_sndbuf(conn);
|
||||||
|
@ -3586,9 +3601,30 @@ int tcp_sock_init(struct ctx *c, struct timespec *now)
|
||||||
{
|
{
|
||||||
struct tcp_sock_refill_arg refill_arg = { c, 0 };
|
struct tcp_sock_refill_arg refill_arg = { c, 0 };
|
||||||
int i, port;
|
int i, port;
|
||||||
|
#ifndef HAS_GETRANDOM
|
||||||
|
int dev_random = open("/dev/random", O_RDONLY);
|
||||||
|
unsigned int random_read = 0;
|
||||||
|
|
||||||
|
while (dev_random && random_read < sizeof(c->tcp.hash_secret)) {
|
||||||
|
int ret = read(dev_random,
|
||||||
|
(uint8_t *)&c->tcp.hash_secret + random_read,
|
||||||
|
sizeof(c->tcp.hash_secret) - random_read);
|
||||||
|
|
||||||
|
if (ret == -1 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
random_read += ret;
|
||||||
|
}
|
||||||
|
if (dev_random >= 0)
|
||||||
|
close(dev_random);
|
||||||
|
if (random_read < sizeof(c->tcp.hash_secret)) {
|
||||||
|
#else
|
||||||
if (getrandom(&c->tcp.hash_secret, sizeof(c->tcp.hash_secret),
|
if (getrandom(&c->tcp.hash_secret, sizeof(c->tcp.hash_secret),
|
||||||
GRND_RANDOM) < 0) {
|
GRND_RANDOM) < 0) {
|
||||||
|
#endif /* !HAS_GETRANDOM */
|
||||||
perror("TCP initial sequence getrandom");
|
perror("TCP initial sequence getrandom");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue