Skip to content

Commit d6406d6

Browse files
committed
dataplane: plumb disco and stun to separate streams
Signed-off-by: Nathan Perry <nathan@tailscale.com> Change-Id: Ibf7d20ff1a3ab10e1277e78179285eb46a6a6964
1 parent 2c65bf6 commit d6406d6

4 files changed

Lines changed: 72 additions & 10 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ts_dataplane/src/async_tokio.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ pub type ToUnderlay = (PeerId, Vec<PacketMut>);
2828
/// Packet batches received from an underlay.
2929
pub type FromUnderlay = Vec<PacketMut>;
3030

31+
/// A batch of disco packets received from an underlay transport.
32+
pub type DiscoBatch = Vec<PacketMut>;
33+
/// A batch of stun packets received from an underlay transport.
34+
pub type StunBatch = Vec<PacketMut>;
35+
3136
/// Shorthand for a sender channel.
3237
pub type Tx<T> = mpsc::UnboundedSender<T>;
3338

@@ -58,6 +63,11 @@ struct CoreState {
5863
overlay_transports: HashMap<OverlayTransportId, Tx<ToOverlay>>,
5964
/// Queues to write packets to underlay transports.
6065
underlay_transports: HashMap<UnderlayTransportId, Tx<ToUnderlay>>,
66+
67+
/// Send handle for disco packets received from underlays.
68+
disco_out: Tx<DiscoBatch>,
69+
/// Send handle for stun packets received from underlays.
70+
stun_out: Tx<StunBatch>,
6171
}
6272

6373
/// State that must be held during async polling.
@@ -73,13 +83,19 @@ impl DataPlane {
7383
///
7484
/// The caller must configure overlay/underlay output queues for the data plane to be useful,
7585
/// otherwise all it can do is drop packets.
76-
pub fn new(my_key: NodeKeyPair) -> Self {
86+
///
87+
/// The second and third elements of the return tuple are output queues for disco and
88+
/// STUN messages, respectively.
89+
pub fn new(my_key: NodeKeyPair) -> (Self, Rx<DiscoBatch>, Rx<StunBatch>) {
7790
let (overlay_up, overlay_down) = mpsc::unbounded_channel();
7891
let (underlay_down, underlay_up) = mpsc::unbounded_channel();
7992

93+
let (disco_tx, disco_rx) = mpsc::unbounded_channel();
94+
let (stun_tx, stun_rx) = mpsc::unbounded_channel();
95+
8096
let sync = crate::DataPlane::new(my_key);
8197

82-
Self {
98+
let dp = Self {
8399
underlay_down,
84100
overlay_up,
85101

@@ -90,6 +106,8 @@ impl DataPlane {
90106

91107
core_state: Mutex::new(CoreState {
92108
sync,
109+
stun_out: stun_tx,
110+
disco_out: disco_tx,
93111
overlay_transports: Default::default(),
94112
underlay_transports: Default::default(),
95113
}),
@@ -98,7 +116,9 @@ impl DataPlane {
98116
from_overlay: overlay_down,
99117
from_underlay: underlay_up,
100118
}),
101-
}
119+
};
120+
121+
(dp, disco_rx, stun_rx)
102122
}
103123

104124
/// Allocate a new underlay transport.
@@ -230,7 +250,20 @@ impl DataPlane {
230250
(Some(to_peers), Some(loopback))
231251
}
232252
SelectResult::UnderlayUp(underlay_up) => {
233-
let InboundResult { to_local, to_peers } = core.sync.process_inbound(underlay_up);
253+
let InboundResult {
254+
to_local,
255+
to_peers,
256+
disco,
257+
stun,
258+
} = core.sync.process_inbound(underlay_up);
259+
260+
if !disco.is_empty() && core.disco_out.send(disco).is_err() {
261+
tracing::warn!("disco packets dropped: no receiver");
262+
}
263+
264+
if !stun.is_empty() && core.stun_out.send(stun).is_err() {
265+
tracing::warn!("stun packets dropped: no receiver");
266+
}
234267

235268
(Some(to_peers), Some(to_local))
236269
}

ts_dataplane/src/lib.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,27 @@ impl DataPlane {
101101
&mut self,
102102
packets: impl IntoIterator<Item = PacketMut>,
103103
) -> InboundResult {
104+
let (wireguard, disco, stun) = packets.into_iter().fold(
105+
(vec![], vec![], vec![]),
106+
|(mut wg, mut disco, mut stun), pkt| {
107+
let ident = PacketIdent::identify(pkt.as_ref());
108+
109+
match ident.ty {
110+
PacketType::Disco => {
111+
disco.push(pkt);
112+
}
113+
PacketType::StunBinding => {
114+
stun.push(pkt);
115+
}
116+
PacketType::Wireguard | PacketType::Unknown => wg.push(pkt),
117+
}
118+
119+
(wg, disco, stun)
120+
},
121+
);
122+
104123
let ts_tunnel::RecvResult { to_local, to_peers } =
105-
self.wireguard.recv(Instant::now(), packets);
124+
self.wireguard.recv(Instant::now(), wireguard);
106125

107126
let to_local = to_local
108127
.into_iter()
@@ -201,7 +220,12 @@ impl DataPlane {
201220
prev.cancel();
202221
}
203222

204-
InboundResult { to_local, to_peers }
223+
InboundResult {
224+
to_local,
225+
to_peers,
226+
disco,
227+
stun,
228+
}
205229
}
206230

207231
/// Return the next time at which [`DataPlane::process_events`] must be called.
@@ -261,6 +285,12 @@ pub struct InboundResult {
261285
pub to_local: HashMap<OverlayTransportId, Vec<PacketMut>>,
262286
/// Encrypted packets to be sent to wireguard peers by the underlay.
263287
pub to_peers: HashMap<(UnderlayTransportId, PeerId), Vec<PacketMut>>,
288+
289+
/// Encrypted disco packets to be handled externally.
290+
pub disco: Vec<PacketMut>,
291+
292+
/// STUN packets to be handled externally.
293+
pub stun: Vec<PacketMut>,
264294
}
265295

266296
/// The result of processing an event.

ts_runtime/src/dataplane.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ impl kameo::Actor for DataplaneActor {
4242
type Error = Error;
4343

4444
async fn on_start(env: Self::Args, slf: ActorRef<Self>) -> Result<Self, Self::Error> {
45-
let dataplane = Arc::new(ts_dataplane::async_tokio::DataPlane::new(
46-
env.keys.node_keys.clone(),
47-
));
45+
let (dataplane, ..) = ts_dataplane::async_tokio::DataPlane::new(env.keys.node_keys.clone());
46+
let dataplane = Arc::new(dataplane);
4847

4948
env.subscribe::<PeerRouteUpdate>(&slf).await?;
5049
env.subscribe::<SelfRouteUpdate>(&slf).await?;

0 commit comments

Comments
 (0)