Skip to content

feat(simlibp2p): Simulated libp2p Networks#3262

Merged
MarcoPolo merged 21 commits intomasterfrom
marco/simnet
Aug 15, 2025
Merged

feat(simlibp2p): Simulated libp2p Networks#3262
MarcoPolo merged 21 commits intomasterfrom
marco/simnet

Conversation

@MarcoPolo
Copy link
Copy Markdown
Collaborator

@MarcoPolo MarcoPolo commented Apr 3, 2025

This adds a new Simulated Link to extend the Simulated UDP Packet conn. Simulated links can emulate bandwidth and latency over a connection, and can be used to connect two simulated conns together.

This also adds a simulated network helper to easily create a libp2p network and route the various links.

As-is, this works as a simple real-time simulator that may lose precision as computation gets bigger. The real benefit is when this is combined with Go 1.24's new testing/synctest package that allows the simulated network to run as a discrete event simulator. For this use case, only QUIC is supported.

This should serve to replace mocknet with a more accurate environment.

In draft until I clean up the tests a bit and use it a bit more.

@MarcoPolo
Copy link
Copy Markdown
Collaborator Author

hah these tests will be infinitely flaky in CI. but should be perfect once we can use go 1.24's synctest here (as a buildtag, then another command for just tests with those build tags, just as we do with nocover)

@MarcoPolo
Copy link
Copy Markdown
Collaborator Author

Fixed flaky tests by using synctest. Set an extra CI step to run these synctest tests, like we do for NoCover.

@MarcoPolo
Copy link
Copy Markdown
Collaborator Author

cc @Wondertan since you are (were?) a user of mocknet. I'm curious if you would find this useful. It's more realistic than mocknet (you can set bandwidth limits and latencies) and you exercise all the same quic code you would in production. Combining this with synctest means you should be able to run large simulated networks accurately.

@Wondertan
Copy link
Copy Markdown
Contributor

Hey @MarcoPolo, thanks for the ping. Yes, we rely on mocknet and I was hoping that in memory transport is gonna replace the need for it.

I guess the simulated network has even more capabilities with bandwidth/latency tunables as its a lower layer construct, but I wouldnt say this is something we need atm. Although, definetly useful

Afaiu, the synctest would help with flakes for both.

@MarcoPolo
Copy link
Copy Markdown
Collaborator Author

Afaiu, the synctest would help with flakes for both.

Correct

@MarcoPolo MarcoPolo marked this pull request as ready for review May 15, 2025 04:33
@MarcoPolo
Copy link
Copy Markdown
Collaborator Author

I've been playing with this a lot, and I think it is quite useful. Worth merging

Copy link
Copy Markdown
Member

@sukunrt sukunrt left a comment

Choose a reason for hiding this comment

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

Partial review. Mostly looks good except a few nits.

Comment on lines +69 to +70
// When we pass in our own conn manager, we need to close it manually (??)
// TODO: this seems like a bug
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this true? Can you open an issue?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

True. Not sure it's a bug though: https://github.com/libp2p/go-libp2p/blob/master/config/config.go#L412

maybe the lifecycle should be handled here (?)

return m, nil
}),
quicreuse.OverrideListenUDP(func(network string, address *net.UDPAddr) (net.PacketConn, error) {
m.ip.Store(&address.IP)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this mean we will only dial out from the last Listened IP?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes

h, err = libp2p.New(
libp2p.ListenAddrStrings(addr),
QUICSimConnSimpleNet(nw, l.LinkSettings, quicReuseOpts...),
libp2p.DisableIdentifyAddressDiscovery(),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need to disable address discovery?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We likely don't need to. This was probably me reducing the number of goroutines per peer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Just tried it. We do need to disable it because something in that service stalls it.

Going to leave it disabled for now because there are a lot of changes happening there. I'll leave it as a todo to come back to it later.

@MarcoPolo MarcoPolo changed the title feat(simconn): Simulated Networks feat(simlibp2p): Simulated libp2p Networks Aug 13, 2025
@MarcoPolo MarcoPolo merged commit 9f5945e into master Aug 15, 2025
11 checks passed
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