mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-19 01:09:58 +00:00
implement medium congestion indication
This commit is contained in:
parent
2b6a95cbee
commit
d677d67676
@ -376,7 +376,7 @@ namespace i2p
|
|||||||
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
|
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
|
||||||
uint8_t retCode = 0;
|
uint8_t retCode = 0;
|
||||||
// replace record to reply
|
// replace record to reply
|
||||||
if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ())
|
if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < 100)
|
||||||
{
|
{
|
||||||
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
||||||
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||||
@ -586,7 +586,7 @@ namespace i2p
|
|||||||
// check if we accept this tunnel
|
// check if we accept this tunnel
|
||||||
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
|
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
|
||||||
uint8_t retCode = 0;
|
uint8_t retCode = 0;
|
||||||
if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ())
|
if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= 100)
|
||||||
retCode = 30;
|
retCode = 30;
|
||||||
if (!retCode)
|
if (!retCode)
|
||||||
{
|
{
|
||||||
|
@ -1137,13 +1137,14 @@ namespace i2p
|
|||||||
return i2p::tunnel::tunnels.GetExploratoryPool ();
|
return i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RouterContext::IsHighCongestion () const
|
int RouterContext::GetCongestionLevel (bool longTerm) const
|
||||||
{
|
{
|
||||||
return i2p::tunnel::tunnels.IsTooManyTransitTunnels () ||
|
return std::max (
|
||||||
i2p::transport::transports.IsBandwidthExceeded () ||
|
i2p::tunnel::tunnels.GetCongestionLevel (),
|
||||||
i2p::transport::transports.IsTransitBandwidthExceeded ();
|
i2p::transport::transports.GetCongestionLevel (longTerm)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len)
|
void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
|
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
|
||||||
@ -1447,10 +1448,16 @@ namespace i2p
|
|||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
auto c = i2p::data::RouterInfo::eLowCongestion;
|
auto c = i2p::data::RouterInfo::eLowCongestion;
|
||||||
if (!AcceptsTunnels ())
|
if (!AcceptsTunnels () || m_ShareRatio == 0)
|
||||||
c = i2p::data::RouterInfo::eRejectAll;
|
c = i2p::data::RouterInfo::eRejectAll;
|
||||||
else if (IsHighCongestion ())
|
else
|
||||||
c = i2p::data::RouterInfo::eHighCongestion;
|
{
|
||||||
|
int congestionLevel = GetCongestionLevel (true);
|
||||||
|
if (congestionLevel > 90)
|
||||||
|
c = i2p::data::RouterInfo::eHighCongestion;
|
||||||
|
else if (congestionLevel > 70)
|
||||||
|
c = i2p::data::RouterInfo::eMediumCongestion;
|
||||||
|
}
|
||||||
if (m_RouterInfo.UpdateCongestion (c))
|
if (m_RouterInfo.UpdateCongestion (c))
|
||||||
UpdateRouterInfo ();
|
UpdateRouterInfo ();
|
||||||
ScheduleCongestionUpdate ();
|
ScheduleCongestionUpdate ();
|
||||||
|
@ -167,7 +167,7 @@ namespace garlic
|
|||||||
void SetShareRatio (int percents); // 0 - 100
|
void SetShareRatio (int percents); // 0 - 100
|
||||||
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
|
bool AcceptsTunnels () const { return m_AcceptsTunnels; };
|
||||||
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
|
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
|
||||||
bool IsHighCongestion () const;
|
int GetCongestionLevel (bool longTerm) const;
|
||||||
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
|
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
|
||||||
bool SupportsV4 () const { return m_RouterInfo.IsV4 (); };
|
bool SupportsV4 () const { return m_RouterInfo.IsV4 (); };
|
||||||
bool SupportsMesh () const { return m_RouterInfo.IsMesh (); };
|
bool SupportsMesh () const { return m_RouterInfo.IsMesh (); };
|
||||||
|
@ -140,10 +140,8 @@ namespace transport
|
|||||||
m_X25519KeysPairSupplier (15), // 15 pre-generated keys
|
m_X25519KeysPairSupplier (15), // 15 pre-generated keys
|
||||||
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
|
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
|
||||||
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
|
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
|
||||||
m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), m_LastTransitBandwidthUpdateBytes (0),
|
|
||||||
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
|
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
|
||||||
m_LastInBandwidth15sUpdateBytes (0), m_LastOutBandwidth15sUpdateBytes (0), m_LastTransitBandwidth15sUpdateBytes (0),
|
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0)
|
||||||
m_LastBandwidth15sUpdateTime (0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,6 +304,16 @@ namespace transport
|
|||||||
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT));
|
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5 * SESSION_CREATION_TIMEOUT));
|
||||||
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
|
||||||
|
|
||||||
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
|
for (int i = 0; i < TRAFFIC_SAMPLE_COUNT; i++)
|
||||||
|
{
|
||||||
|
m_TrafficSamples[i].Timestamp = ts - (TRAFFIC_SAMPLE_COUNT - i - 1) * 1000;
|
||||||
|
m_TrafficSamples[i].TotalReceivedBytes = 0;
|
||||||
|
m_TrafficSamples[i].TotalSentBytes = 0;
|
||||||
|
m_TrafficSamples[i].TotalTransitTransmittedBytes = 0;
|
||||||
|
}
|
||||||
|
m_TrafficSamplePtr = TRAFFIC_SAMPLE_COUNT - 1;
|
||||||
|
|
||||||
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
|
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
|
||||||
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
|
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
|
||||||
|
|
||||||
@ -364,51 +372,62 @@ namespace transport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Transports::UpdateBandwidthValues(int interval, uint32_t& in, uint32_t& out, uint32_t& transit)
|
||||||
|
{
|
||||||
|
TrafficSample& sample1 = m_TrafficSamples[m_TrafficSamplePtr];
|
||||||
|
TrafficSample& sample2 = m_TrafficSamples[(TRAFFIC_SAMPLE_COUNT + m_TrafficSamplePtr - interval) % TRAFFIC_SAMPLE_COUNT];
|
||||||
|
auto delta = sample1.Timestamp - sample2.Timestamp;
|
||||||
|
in = (sample1.TotalReceivedBytes - sample2.TotalReceivedBytes) * 1000 / delta;
|
||||||
|
out = (sample1.TotalSentBytes - sample2.TotalSentBytes) * 1000 / delta;
|
||||||
|
transit = (sample1.TotalTransitTransmittedBytes - sample2.TotalTransitTransmittedBytes) * 1000 / delta;
|
||||||
|
}
|
||||||
|
|
||||||
void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode)
|
void Transports::HandleUpdateBandwidthTimer (const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
m_TrafficSamplePtr++;
|
||||||
|
if (m_TrafficSamplePtr == TRAFFIC_SAMPLE_COUNT)
|
||||||
|
m_TrafficSamplePtr = 0;
|
||||||
|
|
||||||
// updated every second
|
TrafficSample& sample = m_TrafficSamples[m_TrafficSamplePtr];
|
||||||
m_InBandwidth = m_TotalReceivedBytes - m_LastInBandwidthUpdateBytes;
|
sample.Timestamp = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
m_OutBandwidth = m_TotalSentBytes - m_LastOutBandwidthUpdateBytes;
|
sample.TotalReceivedBytes = m_TotalReceivedBytes;
|
||||||
m_TransitBandwidth = m_TotalTransitTransmittedBytes - m_LastTransitBandwidthUpdateBytes;
|
sample.TotalSentBytes = m_TotalSentBytes;
|
||||||
|
sample.TotalTransitTransmittedBytes = m_TotalTransitTransmittedBytes;
|
||||||
|
|
||||||
m_LastInBandwidthUpdateBytes = m_TotalReceivedBytes;
|
UpdateBandwidthValues (1, m_InBandwidth, m_OutBandwidth, m_TransitBandwidth);
|
||||||
m_LastOutBandwidthUpdateBytes = m_TotalSentBytes;
|
UpdateBandwidthValues (15, m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s);
|
||||||
m_LastTransitBandwidthUpdateBytes = m_TotalTransitTransmittedBytes;
|
UpdateBandwidthValues (300, m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m);
|
||||||
|
|
||||||
// updated every 15 seconds
|
|
||||||
auto delta = ts - m_LastBandwidth15sUpdateTime;
|
|
||||||
if (delta > 15 * 1000)
|
|
||||||
{
|
|
||||||
m_InBandwidth15s = (m_TotalReceivedBytes - m_LastInBandwidth15sUpdateBytes) * 1000 / delta;
|
|
||||||
m_OutBandwidth15s = (m_TotalSentBytes - m_LastOutBandwidth15sUpdateBytes) * 1000 / delta;
|
|
||||||
m_TransitBandwidth15s = (m_TotalTransitTransmittedBytes - m_LastTransitBandwidth15sUpdateBytes) * 1000 / delta;
|
|
||||||
|
|
||||||
m_LastBandwidth15sUpdateTime = ts;
|
|
||||||
m_LastInBandwidth15sUpdateBytes = m_TotalReceivedBytes;
|
|
||||||
m_LastOutBandwidth15sUpdateBytes = m_TotalSentBytes;
|
|
||||||
m_LastTransitBandwidth15sUpdateBytes = m_TotalTransitTransmittedBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
|
m_UpdateBandwidthTimer->expires_from_now (boost::posix_time::seconds(1));
|
||||||
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
|
m_UpdateBandwidthTimer->async_wait (std::bind (&Transports::HandleUpdateBandwidthTimer, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transports::IsBandwidthExceeded () const
|
int Transports::GetCongestionLevel (bool longTerm) const
|
||||||
{
|
{
|
||||||
auto limit = i2p::context.GetBandwidthLimit() * 1024; // convert to bytes
|
auto bwLimit = i2p::context.GetBandwidthLimit () * 1024; // convert to bytes
|
||||||
auto bw = std::max (m_InBandwidth15s, m_OutBandwidth15s);
|
auto tbwLimit = i2p::context.GetTransitBandwidthLimit () * 1024; // convert to bytes
|
||||||
return bw > limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Transports::IsTransitBandwidthExceeded () const
|
if (tbwLimit == 0 || bwLimit == 0)
|
||||||
{
|
return 100;
|
||||||
auto limit = i2p::context.GetTransitBandwidthLimit() * 1024; // convert to bytes
|
|
||||||
return m_TransitBandwidth > limit;
|
uint32_t bw;
|
||||||
|
uint32_t tbw;
|
||||||
|
if (longTerm)
|
||||||
|
{
|
||||||
|
bw = std::max (m_InBandwidth5m, m_OutBandwidth5m);
|
||||||
|
tbw = m_TransitBandwidth5m;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bw = std::max (m_InBandwidth15s, m_OutBandwidth15s);
|
||||||
|
tbw = m_TransitBandwidth;
|
||||||
|
}
|
||||||
|
auto bwCongestionLevel = 100 * bw / bwLimit;
|
||||||
|
auto tbwCongestionLevel = 100 * tbw / tbwLimit;
|
||||||
|
return std::max (bwCongestionLevel, tbwCongestionLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
|
void Transports::SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg)
|
||||||
|
@ -114,6 +114,17 @@ namespace transport
|
|||||||
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
|
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
|
||||||
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
const int MAX_NUM_DELAYED_MESSAGES = 150;
|
||||||
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
|
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
|
||||||
|
|
||||||
|
const int TRAFFIC_SAMPLE_COUNT = 301; // seconds
|
||||||
|
|
||||||
|
struct TrafficSample
|
||||||
|
{
|
||||||
|
uint64_t Timestamp;
|
||||||
|
uint64_t TotalReceivedBytes;
|
||||||
|
uint64_t TotalSentBytes;
|
||||||
|
uint64_t TotalTransitTransmittedBytes;
|
||||||
|
};
|
||||||
|
|
||||||
class Transports
|
class Transports
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -153,8 +164,7 @@ namespace transport
|
|||||||
uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; };
|
uint32_t GetInBandwidth15s () const { return m_InBandwidth15s; };
|
||||||
uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; };
|
uint32_t GetOutBandwidth15s () const { return m_OutBandwidth15s; };
|
||||||
uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; };
|
uint32_t GetTransitBandwidth15s () const { return m_TransitBandwidth15s; };
|
||||||
bool IsBandwidthExceeded () const;
|
int GetCongestionLevel (bool longTerm) const;
|
||||||
bool IsTransitBandwidthExceeded () const;
|
|
||||||
size_t GetNumPeers () const { return m_Peers.size (); };
|
size_t GetNumPeers () const { return m_Peers.size (); };
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
|
||||||
|
|
||||||
@ -186,6 +196,7 @@ namespace transport
|
|||||||
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
|
||||||
void HandlePeerTestTimer (const boost::system::error_code& ecode);
|
void HandlePeerTestTimer (const boost::system::error_code& ecode);
|
||||||
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
|
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
|
||||||
|
void UpdateBandwidthValues (int interval, uint32_t& in, uint32_t& out, uint32_t& transit);
|
||||||
|
|
||||||
void DetectExternalIP ();
|
void DetectExternalIP ();
|
||||||
|
|
||||||
@ -210,14 +221,15 @@ namespace transport
|
|||||||
|
|
||||||
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
|
std::atomic<uint64_t> m_TotalSentBytes, m_TotalReceivedBytes, m_TotalTransitTransmittedBytes;
|
||||||
|
|
||||||
|
TrafficSample m_TrafficSamples[TRAFFIC_SAMPLE_COUNT];
|
||||||
|
int m_TrafficSamplePtr;
|
||||||
|
|
||||||
// Bandwidth per second
|
// Bandwidth per second
|
||||||
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth;
|
uint32_t m_InBandwidth, m_OutBandwidth, m_TransitBandwidth;
|
||||||
uint64_t m_LastInBandwidthUpdateBytes, m_LastOutBandwidthUpdateBytes, m_LastTransitBandwidthUpdateBytes;
|
// Bandwidth during last 15 seconds
|
||||||
|
|
||||||
// Bandwidth every 15 seconds
|
|
||||||
uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s;
|
uint32_t m_InBandwidth15s, m_OutBandwidth15s, m_TransitBandwidth15s;
|
||||||
uint64_t m_LastInBandwidth15sUpdateBytes, m_LastOutBandwidth15sUpdateBytes, m_LastTransitBandwidth15sUpdateBytes;
|
// Bandwidth during last 5 minutes
|
||||||
uint64_t m_LastBandwidth15sUpdateTime;
|
uint32_t m_InBandwidth5m, m_OutBandwidth5m, m_TransitBandwidth5m;
|
||||||
|
|
||||||
/** which router families to trust for first hops */
|
/** which router families to trust for first hops */
|
||||||
std::vector<i2p::data::FamilyID> m_TrustedFamilies;
|
std::vector<i2p::data::FamilyID> m_TrustedFamilies;
|
||||||
|
@ -240,7 +240,7 @@ namespace tunnel
|
|||||||
|
|
||||||
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
|
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
|
||||||
uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
|
uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
|
||||||
bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
|
int GetCongestionLevel() const { return 100 * m_TransitTunnels.size() / m_MaxNumTransitTunnels; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user