From 3b13a3f2a1f177f1caf0614c574c5d4c3936df39 Mon Sep 17 00:00:00 2001 From: SidorKozlov Date: Wed, 3 May 2023 15:59:35 +0200 Subject: [PATCH] Configurable minimum successful tunnels --- libi2pd/Config.cpp | 1 + libi2pd/NetDb.cpp | 56 ++++++++++++++++++++++++---------------------- libi2pd/NetDb.hpp | 1 - libi2pd/Tunnel.h | 9 ++++---- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 39af997b..6b515ef9 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -78,6 +78,7 @@ namespace config { ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.openfiles", value()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.transittunnels", value()->default_value(5000), "Maximum active transit tunnels (default:5000)") + ("limits.zombies", value()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)") ("limits.ntcpsoft", value()->default_value(0), "Ignored") ("limits.ntcphard", value()->default_value(0), "Ignored") ("limits.ntcpthreads", value()->default_value(1), "Ignored") diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index d3346236..aea97adc 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -245,19 +245,19 @@ namespace data updated = false; m_Requests.RequestComplete (ident, r); return r; - } + } if (r->IsUnreachable ()) { // delete router as invalid after update m_RouterInfos.erase (ident); if (wasFloodfill) - { + { std::unique_lock l(m_FloodfillsMutex); m_Floodfills.Remove (r->GetIdentHash ()); - } + } m_Requests.RequestComplete (ident, nullptr); - return nullptr; - } + return nullptr; + } } LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated @@ -419,7 +419,7 @@ namespace data if (profile) profile->Unreachable (); } - } + } } void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports) @@ -429,9 +429,9 @@ namespace data { std::unique_lock l(m_RouterInfosMutex); r->ExcludeReachableTransports (transports); - } - } - + } + } + void NetDb::Reseed () { if (!m_Reseeder) @@ -607,7 +607,9 @@ namespace data uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); auto uptime = i2p::context.GetUptime (); - bool isLowRate = false; // i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE; + double minTunnelCreationSuccessRate; + i2p::config::GetOption("limits.zombies", minTunnelCreationSuccessRate); + bool isLowRate = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < minTunnelCreationSuccessRate; // routers don't expire if less than 90 or uptime is less than 1 hour bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes if (checkForExpiration && uptime > 3600) // 1 hour @@ -622,12 +624,12 @@ namespace data if (it.second->IsUpdated ()) { if (it.second->GetBuffer ()) - { + { // we have something to save it.second->SaveToFile (m_Storage.Path(ident)); it.second->SetUnreachable (false); it.second->DeleteBuffer (); - } + } it.second->SetUpdated (false); updatedCount++; continue; @@ -639,7 +641,7 @@ namespace data (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) it.second->SetUnreachable (false); if (!it.second->IsUnreachable ()) - { + { // find & mark expired routers if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport it.second->SetUnreachable (true); @@ -652,7 +654,7 @@ namespace data } if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ())) it.second->SetUnreachable (false); // don't expire connected router - } + } if (it.second->IsUnreachable ()) { @@ -667,7 +669,7 @@ namespace data m_RouterInfoBuffersPool.CleanUpMt (); m_RouterInfoAddressesPool.CleanUpMt (); m_RouterInfoAddressVectorsPool.CleanUpMt (); - m_IdentitiesPool.CleanUpMt (); + m_IdentitiesPool.CleanUpMt (); if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers"); @@ -682,10 +684,10 @@ namespace data if (it->second->IsUnreachable ()) it = m_RouterInfos.erase (it); else - { + { it->second->DropProfile (); it++; - } + } } } // clean up expired floodfills or not floodfills anymore @@ -724,9 +726,9 @@ namespace data if (outbound && inbound) { auto msg = dest->CreateRequestMessage (floodfill, inbound); - outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, + outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); - } + } else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); @@ -794,7 +796,7 @@ namespace data uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW - { + { auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); if (!tunnelID) // send response directly transports.SendMessage (buf + offset, deliveryStatus); @@ -807,7 +809,7 @@ namespace data else LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found"); } - } + } offset += 32; } // we must send reply back before this check @@ -1315,16 +1317,16 @@ namespace data return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () && !excluded.count (r->GetIdentHash ()); }); - } + } if (v.empty ()) return res; - + XORMetric ourMetric; if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash (); for (auto& it: v) { if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break; res.push_back (it->GetIdentHash ()); - } + } return res; } @@ -1367,10 +1369,10 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto& it: m_RouterInfos) it.second->UpdateIntroducers (ts); - } + } SaveUpdated (); - } - + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index b6dc8ce7..0222de0d 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -38,7 +38,6 @@ namespace data { const int NETDB_MIN_ROUTERS = 90; const int NETDB_MIN_FLOODFILLS = 5; - const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 5810a7a8..e6e3c3a5 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -45,7 +45,7 @@ namespace tunnel const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds - + const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12 const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6 @@ -232,8 +232,8 @@ namespace tunnel void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; - bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; - + bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; }; + private: template @@ -292,7 +292,7 @@ namespace tunnel i2p::util::Queue > m_Queue; i2p::util::MemoryPoolMt > m_I2NPTunnelEndpointMessagesMemoryPool; i2p::util::MemoryPoolMt > m_I2NPTunnelMessagesMemoryPool; - uint16_t m_MaxNumTransitTunnels; + uint16_t m_MaxNumTransitTunnels; // count of tunnels for total TCSR algorithm int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations; double m_TunnelCreationSuccessRate; @@ -311,6 +311,7 @@ namespace tunnel int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents + double GetPreciseTunnelCreationSuccessRate () const { return m_TunnelCreationSuccessRate * 100; } // in percents int GetTotalTunnelCreationSuccessRate () const // in percents { int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations;