Skip to content

Commit 034f61f

Browse files
p2p: Protect extra full outbound peers by network
If a peer is the only one of its network, protect it from eviction. This improves the diversity of outbound connections with respect to reachable networks. Co-authored-by: Amiti Uttarwar <[email protected]>
1 parent 654d9bc commit 034f61f

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

src/net.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,12 @@ std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
16071607
return networks;
16081608
}
16091609

1610+
bool CConnman::MultipleManualOrFullOutboundConns(Network net) const
1611+
{
1612+
AssertLockHeld(m_nodes_mutex);
1613+
return m_network_conn_counts[net] > 1;
1614+
}
1615+
16101616
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
16111617
{
16121618
AssertLockNotHeld(m_unused_i2p_sessions_mutex);

src/net.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,9 @@ class CConnman
793793
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
794794
bool CheckIncomingNonce(uint64_t nonce);
795795

796+
// alias for thread safety annotations only, not defined
797+
RecursiveMutex& GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex);
798+
796799
bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
797800

798801
void PushMessage(CNode* pnode, CSerializedNetMsg&& msg) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
@@ -909,6 +912,8 @@ class CConnman
909912
/** Return true if we should disconnect the peer for failing an inactivity check. */
910913
bool ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const;
911914

915+
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex);
916+
912917
private:
913918
struct ListenSocket {
914919
public:

src/net_processing.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5146,10 +5146,12 @@ void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
51465146
// Pick the outbound-full-relay peer that least recently announced
51475147
// us a new block, with ties broken by choosing the more recent
51485148
// connection (higher node id)
5149+
// Protect peers from eviction if we don't have another connection
5150+
// to their network, counting both outbound-full-relay and manual peers.
51495151
NodeId worst_peer = -1;
51505152
int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
51515153

5152-
m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
5154+
m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_connman.GetNodesMutex()) {
51535155
AssertLockHeld(::cs_main);
51545156

51555157
// Only consider outbound-full-relay peers that are not already
@@ -5159,6 +5161,9 @@ void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
51595161
if (state == nullptr) return; // shouldn't be possible, but just in case
51605162
// Don't evict our protected peers
51615163
if (state->m_chain_sync.m_protect) return;
5164+
// If this is the only connection on a particular network that is
5165+
// OUTBOUND_FULL_RELAY or MANUAL, protect it.
5166+
if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
51625167
if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
51635168
worst_peer = pnode->GetId();
51645169
oldest_block_announcement = state->m_last_block_announcement;

0 commit comments

Comments
 (0)