Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

p2p: don't exclusively drop tor/i2p outgoing cxns in idle loop #8330

Merged
merged 1 commit into from
May 27, 2022

Conversation

j-berman
Copy link
Collaborator

Context

update_sync_search runs in the idle loop, checking to see if we have outgoing connections >= the max allowed. If so, a sync'd connection gets dropped so that the daemon can try to connect to nodes that need to sync.

Before this PR

Currently it's comparing the tally of clearnet + tor + i2p outgoing connections to the max of outgoing clearnet peers; but, the tally of clearnet + tor + i2p outgoing peers is usually always going to be greater than the max allowed outgoing clearnet peers. Because of this, it's usually just going to drop a tor or i2p connection right here (because they are last when iterating over all connections), even if the daemon has just 1 outgoing tor or i2p connection.

This seems to be another source of tor/i2p connection reliability issues mentioned in #6938, #6631, #8251.

This PR

This PR makes sure to tally outgoing connections by zone, then compare to the max by zone. If the max peer count set for tor is 10 for example, and there are <10 outgoing tor connections, an outgoing tor connection won't get dropped.

Future PR

I left a couple TODO's to investigate updating the pruning logic correctly. Didn't seem as trivial to figure out, so I left the logic how it currently is (just comparing the tally to the clearnet max).

const auto it = m_max_out_peers.find(zone);
if (it == m_max_out_peers.end())
{
MWARNING(epee::net_utils::zone_to_string(zone) << " max out peers not set, using default");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really want to spam people who set no limit ? I assume this'd do. It maybe a rare case, but it's legitimate. Or is a max always set even if the user doesn't set one ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm missing something but I can't see how it wouldn't get set by a regular user; it should always get set in here even if a user sets a limit of 0 or doesn't include the --out-peers flag: https://github.com/j-berman/monero/blob/299fbd007687534a3b5abb87c2b3f2f596ecdacb/src/p2p/net_node.inl#L388

The only way I believe it wouldn't get set is if a dev is doing something custom where they skip setting it before calling a function that reads it, like in the unit test I updated in this PR (which was hanging before I made this change). I.e. it should always be set explicitly before it's read in normal use.

Maybe there's a better way to handle this? Default to 0 in case it's not set, and maybe only warn once?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not look. If it's impossible with "normal" usage, it's fine by me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not look. If it's impossible with "normal" usage, it's fine by me.

@@ -171,7 +181,7 @@ namespace cryptonote
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
epee::math_helper::once_a_time_seconds<43> m_bad_peer_checker;
std::atomic<unsigned int> m_max_out_peers;
std::unordered_map<epee::net_utils::zone, std::atomic<unsigned int>> m_max_out_peers;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The map should be atomic to match the previous semantics.

@selsta
Copy link
Collaborator

selsta commented May 18, 2022

@j-berman please squash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants