feat(smartcontract, activator): remove multiple tunnel restriction (#2725)#2728
feat(smartcontract, activator): remove multiple tunnel restriction (#2725)#2728bgm-malbeclabs wants to merge 9 commits intomainfrom
Conversation
14a2136 to
231d212
Compare
10c95c2 to
4bda09f
Compare
1efa5cf to
3b7754c
Compare
3b7754c to
42711d2
Compare
There was a problem hiding this comment.
Pull request overview
This PR removes the restriction that allowed only a single tunnel per user, enabling users to maintain both a unicast (IBRL) tunnel and a multicast tunnel simultaneously. The implementation creates separate user accounts per tunnel type while sharing the same client IP, with each tunnel connecting to potentially different devices.
Changes:
- Added
tunnel_endpointfield to User state to track device-side GRE endpoints for multiple concurrent tunnels - Modified CLI and smart contract to support creating multiple user accounts (one per UserType) for the same client IP
- Extended E2E tests to validate concurrent IBRL+multicast tunnel scenarios
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| smartcontract/programs/doublezero-serviceability/src/state/user.rs | Added tunnel_endpoint field and capability helper methods to User struct |
| smartcontract/programs/doublezero-serviceability/src/processors/user/activate.rs | Updated activate processor to handle tunnel_endpoint parameter |
| smartcontract/sdk/rs/src/commands/user/activate.rs | Added tunnel_endpoint parameter to ActivateUserCommand |
| client/doublezero/src/command/connect.rs | Modified connection logic to support multiple user types per IP and device selection |
| client/doublezero/src/dzd_latency.rs | Added exclude_ips parameter to prevent selecting same device for concurrent tunnels |
| e2e/ibrl_multicast_coexistence_test.go | Added comprehensive tests for concurrent IBRL+multicast tunnels |
| activator/src/process/user.rs | Updated to use new capability helper methods and set tunnel_endpoint |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // For single-client scenarios where the same user has both IBRL and multicast, both tunnels | ||
| // use sequential addresses in the 169.254.0.x range (e.g., IBRL on .0/.1, multicast on .2/.3). | ||
| func verifyConcurrentMulticastPIMAdjacency(t *testing.T, log *slog.Logger, device *devnet.Device) { | ||
| // log.Info("==> Verifying concurrent multicast PIM adjacency", "deviceCode", device.Code) |
There was a problem hiding this comment.
Remove commented-out log statement.
| // log.Info("==> Verifying concurrent multicast PIM adjacency", "deviceCode", device.Code) |
|
|
||
| // Give extra time for agent config to be applied to device before verification | ||
| log.Info("==> Waiting for agent config to be applied to device") | ||
| time.Sleep(15 * time.Second) |
There was a problem hiding this comment.
Want to use a poll/eventually check here instead of the 15s sleep?
|
|
||
| // TestE2E_SingleClient_IBRL_Then_Multicast_Publisher tests a single client connecting | ||
| // to IBRL first, then adding multicast publisher capability. | ||
| func TestE2E_SingleClient_IBRL_Then_Multicast_Publisher(t *testing.T) { |
There was a problem hiding this comment.
Want to combine the subscriber and publisher part of these (1 DZD, 2 clients)?
elitegreg
left a comment
There was a problem hiding this comment.
LGTM. Did you verify that doublezero status with two tunnels connected to separate devices still shows that the user is connect to the "best" devices?
| UserType::Multicast => !user.publishers.is_empty(), | ||
| }; | ||
| // Use device public_ip as tunnel_endpoint | ||
| let tunnel_endpoint = device_state.device.public_ip; |
There was a problem hiding this comment.
@elitegreg is this correct or should it use the first ip from device_state.device.dz_prefixes?
There was a problem hiding this comment.
This is correct. He's setting the tunnel endpoint address (what device to connect to).
|
Not included in this PR but potentially relevant: I think this should be changed to: To account for the 4 bytes for the newly added |
Maybe we can add a test for this so it doesn't get forgotten is User grows? |
added a test - good call out. Also added tests to validate go and rust deserialization given the requirement for pubkey to be the last field |
|
|
||
| // Give time for agent to apply the configuration | ||
| log.Info("==> Waiting for agent to apply configuration") | ||
| time.Sleep(10 * time.Second) |
There was a problem hiding this comment.
Do we need this sleep if we're waiting for client tunnels to be up below?
There was a problem hiding this comment.
yea probably not
| ) | ||
| .unwrap(); | ||
|
|
||
| // Use device public_ip as tunnel_endpoint (preserve existing if set) |
There was a problem hiding this comment.
I thought we were separating out the 2nd tunnel endpoint work. If this lands as is, what else is needed to enable that, at least on the serviceability/client front? I'm worried about fracturing support for it across multiple PRs where some are multi-feature.
Summary of Changes
This PR adds the ability from the CLI and the smart contract to add simultaneous tunnels: a single unicast and a single mulitcast tunnel (subscriber or publisher only).
Closes #2735
Testing Verification
pubkeyis always the last deserialized field in both go and rust