From a63fcfa5b419307176eb11173c0202c8ba34d181 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 24 Dec 2020 17:40:31 -0800 Subject: [PATCH] ircd::net: Add interface to TCP_QUICKACK if supported. --- include/ircd/net/sock_opts.h | 3 +++ ircd/net.cc | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/ircd/net/sock_opts.h b/include/ircd/net/sock_opts.h index 269ba4c70..4998d9773 100644 --- a/include/ircd/net/sock_opts.h +++ b/include/ircd/net/sock_opts.h @@ -18,6 +18,7 @@ namespace ircd::net bool v6only(const socket &); bool blocking(const socket &); bool nodelay(const socket &); + bool quickack(const socket &); bool keepalive(const socket &); time_t linger(const socket &); size_t read_bufsz(const socket &); @@ -28,6 +29,7 @@ namespace ircd::net void v6only(socket &, const bool &); void blocking(socket &, const bool &); void nodelay(socket &, const bool &); + void quickack(socket &, const bool &); void keepalive(socket &, const bool &); void linger(socket &, const time_t &); // -1 is OFF; >= 0 is ON void read_bufsz(socket &, const size_t &bytes); @@ -50,6 +52,7 @@ struct ircd::net::sock_opts int8_t v6only { IGN }; int8_t blocking { IGN }; // Simulates blocking behavior int8_t nodelay { IGN }; + int8_t quickack { IGN }; int8_t keepalive { IGN }; time_t linger { IGN }; // -1 is OFF; >= 0 is ON ssize_t read_bufsz { IGN }; diff --git a/ircd/net.cc b/ircd/net.cc index fddb2d84c..9e7b31353 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -795,6 +795,7 @@ ircd::net::sock_opts::sock_opts(const socket &socket) :v6only{net::v6only(socket)} ,blocking{net::blocking(socket)} ,nodelay{net::nodelay(socket)} +,quickack{net::quickack(socket)} ,keepalive{net::keepalive(socket)} ,linger{net::linger(socket)} ,read_bufsz{ssize_t(net::read_bufsz(socket))} @@ -819,6 +820,9 @@ ircd::net::set(socket &socket, if(opts.nodelay != opts.IGN) net::nodelay(socket, opts.nodelay); + if(opts.quickack != opts.IGN) + net::quickack(socket, opts.quickack); + if(opts.keepalive != opts.IGN) net::keepalive(socket, opts.keepalive); @@ -919,6 +923,27 @@ ircd::net::keepalive(socket &socket, sd.set_option(option); } +void +ircd::net::quickack(socket &socket, + const bool &b) +#if defined(TCP_QUICKACK) && defined(SOL_SOCKET) +{ + ip::tcp::socket &sd(socket); + const auto &fd + { + sd.lowest_layer().native_handle() + }; + + const int val(b); + const socklen_t len(sizeof(val)); + syscall(::setsockopt, fd, SOL_SOCKET, TCP_QUICKACK, &val, len); +} +#else +{ + #warning "TCP_QUICKACK is not defined on this platform." +} +#endif + void ircd::net::nodelay(socket &socket, const bool &b) @@ -1023,6 +1048,29 @@ ircd::net::keepalive(const socket &socket) return option.value(); } +bool +ircd::net::quickack(const socket &socket) +#if defined(TCP_QUICKACK) && defined(SOL_SOCKET) +{ + const ip::tcp::socket &sd(socket); + const auto &fd + { + mutable_cast(sd).lowest_layer().native_handle() + }; + + uint32_t ret; + socklen_t len(sizeof(ret)); + syscall(::getsockopt, fd, SOL_SOCKET, TCP_QUICKACK, &ret, &len); + assert(len <= sizeof(ret)); + return ret; +} +#else +{ + #warning "TCP_QUICKACK is not defined on this platform." + return false; +} +#endif + bool ircd::net::nodelay(const socket &socket) {