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

Supporting multiple network interfaces #134

Closed

Conversation

PetrichorIT
Copy link
Contributor

This PR changes:

  • adds NodeIdentifiers to decouple node addresses and node identities
  • adds IpSubnets to model different subnets (subnets are not yet supported, see Support multiple network interfaces #132 for progress)
  • adds 1:n mappings between names and IpAddr in dns.rs
  • decouple dns registration from dns lookups (lookups of nonexistent names will no longer return a newly allocated address)
  • integrales reverse dns lookups into ToIpAddr trait

relates to #132

@mcches
Copy link
Contributor

mcches commented Aug 15, 2023

Apologies for the delay in review. I have this queued up for tomorrow morning (08/15).

Copy link
Contributor

@mcches mcches left a comment

Choose a reason for hiding this comment

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

Thanks for getting started on this.

src/dns.rs Outdated
fn to_ip_addr(&self, dns: &Dns) -> Option<IpAddr>;

#[doc(hidden)]
fn to_name(&self, dns: &Dns) -> String;
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to be in the right place given the name of and responsibilities of the trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This part is only temporarily necessary.

The problem is, that we need a name to create a dns mapping. However not all nodes have a name using the
current API since Sim::client expects a impl ToIpAddr. So to get a name for the dns registration,
this trait must temporarily be able to create such a name.

In the future all nodes should have explicit names, independent of their bound addresses, so this will only be temporary. Explicit names could be archived with the proposed builder API for node creation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, so you want to avoid a breaking change in this first change? If so, can you comment that here saying we'll remove this.

I'm inclined to just break things and work in a remote branch if that allows for less churn.

src/dns.rs Outdated Show resolved Hide resolved
Comment on lines +66 to +70
pub enum IpSubnetParsingError {
AddrParseError(AddrParseError),
IntParseError(ParseIntError),
InvalidSubnetSyntax,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the variants necessary? Could we do something simpler like: https://doc.rust-lang.org/std/net/struct.AddrParseError.html ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this parsing implementation will not be used internally and is just for convenience, it's not strictly necessary.
Whether we should stick to a more complex, but more expressiv API or to a simple easy API, idk

src/ip.rs Show resolved Hide resolved

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct NodeIdentifer {
node_name: Arc<str>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if having something like a uuid or a u64 would be better as an internal identifier. I can't think of any places that break with str right now. It seems from the PR title you were considering uuid:

Adding internal UUIDs...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The advantage of using str is the fact, that a NodeIdentifier not only acts as a unique identifier, but can also be used to create tracing spans. So for the time being, I think we should stick to strs.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can have both, right? A uuid does all the network mapping and the host that is active in the sim loop still has a human readable hostname that is set on the span before each tick.

src/ip.rs Outdated Show resolved Hide resolved
@PetrichorIT
Copy link
Contributor Author

So in the spirit of breaking things, this PR fully supports multiple IP subnets, thus multiple bound addresses.

Changes

  • Nodes are identified by a NodeIdentifier, thus they always have a human-readable name
  • All nodes in the simulation are now connected through a list of subnets provided to Builder::ip_subnets
    • The default subnets are (IPv4 192.168.0.0/16 + IPv6 fe80::/64)
    • Each node is assigned an address in every subnet. Addresses can be specified with NodeBuilder::with_addr or are automatically assigned in the node creation process
  • Node creation can now be managed using the NodeBuilder API
    • Sim::client and Sim::host are still supported, but may be removed
    • Sim::client and Sim::host no longer support impl ToIpAddr as input, only impl AsRef<str> is supported, since every node needs are name (provided input is only used as a name, not longer as an addr)
  • DNS changes
    • lookup will no longer be used to register nodes (consider it read-only from now on)
    • Dns::register can be used to register new nodes in the DNS resolution
    • since every node has a name, every node is represented in the DNS struct
    • Reverse lookups now return a node identifier, instead of a string
    • removed trait ToIpAddr, since all queries may return multiple IP address
    • the public API was already using trait ToIpAddrs, so no changes there
    • internally for_pairs was replaced by for_connected_pairs, since only IPs in the same subnet are connected
    • trait ToSocketAddrs can now return multiple addrs
  • Topology
    • Only IPs in the same subnet are connected in the topology
    • endpoints keeps track of all addresses in one subnet, for easier node creation (maybe broadcast in the future?)
  • Host specific
    • Hosts are now bound to multiple addrs
    • net::tcp and net::udp bind / connect to appropriate addresses
  • removed IpVersion and Builder::ip_version
  • removed *_many APIs

Open questions

Builder API

The node builder API is somewhat cumbersome, when creating very simple nodes. Notably build_client or build_host
seems very verbose.

sim.node("my-simple-node").build_client(async { ... });

We could implement the API in such a way to allow these statements,

sim.client("my-simple-node").build(async { ... });
sim.host("my-simple-host").build(async { ... });

but that would use up the fn names Sim::client and Sim::host. Alternatively
we could keep the original Sim::client / Sim::host as simple aliases to the fully qualified form.

@PetrichorIT PetrichorIT changed the title Adding internal UUIDs and internal multi-interface dns mappings Supporting multiple network interfaces Oct 2, 2023
@PetrichorIT PetrichorIT marked this pull request as ready for review October 10, 2023 08:36
@mcches
Copy link
Contributor

mcches commented Nov 17, 2023

I've not gotten the time to review this, many applogies. Another issue just came up that can provide further motivation for prioritizing this work.

See #153

@progwriter
Copy link
Contributor

Hi folks, any update here?

This looks like a super useful feature for modeling systems in networking, where multi-interfaces are a must. Would be great to see this available in turmoil!

@mcches
Copy link
Contributor

mcches commented Jan 22, 2024

Hi folks, any update here?

This looks like a super useful feature for modeling systems in networking, where multi-interfaces are a must. Would be great to see this available in turmoil!

Thanks for checking in. This is low priority at the moment. I've got a decent refactor underway for the net modules and after that is in I can pick up contributing to this or guiding the changes.

Can you please elaborate on your use cases/requirements so that we take them into consideration?

@progwriter
Copy link
Contributor

Can you please elaborate on your use cases/requirements so that we take them into consideration?

At a high level, doing some testing of a network routing protocol. Since the protocol uses a mix of tcp + udp, was hoping to use turmoil to remove networking non-determinism and enable contained testing + fault injection.

Being able to treat routers as having multiple interfaces is pretty important (for link-local and loopback-to-loopback communication)

@mcches
Copy link
Contributor

mcches commented Sep 2, 2024

Closing due to inactivity and because we need to refactor some core things for this to work.

@mcches mcches closed this Sep 2, 2024
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.

3 participants