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

kad: Manually setting client or server mode #4074

Closed
dariusc93 opened this issue Jun 15, 2023 · 16 comments · Fixed by #4132
Closed

kad: Manually setting client or server mode #4074

dariusc93 opened this issue Jun 15, 2023 · 16 comments · Fixed by #4132

Comments

@dariusc93
Copy link
Member

Description

Apart of #3877 was allowing the kad protocol to automatically select client or server mode based on if there is an external address, however there should be a function that would allow the node to override the automatic selection, specifically if the node wish to remain as a client and eventually be able to switch to being a server.

Motivation

Outlined in #3877 (comment), nodes may wish to only be a client and query nodes for records with the option to switch to being a server at a later point.

Another case may be in environments where it wouldnt be suitable to run in server mode (eg mobile or embedded environments, running on network with limited datacap, etc). With the current implementation, they would be forced into server mode unless the protocol itself is disabled, which may not be desirable, especially if the environment can change later on during runtime.

Open questions

  1. When reimplementing Kademlia::set_mode, should it override any automatic detection that is done based on external address or should we have a configuration flag where you can use one or the other but not both?

Are you planning to do it yourself in a pull request?

Maybe

@thomaseizinger
Copy link
Contributor

When reimplementing Kademlia::set_mode, should it override any automatic detection that is done based on external address or should we have a configuration flag where you can use one or the other but not both?

We could have set_explicit_mode(Option<Mode>) where None means "do it automatically".

@dariusc93
Copy link
Member Author

When reimplementing Kademlia::set_mode, should it override any automatic detection that is done based on external address or should we have a configuration flag where you can use one or the other but not both?

We could have set_explicit_mode(Option<Mode>) where None means "do it automatically".

I actually like that idea.

@stormshield-pj50
Copy link
Contributor

Maybe you could follow the go implementation that uses 3 modes:

  • ModeAuto
  • ModeClient
  • ModeServer
  • ModeAutoServer

@dariusc93
Copy link
Member Author

Maybe you could follow the go implementation that uses 3 modes:

* ModeAuto

* ModeClient

* ModeServer

* ModeAutoServer

If we did follow the go implementation, would we even need ModeAutoServer?

@thomaseizinger
Copy link
Contributor

Maybe you could follow the go implementation that uses 3 modes:

  • ModeAuto
  • ModeClient
  • ModeServer
  • ModeAutoServer

Minus ModeAutoServer that is essentially what I am proposing, but with a dedicated enum instead of composing Option.

I think I'd prefer composition because it keeps the ConnectionHandler unaware of how the mode is chosen.

@thomaseizinger
Copy link
Contributor

I think the fact that we arrived at the same solution without looking at what go-libp2p does is a good validation.

@joshuef
Copy link
Contributor

joshuef commented Jun 27, 2023

I'm continuing looking into upgrading to 0.52, and I think we're butting up against this. Our local testnets and CI machines, where we normally run ~30 nodes to validate basic functionality are not working as it seems every node is a `Client.

I just wanted to check if there's some other recommend way to setup these test networks so we can force Mode::Server? Or (i suspect) will we need to wait for resolution on this issue?

🙇

@mxinden
Copy link
Member

mxinden commented Jun 27, 2023

I just wanted to check if there's some other recommend way to setup these test networks so we can force Mode::Server?

@joshuef calling Swarm::add_external_address will make sure your node runs in Mode::Server. See changelog entry.

https://github.com/libp2p/rust-libp2p/blob/master/protocols/kad/CHANGELOG.md#0440

@joshuef
Copy link
Contributor

joshuef commented Jun 27, 2023

Awesome, that's got us going 💪 . Thanks very much 🙇

@dariusc93
Copy link
Member Author

I'm continuing looking into upgrading to 0.52, and I think we're butting up against this. Our local testnets and CI machines, where we normally run ~30 nodes to validate basic functionality are not working as it seems every node is a `Client.

What i usually do to get around that would be to add the addresses produced by SwarmEvent::NewListenAddr and remove them with SwarmEvent::ExpiredListenAddr and SwarmEvent::ListenerClosed. Not preferable doing this though but in testing that will work fine

@thomaseizinger
Copy link
Contributor

thomaseizinger commented Jun 27, 2023

I'm continuing looking into upgrading to 0.52, and I think we're butting up against this. Our local testnets and CI machines, where we normally run ~30 nodes to validate basic functionality are not working as it seems every node is a `Client.

What i usually do to get around that would be to add the addresses produced by SwarmEvent::NewListenAddr and remove them with SwarmEvent::ExpiredListenAddr and SwarmEvent::ListenerClosed. Not preferable doing this though but in testing that will work fine

That is only correct if your local interface is in a fact routable from your other nodes, i.e. if you are in the same subnet.

Unless you are utilizing something like AutoNAT, it is likely better to just add a configuration option to your binary where users have to specify the public IP of the node and you statically add using Swarm::add_external_address.

@thomaseizinger
Copy link
Contributor

thomaseizinger commented Jun 27, 2023

Or (i suspect) will we need to wait for resolution on this issue?

There are no objections against this idea mentioned. Contributions implementing that are most certainly welcomed!

@vladlabs
Copy link

vladlabs commented Jun 28, 2023

We are facing same issue as @joshuef. Kademlia related tests are now failing. BTW we are utilizing memory transport for such tests.

@thomaseizinger
Copy link
Contributor

We are facing same issue as @joshuef. Kademlia related tests are now failing. BTW we are utilizing memory transport for such tests.

And the solution mentioned above does not work?

@vladlabs
Copy link

Well it helped. But this is not a good solution considering that in our code Swarm is incapsulated.

I personally do not like any auto configurations by default at all (especially if there is no obvious way to change such behavior).
Also I think that auto configs should be enabled only manually by calling some method like do_autoconfig_magic()

@thomaseizinger
Copy link
Contributor

thomaseizinger commented Jun 28, 2023

Well it helped.

Great to hear!

But this is not a good solution considering that in our code Swarm is incapsulated.

Can you elaborate why? Whether or not kademlia should operate in server-mode (i.e. answer inbound requests) literally depends on whether or not your node is publicly reachable and that is configured by Swarm::add_external_address (or using a system of libp2p-identify and libp2p-autonat). If your node is not reachable, it should not advertise kademlia, otherwise you'll poison the routing table of your peers! I don't follow why configuring the external address of a Swarm is not a good solution.

I personally do not like any auto configurations by default at all (especially if there is no obvious way to change such behavior). Also I think that auto configs should be enabled only manually by calling some method like do_autoconfig_magic()

I doubt you actually mean that. By that logic:

  • Your phone shouldn't automatically change the timezone when you fly to another country
  • Your AC shouldn't stop cooling once your room reaches the desired temperature
  • Your car shouldn't turn the headlights on when you drive into a tunnel
  • ...

Defaults matter, we just need to find the correct trigger for a behaviour. I am fairly certain that the presence of an external address is the correct trigger for kademlia server mode. And client-mode must be the default, otherwise your routing table will be full of unreachable peers and you'll have a terrible DHT performance.

There is already a proposal for a solution on how to force a particular mode. Contributions for that are highly welcome!

@mergify mergify bot closed this as completed in #4132 Jul 4, 2023
mergify bot pushed a commit that referenced this issue Jul 4, 2023
The current implementation in Kademlia relies on an external address to determine if it should be in client or server mode. However there are instances where a node, which may know an external address, wishes to remain in client mode and switch to server mode at a later point.

This PR introduces `Kademlia::set_mode`, which accepts an `Option<Mode>` that would allow one to set `Mode::Client` for client mode, `Mode::Server` for server mode, or `None` to determine if we should operate as a client or server based on our external addresses.

Resolves #4074.

Pull-Request: #4132.
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 a pull request may close this issue.

6 participants