Merge #9319: Break addnode out from the outbound connection limits.
032ba3f
RPC help documentation for addnode peerinfo. (Gregory Maxwell)90f13e1
Add release notes for addnode changes. (Gregory Maxwell)50bd12c
Break addnode out from the outbound connection limits. (Gregory Maxwell)
This commit is contained in:
commit
a55716abe5
7 changed files with 64 additions and 13 deletions
|
@ -62,6 +62,16 @@ Removal of Priority Estimation
|
|||
major version. To prepare for this, the default for the rate limit of priority
|
||||
transactions (`-limitfreerelay`) has been set to `0` kB/minute.
|
||||
|
||||
P2P connection management
|
||||
--------------------------
|
||||
|
||||
- Peers manually added through the addnode option or addnode RPC now have their own
|
||||
limit of eight connections which does not compete with other inbound or outbound
|
||||
connection usage and is not subject to the maxconnections limitation.
|
||||
|
||||
- New connections to manually added peers are much faster.
|
||||
|
||||
|
||||
0.14.0 Change log
|
||||
=================
|
||||
|
||||
|
|
|
@ -871,11 +871,11 @@ bool AppInitParameterInteraction()
|
|||
nMaxConnections = std::max(nUserMaxConnections, 0);
|
||||
|
||||
// Trim requested connection counts, to fit into system limitations
|
||||
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
|
||||
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
|
||||
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS)), 0);
|
||||
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
|
||||
if (nFD < MIN_CORE_FILEDESCRIPTORS)
|
||||
return InitError(_("Not enough file descriptors available."));
|
||||
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections);
|
||||
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections);
|
||||
|
||||
if (nMaxConnections < nUserMaxConnections)
|
||||
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections));
|
||||
|
@ -1109,7 +1109,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
|
||||
LogPrintf("Using data directory %s\n", GetDataDir().string());
|
||||
LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
|
||||
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||
|
||||
InitSignatureCache();
|
||||
|
||||
|
@ -1566,6 +1566,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
connOptions.nRelevantServices = nRelevantServices;
|
||||
connOptions.nMaxConnections = nMaxConnections;
|
||||
connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections);
|
||||
connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
|
||||
connOptions.nMaxFeeler = 1;
|
||||
connOptions.nBestHeight = chainActive.Height();
|
||||
connOptions.uiInterface = &uiInterface;
|
||||
|
|
42
src/net.cpp
42
src/net.cpp
|
@ -621,6 +621,7 @@ void CNode::copyStats(CNodeStats &stats)
|
|||
X(nVersion);
|
||||
X(cleanSubVer);
|
||||
X(fInbound);
|
||||
X(fAddnode);
|
||||
X(nStartingHeight);
|
||||
X(nSendBytes);
|
||||
X(mapSendBytesPerMsgCmd);
|
||||
|
@ -1631,7 +1632,12 @@ void CConnman::ThreadOpenConnections()
|
|||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
if (!pnode->fInbound) {
|
||||
if (!pnode->fInbound && !pnode->fAddnode) {
|
||||
// Netgroups for inbound and addnode peers are not excluded because our goal here
|
||||
// is to not use multiple of our limited outbound slots on a single netgroup
|
||||
// but inbound and addnode peers do not use our outbound slots. Inbound peers
|
||||
// also have the added issue that they're attacker controlled and could be used
|
||||
// to prevent us from connecting to particular hosts if we used them here.
|
||||
setConnected.insert(pnode->addr.GetGroup());
|
||||
nOutbound++;
|
||||
}
|
||||
|
@ -1776,27 +1782,35 @@ void CConnman::ThreadOpenAddedConnections()
|
|||
vAddedNodes = mapMultiArgs.at("-addnode");
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; true; i++)
|
||||
while (true)
|
||||
{
|
||||
CSemaphoreGrant grant(*semAddnode);
|
||||
std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
|
||||
bool tried = false;
|
||||
for (const AddedNodeInfo& info : vInfo) {
|
||||
if (!info.fConnected) {
|
||||
CSemaphoreGrant grant(*semOutbound);
|
||||
if (!grant.TryAcquire()) {
|
||||
// If we've used up our semaphore and need a new one, lets not wait here since while we are waiting
|
||||
// the addednodeinfo state might change.
|
||||
break;
|
||||
}
|
||||
// If strAddedNode is an IP/port, decode it immediately, so
|
||||
// OpenNetworkConnection can detect existing connections to that IP/port.
|
||||
tried = true;
|
||||
CService service(LookupNumeric(info.strAddedNode.c_str(), Params().GetDefaultPort()));
|
||||
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
|
||||
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false, false, true);
|
||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!interruptNet.sleep_for(std::chrono::minutes(2)))
|
||||
// Retry every 60 seconds if a connection was attempted, otherwise two seconds
|
||||
if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if successful, this moves the passed grant to the constructed node
|
||||
bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler)
|
||||
bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot, bool fFeeler, bool fAddnode)
|
||||
{
|
||||
//
|
||||
// Initiate outbound network connection
|
||||
|
@ -1825,6 +1839,8 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
|
|||
pnode->fOneShot = true;
|
||||
if (fFeeler)
|
||||
pnode->fFeeler = true;
|
||||
if (fAddnode)
|
||||
pnode->fAddnode = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2076,8 +2092,10 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe
|
|||
nSendBufferMaxSize = 0;
|
||||
nReceiveFloodSize = 0;
|
||||
semOutbound = NULL;
|
||||
semAddnode = NULL;
|
||||
nMaxConnections = 0;
|
||||
nMaxOutbound = 0;
|
||||
nMaxAddnode = 0;
|
||||
nBestHeight = 0;
|
||||
clientInterface = NULL;
|
||||
flagInterruptMsgProc = false;
|
||||
|
@ -2099,6 +2117,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
|
|||
nLocalServices = connOptions.nLocalServices;
|
||||
nMaxConnections = connOptions.nMaxConnections;
|
||||
nMaxOutbound = std::min((connOptions.nMaxOutbound), nMaxConnections);
|
||||
nMaxAddnode = connOptions.nMaxAddnode;
|
||||
nMaxFeeler = connOptions.nMaxFeeler;
|
||||
|
||||
nSendBufferMaxSize = connOptions.nSendBufferMaxSize;
|
||||
|
@ -2151,6 +2170,10 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
|
|||
// initialize semaphore
|
||||
semOutbound = new CSemaphore(std::min((nMaxOutbound + nMaxFeeler), nMaxConnections));
|
||||
}
|
||||
if (semAddnode == NULL) {
|
||||
// initialize semaphore
|
||||
semAddnode = new CSemaphore(nMaxAddnode);
|
||||
}
|
||||
|
||||
//
|
||||
// Start threads
|
||||
|
@ -2227,6 +2250,10 @@ void CConnman::Stop()
|
|||
if (threadSocketHandler.joinable())
|
||||
threadSocketHandler.join();
|
||||
|
||||
if (semAddnode)
|
||||
for (int i=0; i<nMaxAddnode; i++)
|
||||
semOutbound->post();
|
||||
|
||||
if (fAddressesInitialized)
|
||||
{
|
||||
DumpData();
|
||||
|
@ -2254,6 +2281,8 @@ void CConnman::Stop()
|
|||
vhListenSocket.clear();
|
||||
delete semOutbound;
|
||||
semOutbound = NULL;
|
||||
delete semAddnode;
|
||||
semAddnode = NULL;
|
||||
}
|
||||
|
||||
void CConnman::DeleteNode(CNode* pnode)
|
||||
|
@ -2554,6 +2583,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
|
|||
strSubVer = "";
|
||||
fWhitelisted = false;
|
||||
fOneShot = false;
|
||||
fAddnode = false;
|
||||
fClient = false; // set by version message
|
||||
fFeeler = false;
|
||||
fSuccessfullyConnected = false;
|
||||
|
|
11
src/net.h
11
src/net.h
|
@ -58,8 +58,10 @@ static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
|||
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000;
|
||||
/** Maximum length of strSubVer in `version` message */
|
||||
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
|
||||
/** Maximum number of outgoing nodes */
|
||||
/** Maximum number of automatic outgoing nodes */
|
||||
static const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||
/** Maximum number of addnode outgoing nodes */
|
||||
static const int MAX_ADDNODE_CONNECTIONS = 8;
|
||||
/** -listen default */
|
||||
static const bool DEFAULT_LISTEN = true;
|
||||
/** -upnp default */
|
||||
|
@ -135,6 +137,7 @@ public:
|
|||
ServiceFlags nRelevantServices = NODE_NONE;
|
||||
int nMaxConnections = 0;
|
||||
int nMaxOutbound = 0;
|
||||
int nMaxAddnode = 0;
|
||||
int nMaxFeeler = 0;
|
||||
int nBestHeight = 0;
|
||||
CClientUIInterface* uiInterface = nullptr;
|
||||
|
@ -151,7 +154,7 @@ public:
|
|||
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
||||
bool GetNetworkActive() const { return fNetworkActive; };
|
||||
void SetNetworkActive(bool active);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false);
|
||||
bool CheckIncomingNonce(uint64_t nonce);
|
||||
|
||||
bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
|
||||
|
@ -414,8 +417,10 @@ private:
|
|||
ServiceFlags nRelevantServices;
|
||||
|
||||
CSemaphore *semOutbound;
|
||||
CSemaphore *semAddnode;
|
||||
int nMaxConnections;
|
||||
int nMaxOutbound;
|
||||
int nMaxAddnode;
|
||||
int nMaxFeeler;
|
||||
std::atomic<int> nBestHeight;
|
||||
CClientUIInterface* clientInterface;
|
||||
|
@ -529,6 +534,7 @@ public:
|
|||
int nVersion;
|
||||
std::string cleanSubVer;
|
||||
bool fInbound;
|
||||
bool fAddnode;
|
||||
int nStartingHeight;
|
||||
uint64_t nSendBytes;
|
||||
mapMsgCmdSize mapSendBytesPerMsgCmd;
|
||||
|
@ -626,6 +632,7 @@ public:
|
|||
bool fWhitelisted; // This peer can bypass DoS banning.
|
||||
bool fFeeler; // If true this node is being used as a short lived feeler.
|
||||
bool fOneShot;
|
||||
bool fAddnode;
|
||||
bool fClient;
|
||||
const bool fInbound;
|
||||
bool fSuccessfullyConnected;
|
||||
|
|
|
@ -2644,6 +2644,8 @@ bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interruptMsg
|
|||
state.fShouldBan = false;
|
||||
if (pto->fWhitelisted)
|
||||
LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
|
||||
else if (pto->fAddnode)
|
||||
LogPrintf("Warning: not punishing addnoded peer %s!\n", pto->addr.ToString());
|
||||
else {
|
||||
pto->fDisconnect = true;
|
||||
if (pto->addr.IsLocal())
|
||||
|
|
|
@ -92,6 +92,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
|
|||
" \"version\": v, (numeric) The peer version, such as 7001\n"
|
||||
" \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
|
||||
" \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
|
||||
" \"addnode\": true|false, (boolean) Whether connection was due to addnode and is using an addnode slot\n"
|
||||
" \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
|
||||
" \"banscore\": n, (numeric) The ban score\n"
|
||||
" \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
|
||||
|
@ -152,6 +153,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
|
|||
// their ver message.
|
||||
obj.push_back(Pair("subver", stats.cleanSubVer));
|
||||
obj.push_back(Pair("inbound", stats.fInbound));
|
||||
obj.push_back(Pair("addnode", stats.fAddnode));
|
||||
obj.push_back(Pair("startingheight", stats.nStartingHeight));
|
||||
if (fStateStats) {
|
||||
obj.push_back(Pair("banscore", statestats.nMisbehavior));
|
||||
|
|
|
@ -264,7 +264,6 @@ public:
|
|||
grant.Release();
|
||||
grant.sem = sem;
|
||||
grant.fHaveGrant = fHaveGrant;
|
||||
sem = NULL;
|
||||
fHaveGrant = false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue