Skip to content

Commit

Permalink
Socket MaxTCPConnections Limiter (New Connections): Use system's maxi…
Browse files Browse the repository at this point in the history
…mum concurrent TCP connections, disable if undefined

Used system value on a Linux kernel are
- /proc/sys/net/ipv4/tcp_max_orphans
  See https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html
- /proc/sys/net/nf_conntrack_max
  See https://www.kernel.org/doc/html/latest/networking/nf_conntrack-sysctl.html

Previous confusion about 'max connections' semantics has been resolved,
as this `net::Default::maxTCPConnections` is unrelated to session count
but actual outfacing TCP connections only.

Signed-off-by: Sven Göthel <[email protected]>
Change-Id: Iad74f253bdac5636757b130b299b5deacda658db
  • Loading branch information
Sven Göthel committed Oct 29, 2024
1 parent d481ea8 commit 32b688b
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 13 deletions.
16 changes: 16 additions & 0 deletions common/Util-desktop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <config.h>

#include "Util.hpp"
#include "FileUtil.hpp"

#ifdef __linux__
#include <sys/time.h>
Expand Down Expand Up @@ -160,6 +161,21 @@ std::size_t getTotalSystemMemoryKb()
return totalMemKb;
}

std::size_t getMaxConcurrentTCPConnections()
{
#ifdef __linux__
char line[1024+1]; // includes EOS
const ssize_t tcp_max_orphans = FileUtil::readDecimal("/proc/sys/net/ipv4/tcp_max_orphans", line, sizeof(line)-1, 0);
const ssize_t nf_conntrack_max = FileUtil::readDecimal("/proc/sys/net/nf_conntrack_max", line, sizeof(line)-1, 0);
LOG_DBG("MaxConcurrentTCPConnections: min(orphans " << tcp_max_orphans
<< ", conntrack " << nf_conntrack_max << ") = "
<< std::min(tcp_max_orphans, nf_conntrack_max));
return std::min(tcp_max_orphans, nf_conntrack_max);
#else
return 0;
#endif
}

std::size_t getFromCGroup(const std::string& group, const std::string& key)
{
std::size_t num = 0;
Expand Down
1 change: 1 addition & 0 deletions common/Util-mobile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ int spawnProcess(const std::string& cmd, const StringVector& args) { return 0; }

std::string getHumanizedBytes(unsigned long nBytes) { return std::string(); }
size_t getTotalSystemMemoryKb() { return 0; }
std::size_t getMaxConcurrentTCPConnections() { return 0; }
std::size_t getFromFile(const char* path) { return 0; }
std::size_t getCGroupMemLimit() { return 0; }
std::size_t getCGroupMemSoftLimit() { return 0; }
Expand Down
3 changes: 3 additions & 0 deletions common/Util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ namespace Util
/// Returns the total physical memory (in kB) available in the system
size_t getTotalSystemMemoryKb();

/// Returns the maximum number of concurrent TCP connections, zero if undefined.
std::size_t getMaxConcurrentTCPConnections();

/// Returns the numerical content of a file at @path
std::size_t getFromFile(const char *path);

Expand Down
10 changes: 5 additions & 5 deletions net/NetUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ class DefaultValues
/// StreamSocket inactivity timeout in us (3600s default). Zero disables instrument.
std::chrono::microseconds inactivityTimeout;

/// Maximum total connections (9999 or MAX_CONNECTIONS). Zero disables instrument.
size_t maxConnections;
/// Maximum number of concurrent TCP connections. Zero disables instrument.
size_t maxTCPConnections;

std::ostream& stream(std::ostream& os) const
{
os << "Socket[MaxConnections " << maxConnections
<< "], Inactivity[timeout "
os << "Socket[maxTCPConnections " << maxTCPConnections
<< "], Inactivity-timeout "
<< std::setw(5)
<< inactivityTimeout.count() / 1000.0 << "ms]";
<< inactivityTimeout.count() / 1000.0 << "ms";
return os;
}

Expand Down
2 changes: 1 addition & 1 deletion net/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ std::mutex SocketPoll::_statsMutex;
std::atomic<size_t> SocketPoll::_statsConnectionCount(0);

net::DefaultValues net::Defaults = { .inactivityTimeout = std::chrono::seconds(3600),
.maxConnections = 9999 };
.maxTCPConnections = 0 /* undefined default */};

size_t SocketPoll::statsConnectionMod(size_t added, size_t removed) {
if( added == 0 && removed == 0 ) {
Expand Down
2 changes: 1 addition & 1 deletion test/UnitTimeoutConnections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class UnitTimeoutConnections : public UnitTimeoutBase1
{
void configure(Poco::Util::LayeredConfiguration& /* config */) override
{
net::Defaults.maxConnections = ConnectionLimit;
net::Defaults.maxTCPConnections = ConnectionLimit;
}

public:
Expand Down
7 changes: 2 additions & 5 deletions wsd/COOLWSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2336,7 +2336,7 @@ void COOLWSD::innerInitialize(Poco::Util::Application& self)
UnitWSD::get().setWSD(this);

// net::Defaults: Set MaxConnections field
net::Defaults.maxConnections = std::max<size_t>(3, MAX_CONNECTIONS);
net::Defaults.maxTCPConnections = std::max(Util::getMaxConcurrentTCPConnections(), std::max<size_t>(3, MAX_CONNECTIONS));

// Allow UT to manipulate before using configuration values.
UnitWSD::get().configure(conf);
Expand Down Expand Up @@ -2747,19 +2747,16 @@ void COOLWSD::innerInitialize(Poco::Util::Application& self)
if (getConfigValue<bool>(conf, "home_mode.enable", false))
{
COOLWSD::MaxConnections = 20;
net::Defaults.maxConnections = COOLWSD::MaxConnections; // re-align
COOLWSD::MaxDocuments = 10;
}
else
{
conf.setString("feedback.show", "true");
conf.setString("welcome.enable", "true");
COOLWSD::MaxConnections = net::Defaults.maxConnections; // aligned w/ MAX_CONNECTIONS above
COOLWSD::MaxDocuments = MAX_DOCUMENTS;
}
#else
{
COOLWSD::MaxConnections = net::Defaults.maxConnections; // aligned w/ MAX_CONNECTIONS above
COOLWSD::MaxDocuments = MAX_DOCUMENTS;
}
#endif
Expand Down Expand Up @@ -2935,7 +2932,7 @@ void COOLWSD::innerInitialize(Poco::Util::Application& self)
#endif

WebServerPoll = std::make_unique<TerminatingPoll>("websrv_poll");
WebServerPoll->setLimiter( net::Defaults.maxConnections );
WebServerPoll->setLimiter( net::Defaults.maxTCPConnections ); // enabled if `maxTCPConnections` > 0

#if !MOBILEAPP
net::AsyncDNS::startAsyncDNS();
Expand Down
2 changes: 1 addition & 1 deletion wsd/DocumentBroker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class DocumentBroker::DocumentBrokerPoll final : public TerminatingPoll
TerminatingPoll(threadName),
_docBroker(docBroker)
{
setLimiter( net::Defaults.maxConnections );
setLimiter( net::Defaults.maxTCPConnections ); // enabled if `maxTCPConnections` > 0
}

void pollingThread() override
Expand Down

0 comments on commit 32b688b

Please sign in to comment.