Skip to content

Commit 5799dc4

Browse files
committed
dataplane: plumb disco and stun to separate streams
Signed-off-by: Nathan Perry <nathan@tailscale.com> Change-Id: Ibf7d20ff1a3ab10e1277e78179285eb46a6a6964
2 parents 173f9e6 + 6cf4e64 commit 5799dc4

5 files changed

Lines changed: 123 additions & 71 deletions

File tree

ts_dataplane/src/async_tokio.rs

Lines changed: 76 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,35 @@ use ts_tunnel::NodeKeyPair;
99

1010
use crate::{EventResult, InboundResult, OutboundResult};
1111

12-
/// Queue for packets leaving the data plane "up" into an overlay transport.
13-
pub type DataplaneToOverlay = mpsc::UnboundedSender<Vec<PacketMut>>;
14-
15-
/// Queue for packets entering the data plane "down" from an overlay transport.
16-
pub type DataplaneFromOverlay = mpsc::UnboundedReceiver<Vec<PacketMut>>;
17-
18-
/// Queue for packets leaving the data plane "down" into an underlay transport.
19-
pub type DataplaneToUnderlay = mpsc::UnboundedSender<(PeerId, Vec<PacketMut>)>;
20-
21-
/// Queue for packets entering the data plane "up" from an underlay transport.
22-
pub type DataplaneFromUnderlay = mpsc::UnboundedReceiver<(PeerId, Vec<PacketMut>)>;
23-
24-
// TODO: wire in overlay/underlay transport traits
12+
// NOTE(npry): this used to have unique types for each queue, but the names got confusing due to
13+
// having to think about the cartesian product of PacketType x QueueDirection x Network
14+
// (this is a "sender handle for receive packets on the overlay", vs. "receive handle for sender
15+
// packets on the overlay", etc.). It wasn't always clear to distinguish what referred to the
16+
// channel direction (sender/receiver) and what referred to the actual traffic kind (packets
17+
// received _from_ the underlay are different from packets sent _to_ the underlay). So now we name
18+
// the packet type here (to/from overlay/underlay) and use separate helper types to make the channel
19+
// directions easier to name.
20+
21+
/// Packet batches sent to an overlay.
22+
pub type ToOverlay = Vec<PacketMut>;
23+
/// Packet batches received from an overlay.
24+
pub type FromOverlay = Vec<PacketMut>;
25+
26+
/// Packet batches sent to an underlay.
27+
pub type ToUnderlay = (PeerId, Vec<PacketMut>);
28+
/// Packet batches received from an underlay.
29+
pub type FromUnderlay = Vec<PacketMut>;
30+
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+
36+
/// Shorthand for a sender channel.
37+
pub type Tx<T> = mpsc::UnboundedSender<T>;
38+
39+
/// Shorthand for a receiver channel.
40+
pub type Rx<T> = mpsc::UnboundedReceiver<T>;
2541

2642
/// Transforms packets to make tailscale happen.
2743
pub struct DataPlane {
@@ -30,8 +46,10 @@ pub struct DataPlane {
3046

3147
transports_changed: tokio::sync::Notify,
3248

33-
underlay_down: DataplaneToUnderlay,
34-
overlay_up: DataplaneToOverlay,
49+
// These are the senders handed out in new_*_transport, just held here so we can clone them, we
50+
// never send to them.
51+
underlay_down: Tx<FromUnderlay>,
52+
overlay_up: Tx<FromOverlay>,
3553

3654
next_underlay_transport: AtomicU32,
3755
next_overlay_transport: AtomicU32,
@@ -42,31 +60,42 @@ struct CoreState {
4260
sync: crate::DataPlane,
4361

4462
/// Queues to write packets to overlay transports.
45-
overlay_transports: HashMap<OverlayTransportId, DataplaneToOverlay>,
63+
overlay_transports: HashMap<OverlayTransportId, Tx<ToOverlay>>,
4664
/// Queues to write packets to underlay transports.
47-
underlay_transports: HashMap<UnderlayTransportId, DataplaneToUnderlay>,
65+
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<DiscoBatch>,
4871
}
4972

5073
/// State that must be held during async polling.
5174
struct PollState {
5275
/// Queue for packets entering the data plane ("coming down") from overlay transports.
53-
from_overlay: DataplaneFromOverlay,
76+
from_overlay: Rx<FromOverlay>,
5477
/// Queue for packets entering the data plane ("coming up") from underlay transports.
55-
from_underlay: DataplaneFromUnderlay,
78+
from_underlay: Rx<FromUnderlay>,
5679
}
5780

5881
impl DataPlane {
5982
/// Create a new data plane for a wireguard node key.
6083
///
6184
/// The caller must configure overlay/underlay output queues for the data plane to be useful,
6285
/// otherwise all it can do is drop packets.
63-
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>) {
6490
let (overlay_up, overlay_down) = mpsc::unbounded_channel();
6591
let (underlay_down, underlay_up) = mpsc::unbounded_channel();
6692

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

69-
Self {
98+
let dp = Self {
7099
underlay_down,
71100
overlay_up,
72101

@@ -77,6 +106,8 @@ impl DataPlane {
77106

78107
core_state: Mutex::new(CoreState {
79108
sync,
109+
stun_out: stun_tx,
110+
disco_out: disco_tx,
80111
overlay_transports: Default::default(),
81112
underlay_transports: Default::default(),
82113
}),
@@ -85,17 +116,15 @@ impl DataPlane {
85116
from_overlay: overlay_down,
86117
from_underlay: underlay_up,
87118
}),
88-
}
119+
};
120+
121+
(dp, disco_rx, stun_rx)
89122
}
90123

91124
/// Allocate a new underlay transport.
92125
pub async fn new_underlay_transport(
93126
&self,
94-
) -> (
95-
UnderlayTransportId,
96-
DataplaneFromUnderlay,
97-
DataplaneToUnderlay,
98-
) {
127+
) -> (UnderlayTransportId, Rx<ToUnderlay>, Tx<FromUnderlay>) {
99128
let id = self
100129
.next_underlay_transport
101130
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
@@ -116,7 +145,7 @@ impl DataPlane {
116145
/// Allocate a new overlay transport.
117146
pub async fn new_overlay_transport(
118147
&self,
119-
) -> (OverlayTransportId, DataplaneToOverlay, DataplaneFromOverlay) {
148+
) -> (OverlayTransportId, Tx<FromOverlay>, Rx<ToOverlay>) {
120149
let id = self
121150
.next_overlay_transport
122151
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
@@ -146,7 +175,7 @@ impl DataPlane {
146175
pub async fn step(&self) {
147176
enum SelectResult {
148177
OverlayDown(Vec<PacketMut>),
149-
UnderlayUp(PeerId, Vec<PacketMut>),
178+
UnderlayUp(Vec<PacketMut>),
150179
TransportsChanged,
151180
Event,
152181
}
@@ -185,10 +214,10 @@ impl DataPlane {
185214
}
186215

187216
underlay_pkts = underlay_up.recv() => {
188-
let (peer_id, underlay_pkts) = underlay_pkts.unwrap();
189-
tracing::trace!(%peer_id, n_underlay_pkts = underlay_pkts.len());
217+
let underlay_pkts = underlay_pkts.unwrap();
218+
tracing::trace!(n_underlay_pkts = underlay_pkts.len());
190219

191-
SelectResult::UnderlayUp(peer_id, underlay_pkts)
220+
SelectResult::UnderlayUp(underlay_pkts)
192221
}
193222

194223
_ = self.transports_changed.notified() => {
@@ -214,8 +243,21 @@ impl DataPlane {
214243

215244
(Some(to_peers), Some(loopback))
216245
}
217-
SelectResult::UnderlayUp(_peer_id, underlay_up) => {
218-
let InboundResult { to_local, to_peers } = core.sync.process_inbound(underlay_up);
246+
SelectResult::UnderlayUp(underlay_up) => {
247+
let InboundResult {
248+
to_local,
249+
to_peers,
250+
disco,
251+
stun,
252+
} = core.sync.process_inbound(underlay_up);
253+
254+
if !disco.is_empty() && core.disco_out.send(disco).is_err() {
255+
tracing::warn!("disco packets dropped: no receiver");
256+
}
257+
258+
if !stun.is_empty() && core.stun_out.send(stun).is_err() {
259+
tracing::warn!("stun packets dropped: no receiver");
260+
}
219261

220262
(Some(to_peers), Some(to_local))
221263
}

ts_dataplane/src/lib.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,26 @@ impl DataPlane {
101101
&mut self,
102102
packets: impl IntoIterator<Item = PacketMut>,
103103
) -> InboundResult {
104-
let ts_tunnel::RecvResult { to_local, to_peers } = self.wireguard.recv(packets);
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+
123+
let ts_tunnel::RecvResult { to_local, to_peers } = self.wireguard.recv(wireguard);
105124

106125
let to_local = to_local
107126
.into_iter()
@@ -200,7 +219,12 @@ impl DataPlane {
200219
prev.cancel();
201220
}
202221

203-
InboundResult { to_local, to_peers }
222+
InboundResult {
223+
to_local,
224+
to_peers,
225+
disco,
226+
stun,
227+
}
204228
}
205229

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

265295
/// The result of processing an event.

ts_runtime/src/dataplane.rs

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ use kameo::{
44
actor::ActorRef,
55
message::{Context, Message},
66
};
7-
use tokio::sync::mpsc;
8-
use ts_packet::PacketMut;
9-
use ts_transport::{OverlayTransportId, PeerId, UnderlayTransportId};
7+
use ts_dataplane::async_tokio::{FromOverlay, FromUnderlay, Rx, ToOverlay, ToUnderlay, Tx};
8+
use ts_transport::{OverlayTransportId, UnderlayTransportId};
109

1110
use crate::{
1211
Error,
@@ -17,18 +16,6 @@ use crate::{
1716
src_filter::SourceFilterState,
1817
};
1918

20-
/// Queue for packets sent from the overlay to the dataplane.
21-
pub type OverlayToDataplane = mpsc::UnboundedSender<Vec<PacketMut>>;
22-
23-
/// Queue for packets entering the overlay from the dataplane.
24-
pub type OverlayFromDataplane = mpsc::UnboundedReceiver<Vec<PacketMut>>;
25-
26-
/// Queue for packets leaving the underlay to the dataplane.
27-
pub type UnderlayToDataplane = mpsc::UnboundedSender<(PeerId, Vec<PacketMut>)>;
28-
29-
/// Queue for packets entering an underlay from the dataplane.
30-
pub type UnderlayFromDataplane = mpsc::UnboundedReceiver<(PeerId, Vec<PacketMut>)>;
31-
3219
pub struct DataplaneActor {
3320
dataplane: Arc<ts_dataplane::async_tokio::DataPlane>,
3421
task: tokio::task::JoinHandle<()>,
@@ -45,18 +32,14 @@ impl DataplaneActor {
4532
#[message]
4633
pub async fn new_overlay_transport(
4734
&self,
48-
) -> (OverlayTransportId, OverlayToDataplane, OverlayFromDataplane) {
35+
) -> (OverlayTransportId, Tx<FromOverlay>, Rx<ToOverlay>) {
4936
self.dataplane.new_overlay_transport().await
5037
}
5138

5239
#[message]
5340
pub async fn new_underlay_transport(
5441
&self,
55-
) -> (
56-
UnderlayTransportId,
57-
UnderlayFromDataplane,
58-
UnderlayToDataplane,
59-
) {
42+
) -> (UnderlayTransportId, Rx<ToUnderlay>, Tx<FromUnderlay>) {
6043
self.dataplane.new_underlay_transport().await
6144
}
6245
}
@@ -66,9 +49,8 @@ impl kameo::Actor for DataplaneActor {
6649
type Error = Error;
6750

6851
async fn on_start(env: Self::Args, slf: ActorRef<Self>) -> Result<Self, Self::Error> {
69-
let dataplane = Arc::new(ts_dataplane::async_tokio::DataPlane::new(
70-
env.keys.node_keys,
71-
));
52+
let (dataplane, ..) = ts_dataplane::async_tokio::DataPlane::new(env.keys.node_keys);
53+
let dataplane = Arc::new(dataplane);
7254

7355
env.subscribe::<PeerRouteUpdate>(&slf).await?;
7456
env.subscribe::<SelfRouteUpdate>(&slf).await?;

ts_runtime/src/multiderp.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use kameo::{
1111
};
1212
use tokio::{sync::watch, task::JoinSet};
1313
use ts_control::DerpRegion;
14+
use ts_dataplane::async_tokio::{FromUnderlay, Rx, ToUnderlay, Tx};
1415
use ts_derp::RegionId;
1516
use ts_keys::{NodeKeyPair, NodePublicKey};
1617
use ts_transport::{
@@ -19,7 +20,7 @@ use ts_transport::{
1920

2021
use crate::{
2122
Env, Error,
22-
dataplane::{DataplaneActor, NewUnderlayTransport, UnderlayFromDataplane, UnderlayToDataplane},
23+
dataplane::{DataplaneActor, NewUnderlayTransport},
2324
derp_latency::DerpLatencyMeasurement,
2425
peer_tracker::{PeerDb, PeerState},
2526
};
@@ -156,8 +157,8 @@ async fn run_derp_once(
156157
id: RegionId,
157158
region: &DerpRegion,
158159
keys: NodeKeyPair,
159-
to_dataplane: &UnderlayToDataplane,
160-
from_dataplane: &mut UnderlayFromDataplane,
160+
to_dataplane: &Tx<FromUnderlay>,
161+
from_dataplane: &mut Rx<ToUnderlay>,
161162
home_derp_rx: &mut watch::Receiver<bool>,
162163
peer_db: &RwLock<Option<Arc<PeerDb>>>,
163164
) -> Result<(), ts_derp::Error> {
@@ -210,7 +211,7 @@ async fn run_derp_once(
210211

211212
tracing::trace!(parent: &span, %peer_id, len = pkts.len(), "packet from derp server");
212213

213-
let Ok(()) = to_dataplane.send((peer_id, pkts)) else {
214+
let Ok(()) = to_dataplane.send(pkts) else {
214215
tracing::error!(parent: &span, "underlay receive channel closed");
215216
break;
216217
};

ts_runtime/src/netstack_actor.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@ use netstack::{
99
netcore::{Channel, NetstackControl},
1010
};
1111
use tokio::task::JoinSet;
12+
use ts_dataplane::async_tokio::{FromOverlay, Rx, ToOverlay, Tx};
1213
use ts_packet::PacketMut;
1314

14-
use crate::{
15-
Error,
16-
dataplane::{OverlayFromDataplane, OverlayToDataplane},
17-
env::Env,
18-
};
15+
use crate::{Error, env::Env};
1916

2017
pub struct NetstackActor {
2118
_joinset: JoinSet<()>,
@@ -26,8 +23,8 @@ impl kameo::Actor for NetstackActor {
2623
type Args = (
2724
Env,
2825
netstack::netcore::Config,
29-
OverlayToDataplane,
30-
OverlayFromDataplane,
26+
Tx<FromOverlay>,
27+
Rx<ToOverlay>,
3128
);
3229
type Error = Error;
3330

0 commit comments

Comments
 (0)