Skip to content

Commit

Permalink
Merge #28464: net: improve max-connection limits code
Browse files Browse the repository at this point in the history
df69b22 doc: improve documentation around connection limit maximums (Amiti Uttarwar)
adc171e scripted-diff: Rename connection limit variables (Amiti Uttarwar)
e9fd9c0 net: add m_max_inbound to connman (Amiti Uttarwar)
c25e0e0 net, refactor: move calculations for connection type limits into connman (Amiti Uttarwar)

Pull request description:

  This is joint work with amitiuttarwar.

  This has the first few commits of #28463. It is not strictly a prerequisite for that, but has changes that in our opinion make sense on their own.
  It improves the handling of maximum numbers for different connection types (that are set during init and don’t change after) by:
  * moving all calculations into one place, `CConnMan::Init()`. Before, they were dispersed between `Init`, `CConnman::Init` and other parts of `CConnman`, resulting in some duplicated test code.
  * removing the possibility of having a negative maximum of inbound connections, which is hard to argue about
  * renaming of variables and doc improvements

ACKs for top commit:
  amitiuttarwar:
    co-author review ACK df69b22
  naumenkogs:
    ACK df69b22
  achow101:
    ACK df69b22

Tree-SHA512: 913d56136bc1df739978de50db67302f88bac2a9d34748ae96763288d97093e998fc0f94f9b6eff12867712d7e86225af6128f4170bf2b5b8ab76f024870a22c
  • Loading branch information
achow101 committed Nov 7, 2023
2 parents 962ea5c + df69b22 commit 82ea4e7
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 35 deletions.
8 changes: 2 additions & 6 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> automatic connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection memory usage for the send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by outbound peers forward or backward by this amount (default: %u seconds).", DEFAULT_MAX_TIME_ADJUSTMENT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
Expand Down Expand Up @@ -1751,11 +1751,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)

CConnman::Options connOptions;
connOptions.nLocalServices = nLocalServices;
connOptions.nMaxConnections = nMaxConnections;
connOptions.m_max_outbound_full_relay = std::min(MAX_OUTBOUND_FULL_RELAY_CONNECTIONS, connOptions.nMaxConnections);
connOptions.m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, connOptions.nMaxConnections-connOptions.m_max_outbound_full_relay);
connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
connOptions.nMaxFeeler = MAX_FEELER_CONNECTIONS;
connOptions.m_max_automatic_connections = nMaxConnections;
connOptions.uiInterface = &uiInterface;
connOptions.m_banman = node.banman.get();
connOptions.m_msgproc = node.peerman.get();
Expand Down
15 changes: 7 additions & 8 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1730,7 +1730,6 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
const CAddress& addr)
{
int nInbound = 0;
int nMaxInbound = nMaxConnections - m_max_outbound;

AddWhitelistPermissionFlags(permission_flags, addr);
if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::Implicit)) {
Expand Down Expand Up @@ -1776,13 +1775,13 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,

// Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= m_max_inbound && discouraged)
{
LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToStringAddrPort());
return;
}

if (nInbound >= nMaxInbound)
if (nInbound >= m_max_inbound)
{
if (!AttemptToEvictConnection()) {
// No connection to evict, disconnect the new connection
Expand Down Expand Up @@ -2733,7 +2732,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// different netgroups in ipv4/ipv6 networks + all peers in Tor/I2P/CJDNS networks.
// Don't record addrman failure attempts when node is offline. This can be identified since all local
// network connections (if any) belong in the same netgroup, and the size of `outbound_ipv46_peer_netgroups` would only be 1.
const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(nMaxConnections - 1, 2)};
const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(m_max_automatic_connections - 1, 2)};
// Use BIP324 transport when both us and them have NODE_V2_P2P set.
const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2);
OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*strDest=*/nullptr, conn_type, use_v2transport);
Expand Down Expand Up @@ -3208,11 +3207,11 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)

if (semOutbound == nullptr) {
// initialize semaphore
semOutbound = std::make_unique<CSemaphore>(std::min(m_max_outbound, nMaxConnections));
semOutbound = std::make_unique<CSemaphore>(std::min(m_max_automatic_outbound, m_max_automatic_connections));
}
if (semAddnode == nullptr) {
// initialize semaphore
semAddnode = std::make_unique<CSemaphore>(nMaxAddnode);
semAddnode = std::make_unique<CSemaphore>(m_max_addnode);
}

//
Expand Down Expand Up @@ -3293,13 +3292,13 @@ void CConnman::Interrupt()
g_socks5_interrupt();

if (semOutbound) {
for (int i=0; i<m_max_outbound; i++) {
for (int i=0; i<m_max_automatic_outbound; i++) {
semOutbound->post();
}
}

if (semAddnode) {
for (int i=0; i<nMaxAddnode; i++) {
for (int i=0; i<m_max_addnode; i++) {
semAddnode->post();
}
}
Expand Down
38 changes: 23 additions & 15 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,11 +1045,7 @@ class CConnman
struct Options
{
ServiceFlags nLocalServices = NODE_NONE;
int nMaxConnections = 0;
int m_max_outbound_full_relay = 0;
int m_max_outbound_block_relay = 0;
int nMaxAddnode = 0;
int nMaxFeeler = 0;
int m_max_automatic_connections = 0;
CClientUIInterface* uiInterface = nullptr;
NetEventsInterface* m_msgproc = nullptr;
BanMan* m_banman = nullptr;
Expand All @@ -1076,13 +1072,12 @@ class CConnman
AssertLockNotHeld(m_total_bytes_sent_mutex);

nLocalServices = connOptions.nLocalServices;
nMaxConnections = connOptions.nMaxConnections;
m_max_outbound_full_relay = std::min(connOptions.m_max_outbound_full_relay, connOptions.nMaxConnections);
m_max_outbound_block_relay = connOptions.m_max_outbound_block_relay;
m_max_automatic_connections = connOptions.m_max_automatic_connections;
m_max_outbound_full_relay = std::min(MAX_OUTBOUND_FULL_RELAY_CONNECTIONS, m_max_automatic_connections);
m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, m_max_automatic_connections - m_max_outbound_full_relay);
m_max_automatic_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + m_max_feeler;
m_max_inbound = std::max(0, m_max_automatic_connections - m_max_automatic_outbound);
m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;
nMaxAddnode = connOptions.nMaxAddnode;
nMaxFeeler = connOptions.nMaxFeeler;
m_max_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + nMaxFeeler;
m_client_interface = connOptions.uiInterface;
m_banman = connOptions.m_banman;
m_msgproc = connOptions.m_msgproc;
Expand Down Expand Up @@ -1466,7 +1461,18 @@ class CConnman

std::unique_ptr<CSemaphore> semOutbound;
std::unique_ptr<CSemaphore> semAddnode;
int nMaxConnections;

/**
* Maximum number of automatic connections permitted, excluding manual
* connections but including inbounds. May be changed by the user and is
* potentially limited by the operating system (number of file descriptors).
*/
int m_max_automatic_connections;

/*
* Maximum number of peers by connection type. Might vary from defaults
* based on -maxconnections init value.
*/

// How many full-relay (tx, block, addr) outbound peers we want
int m_max_outbound_full_relay;
Expand All @@ -1475,9 +1481,11 @@ class CConnman
// We do not relay tx or addr messages with these peers
int m_max_outbound_block_relay;

int nMaxAddnode;
int nMaxFeeler;
int m_max_outbound;
int m_max_addnode{MAX_ADDNODE_CONNECTIONS};
int m_max_feeler{MAX_FEELER_CONNECTIONS};
int m_max_automatic_outbound;
int m_max_inbound;

bool m_use_addrman_outgoing;
CClientUIInterface* m_client_interface;
NetEventsInterface* m_msgproc;
Expand Down
8 changes: 2 additions & 6 deletions src/test/denialofservice_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)

constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
CConnman::Options options;
options.nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
options.m_max_outbound_full_relay = max_outbound_full_relay;
options.nMaxFeeler = MAX_FEELER_CONNECTIONS;
options.m_max_automatic_connections = DEFAULT_MAX_PEER_CONNECTIONS;

const auto time_init{GetTime<std::chrono::seconds>()};
SetMockTime(time_init);
Expand Down Expand Up @@ -248,9 +246,7 @@ BOOST_AUTO_TEST_CASE(block_relay_only_eviction)
constexpr int max_outbound_block_relay{MAX_BLOCK_RELAY_ONLY_CONNECTIONS};
constexpr int64_t MINIMUM_CONNECT_TIME{30};
CConnman::Options options;
options.nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
options.m_max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
options.m_max_outbound_block_relay = max_outbound_block_relay;
options.m_max_automatic_connections = DEFAULT_MAX_PEER_CONNECTIONS;

connman->Init(options);
std::vector<CNode*> vNodes;
Expand Down

0 comments on commit 82ea4e7

Please sign in to comment.